使用自定义注解+springAop实现参数非空校验方式

 更新时间:2021年09月28日 12:12:35   作者:DRNB666  
这篇文章主要介绍了使用自定义注解+springAop实现参数非空校验方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

自定义注解+springAop参数非空校验

自定义注解,来对对应的方法进行入参校验,为空返回参数错误

新建注解类@interface ParamsVerify

@Target(ElementType.METHOD)//枚举,表示注解可能出现在的地方
@Retention(RetentionPolicy.RUNTIME)//运行时保留注解
@Documented//生成api文档时会看到此注解,可加可不加
public @Interface ParamsVerify(){
//注解类修饰符必须是public 如果不写会默认public    
   String[] params() default "";//传入方法的参数
}

利用springAop来实现切面

利用springAop,我们可以把除业务核心代码以外的,需要重复进行的操作来统一处理,例如打印日志,参数校验等等,以切面的方式来进行,一个切面,由切点、通知(增强)来组成

增强就是对Aop管理的代码来通过动态代理来添加额外的逻辑(代码),动态代理有两种实现方式,一种是通过jdk,一种是通过cglib,springboot中默认是使用cglib来进行动态代理的;而切点(ponitCut),是多个连接点组成的一个切点,通常通过表达式来指向程序中一个定义的位置,来告知springAop启动的范围

//这个切点定义为使用该注解的方法都可以执行该切面类里的通知
@Pointcut("@annotation(com.xy.utlis.annotations.TestA)")

新建一个切面类

通知方法执行顺序

环绕–前置—后置

@Aspect//声明该类是一个切面类
@Component//声明该类交由spring管理
public class testAImpl {
    
    /** 定义切点,使用该TestA注解的方法 */
    @Pointcut("@annotation(com.xy.utlis.annotations.TestA)")
    public void addAdvice(){
    }
   
    @Aroud("addAdvice")//环绕通知  另外还有@Before @After
    public Object test(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕方法开始执行....");
        //获取所有参数名
        String[] parameterNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
        //获取所有参数值
        Object[] args = joinPoint.getArgs();
        //获取当前注解下的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        //根据当前方法获取注解
        TestA annotation = signature.getMethod().getAnnotation(TestA.class);
        String[] names = annotation.params();//获得注解参数
        Map<String, Object> params = params(joinPoint);
        for (String name : names) {
            Object o = params.get(name);
            if(null==o||"".equals(o)){
                System.err.println(MessageFormat.format("参数名为{0}的值为null",name));
                return false;
            }
        }
        System.out.println("环绕方法结束执行....");
        return joinPoint.proceed();//继续正常执行方法
    }
}

写一个接口来测试是否成功

@PostMapping("test")
@TestA(params={"name","age","sex"})//表明这三个参数是必填的
public void test(String name,String age,String sex){
 System.out.println("ok");
}

发送post请求,只携带name

在这里插入图片描述

检测到参数为null,打印错误信息

在这里插入图片描述

这里可以自定义返回异常值或者其他处理了

带上完整参数请求接口

在这里插入图片描述

成功放行

在这里插入图片描述

使用注解统一校验参数非空

可修改做工具类

代码:

1. 待校验类

public class User { 
    @NonNull(content = "姓名不能为空", minLen = 2, maxLen = 100)
    private String name; 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

2. 注解类

@Documented
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface NonNull { 
    String name() default ""; 
    String content() default ""; 
    int maxLen() default 50; 
    int minLen() default 1;
}

3. 校验

    public void test() {
        User user = new User();
        user.setName("老王");
        try {
            valid(user);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
 
    private <T> void valid(T user) throws IllegalAccessException, InvocationTargetException {
        Class<?> clazz = user.getClass();
        Field[] declaredFields = clazz.getDeclaredFields();
        Method[] methods = clazz.getMethods();
        for (Field field : declaredFields) {
            validParams(user, methods, field);
        }
        System.out.println("==========参数校验通过=========");
    }
 
    private <T> void validParams(T user, Method[] methods, Field field) throws IllegalAccessException, InvocationTargetException {
        NonNull annotation = field.getAnnotation(NonNull.class);
        String fieldName;
        if (StringUtils.isNotBlank(annotation.name())) {
            fieldName = annotation.name();
        } else {
            fieldName = field.getName();
        }
        for (Method method : methods) {
            if (("get" + fieldName).toLowerCase().equals(method.getName().toLowerCase())) {
                Object getMethodResult = method.invoke(user, null);
                if (getMethodResult == null) {
                    System.out.println("==========非Null校验失败=========");
                    throw new IllegalArgumentException("[" + annotation.content() + "]为null");
                }
                if (getMethodResult instanceof String) {
                    if (StringUtils.isBlank(String.valueOf(getMethodResult))) {
                        System.out.println("==========非空校验失败=========");
                        throw new IllegalArgumentException("[" + annotation.content() + "]为空");
                    }
                    System.out.println(fieldName + "长度:" + String.valueOf(getMethodResult).length());
                    if (String.valueOf(getMethodResult).length() > annotation.maxLen()) {
                        System.out.println("==========长度超出指定范围=========");
                        throw new IllegalArgumentException("[" + fieldName + "]长度超出");
                    }
                    if (String.valueOf(getMethodResult).length() < annotation.minLen()) {
                        System.out.println("==========长度小于指定范围=========");
                        throw new IllegalArgumentException("[" + fieldName + "]长度不够");
                    }
                }
            }
        }
    }

结果参考:

name长度:2

==========参数校验通过=========

name长度:2

==========长度小于指定范围=========

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 监听器获取Spring配置文件的方法

    监听器获取Spring配置文件的方法

    这篇文章主要为大家详细介绍了监听器获取Spring配置文件的方法,很实用的方法,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • CentOS安装jdk的三种方法

    CentOS安装jdk的三种方法

    这篇文章主要为大家详细介绍了CentOS安装jdk的三种方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02
  • SpringBootWeb 入门了解 Swagger 的具体使用

    SpringBootWeb 入门了解 Swagger 的具体使用

    这篇文章主要介绍了SpringBootWeb 入门了解 Swagger 的具体使用,Swagger 框架可以根据已经实现的方法或者类,通过页面的方式直观清晰的查看或者进行测试该方法,需要的朋友可以参考下
    2024-08-08
  • SpringBoot配置使Mybatis打印SQL执行时的实际参数值操作

    SpringBoot配置使Mybatis打印SQL执行时的实际参数值操作

    这篇文章主要介绍了SpringBoot配置使Mybatis打印SQL执行时的实际参数值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 利用idea生成webservice客户端超详解步骤(wsdl文件的使用)

    利用idea生成webservice客户端超详解步骤(wsdl文件的使用)

    这篇文章主要给大家介绍了关于利用idea生成webservice客户端超详解步骤,第一次接触webservice,从采坑到采坑,算是了解了一些,明白了一些,文中通过代码以及图文介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • macOS上使用gperftools定位Java内存泄漏问题及解决方案

    macOS上使用gperftools定位Java内存泄漏问题及解决方案

    这篇文章主要介绍了macOS上使用gperftools定位Java内存泄漏问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • java代码实现双向链表

    java代码实现双向链表

    这篇文章主要为大家详细介绍了java代码实现双向链表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • Intellij IDEA创建spring-boot项目的图文教程

    Intellij IDEA创建spring-boot项目的图文教程

    本文通过图文并茂的形式给大家介绍了Intellij IDEA创建spring-boot项目的教程,本文给大家介绍的非常详细,具有参考借鉴价值,需要的朋友参考下吧
    2018-01-01
  • Java实现一个小说采集程序的简单实例

    Java实现一个小说采集程序的简单实例

    下面小编就为大家带来一篇Java实现一个小说采集程序的简单实例。小编觉得挺不错的, 现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • Java Web之限制用户多处登录实例代码

    Java Web之限制用户多处登录实例代码

    本篇文章主要介绍了Java Web之限制用户多处登录实例代码,可以限制单个用户在多个终端登录。非常具有实用价值,需要的朋友可以参考下。
    2017-03-03

最新评论