吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1327|回复: 1
收起左侧

[Java 转载] 自定义注解对接口传入参数进行空判断

[复制链接]
jiaowojiangge 发表于 2022-7-19 12:23

前言:

本来项目是Springboot的,用的是 validation 对接口传入的参数进行判空处理,自己测试没得问题(测试服务器上也没得问题),但是技术经理最后需要打成war包(springboot多为jar包)部署到Tomcat上,但是发现打包为war包之后validation就突然失效了,略微查找之后没得找到问题根源,当时由于时间紧张,@RequestParam不能满足需求,就自己写了自定义的注解通过切面暂时实现,感觉挺有意思,就记录一下:直接上代码

一. 判断入参不为空的注解

1.1 : 定义注解 StringNullRegex (名字自己随意取)
import java.lang.annotation.*;

/**
 *   @Description         判断接口入参不能为空的自定义注解
 *   home.php?mod=space&uid=686208 江
 */
@Target(ElementType.METHOD)   // 作用于方法
@Retention(RetentionPolicy.RUNTIME)
public home.php?mod=space&uid=593715 StringNullRegex {

}
1.2 : 注解功能实现 StringNullRegexAspect
import com.example.waitdemo.utils.HttpResult;
import com.example.waitdemo.utils.StringNullUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;

/**
 * @Description       StringNullRegex注解的实现
 * @ClassName         StringNullRegexAspect
 */
@Aspect     // 切面
@Component  // 表示这是一个bean,由Spring进行管理 或者说输入spring
public class StringNullRegexAspect {

    // 配置织入点   @annotation 为自定义的注解的位置(路径)
    @Pointcut("@annotation(com.example.waitdemo.config.StringNullRegex)")
    public void annotationPointcut() {
    }

    /**
     *  
     */
    @Around("annotationPointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        // 通过方法获取参数及其内容的 map
        Map<String, String> parameter = getParameter(method, joinPoint.getArgs());
        // 对参数进行判空处理
        for (String key : parameter.keySet()) {
            if (StringNullUtil.isEmpty(parameter.get(key))){
                return HttpResult.newError(key + "参数不能为空!");
            }
        }

        return joinPoint.proceed();
    }

        // 获取参数及对应数据
        private Map<String, String> getParameter(Method method, Object[] args) {
        Map<String, String> argList = new  HashMap<>();
        Parameter[] parameters = method.getParameters();

        for (int i = 0; i < parameters.length; i++) {

            argList.put(parameters[i].getName(), String.valueOf(args[i]));
        }
        if (argList.size() == 0) {
            return null;
        } else if (argList.size() == 1) {
            return argList;
        } else {
            return argList;
        }
    }

}

二. 判断入参为对象 不为空的注解

2.1 : 定义注解 NotNotNull (名字自己随意取,这里是为了和 NotNull 区分开)
/**
 * @Description     配合 ClassNotNull 进行实体类验证
 *                  作用于实体类的字段上边
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)   // 作用于字段
public @interface NotNotNull {
        String  message() default "";
}
2.2 : 定义注解 ClassNotNull
/**
 * @Description        配合 NotNotNull 实体类验证
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassNotNull {
}
2.3 : 注解功能实现 ClassNotNull
import com.example.waitdemo.utils.HttpResult;
import com.example.waitdemo.utils.StringNullUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * @Description
 * @ClassName ClassNotNullAspect
 */
@Aspect     // 切面
@Component  // 表示这是一个bean,由Spring进行管理 或者说输入spring
public class ClassNotNullAspect {

    // 配置织入点
    @Pointcut("@annotation(com.example.waitdemo.config.ClassNotNull)")
    public void ClassNotNullPointcut() {
    }

    @Around("ClassNotNullPointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        //System.out.println("---------");
        Object arg = joinPoint.getArgs()[0];
        Parameter[] parameters = method.getParameters();
        //获取class对象
        Class<?> aClass = parameters[0].getType();

        //获取当前对象所有属性  使用带Declared的方法可访问private属性
        Field[] declaredFields = aClass.getDeclaredFields();
        for(Field field:declaredFields){
            //开启访问权限
            field.setAccessible(true);
            //使用此方法 field.get(Object obj) 可以获取  当前对象这个列的值
            Object o = field.get(arg);
            Annotation annotation = field.getDeclaredAnnotation(NotNotNull.class);
            //如果没有设置当前注解 不用校验
            if(annotation == null){
                continue;
            }
            //如果设置了当前注解,但是没有值,抛出异常
            if(StringNullUtil.isEmpty(String.valueOf(o))){
                //获取注解接口对象
                NotNotNull notNull = (NotNotNull)annotation;
                if(StringNullUtil.isNotEmpty(notNull.message())){
                    System.out.println("notNull.message() = " + notNull.message());
                    //设置了注解message值 直接返回
                                        // 这里又两种返回方法 ,
                                        // 1: 通过自定义错误,然后进行全局拦截
                    //throw new ClassNotNullException(notNull.message());
                                        // 2: 自己包装的返回参数 (通过枚举等)
                    return HttpResult.newError(notNull.message());
                }else{
                    System.out.println("field.getName() = " + field.getName()+" is null");
                    //没有设置可以拼接
                    //throw new ClassNotNullException(field.getName()+" is null");
                    return HttpResult.newError(field.getName()+" is null");
                }
            }
        }
        return joinPoint.proceed();
    }
}

自定义的注解已经完成,准备使用

三. 定义用户类:

自定义注解 NotNotNull  的使用位置

import com.example.waitdemo.config.NotNotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * TODO
 *
 * @ClassName User
 * @Author
 * @Date 
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component
public class UserProperty {

    @NotNotNull(message = "名字不能为空!")
    private String name;
    private Integer age;
    @NotNotNull(message = "qq is null")
    private Integer qq;

}
四. controller 中使用自定义注解
/**
 * @ClassName WaitController
 */
@Log4j2
@RestController
@RequestMapping("/wait")
public class WaitController {

    @RequestMapping(value = "/test_string_null",method = RequestMethod.GET)
    @StringNullRegex
    public HttpResult testStringNullRegex(String name, Integer age){

        System.out.println("名字 = " + name);

        System.out.println("年龄 = " + age);

        return HttpResult.newSuccess();
    }

    @RequestMapping(value = "/testTwo",method = RequestMethod.GET)
    @ClassNotNull
    public HttpResult testTwo(UserProperty userProperty){

        String name = userProperty.getName();
        System.out.println("名字 = " + name);
        Integer age = userProperty.getAge();
        System.out.println("年龄 = " + age);
        Integer qq = userProperty.getQq();
        System.out.println("QQ = " + qq);

        return HttpResult.newSuccess();
    }
}

其他问题:

到这里基本的功能实现了,但是新问题:

  1. 不支持 多参数中可以为空,可以不为空的问题

解释: 这个没有用到就没得测试,对象注解中算实现了,但是不太合格,通过自定义注解应该也可以实现,感兴趣的可以试一下^_^

免费评分

参与人数 2吾爱币 +5 热心值 +2 收起 理由
Sunry0831 + 1 谢谢@Thanks!
苏紫方璇 + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

maozzs 发表于 2022-7-22 20:15
钻研的精神是可佳的。不过相比于spring框架自带的非空注解。这么做的优势在哪里哟~
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-27 12:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表