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

目录
  • 自定义注解+springAop参数非空校验
    • 新建注解类@interface ParamsVerify
    • 利用springAop来实现切面
    • 新建一个切面类
  • 使用注解统一校验参数非空
    • 1. 待校验类
    • 2. 注解类
    • 3. 校验

自定义注解+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

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

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

(0)

相关推荐

  • Spring AOP实现功能权限校验功能的示例代码

    实现功能权限校验的功能有多种方法,其一使用拦截器拦截请求,其二是使用AOP抛异常. 首先用拦截器实现未登录时跳转到登录界面的功能.注意这里没有使用AOP切入,而是用拦截器拦截,因为AOP一般切入的是service层方法,而拦截器是拦截控制器层的请求,它本身也是一个处理器,可以直接中断请求的传递并返回视图,而AOP则不可以. 1.使用拦截器实现未登录时跳转到登录界面的功能 1.1 拦截器SecurityInterceptor package com.jykj.demo.filter; import

  • 详解spring注解式参数校验

    一般入参我们都会转为vo对象.那么直接在对象的属性上注解即可. 其实spring用的是hibernate的validator. 步骤 1.配置spring.xml <mvc:annotation-driven /> 2.配置自己的validate类. <bean id="validateArgsAOP" class="com.my.validate.aop.ValidateArgsAOP"/> <aop:config> <a

  • 详解使用Spring AOP和自定义注解进行参数检查

    引言 使用SpringMVC作为Controller层进行Web开发时,经常会需要对Controller中的方法进行参数检查.本来SpringMVC自带@Valid和@Validated两个注解可用来检查参数,但只能检查参数是bean的情况,对于参数是String或者Long类型的就不适用了,而且有时候这两个注解又突然失效了(没有仔细去调查过原因),对此,可以利用Spring的AOP和自定义注解,自己写一个参数校验的功能. 代码示例 注意:本节代码只是一个演示,给出一个可行的思路,并非完整的解决

  • SpringBoot中自定义注解实现参数非空校验的示例

    前言 由于刚写项目不久,在写 web 后台接口时,经常会对前端传入的参数进行一些规则校验,如果入参较少还好,一旦需要校验的参数比较多,那么使用 if 校验会带来大量的重复性工作,并且代码看起来会非常冗余,所以我首先想到能否通过一些手段改进这点,让 Controller 层减少参数校验的冗余代码,提升代码的可阅读性. 经过阅读他人的代码,发现使用 annotation 注解是一个比较方便的手段,SpringBoot 自带的 @RequestParam 注解只会校验请求中该参数是否存在,但是该参数是

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

    目录 自定义注解+springAop参数非空校验 新建注解类@interface ParamsVerify 利用springAop来实现切面 新建一个切面类 使用注解统一校验参数非空 1. 待校验类 2. 注解类 3. 校验 自定义注解+springAop参数非空校验 自定义注解,来对对应的方法进行入参校验,为空返回参数错误 新建注解类@interface ParamsVerify @Target(ElementType.METHOD)//枚举,表示注解可能出现在的地方 @Retention(R

  • 使用注解@Validated和BindingResult对入参进行非空校验方式

    目录 注解@Validated和BindingResult对入参非空校验 @Validated 和 BindingResult 使用遇到的坑 注解@Validated和BindingResult对入参非空校验 在项目当中少不了入参校验,服务器和浏览器互不信任,不能因为前端加入参判断了后台就不处理了,这样是不对的. 比如前台传过来一个对象作为入参参数,这个对象中有些属性允许为空,有些属性不允许为空.那么你还在使用if()else{}进行非空判断吗?不妨尝试下使用注解,可以使用@Validated和

  • 浅谈C#9.0新特性之参数非空检查简化

    参数非空检查是缩写类库很常见的操作,在一个方法中要求参数不能为空,否则抛出相应的异常.比如: public static string HashPassword(string password) { if(password is null) { throw new ArgumentNullException(nameof(password)); } ... } 当异常发生时,调用者很容易知道是什么问题.如果不加这个检查,可能就会由系统抛出未将对象引用为实例之类的错误,这不利于调用者诊断错误. 由

  • java自定义注解实现前后台参数校验的实例

    其实是可以通过@Constraint来限定自定义注解的方法. @Constraint(validatedBy = xxxx.class) 下面是我做的 java自定义注解实现前后台参数校验 的代码示例 对这个感兴趣的,请好好看,好好学: package sonn.sonnannotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.anno

  • SpringBoot通过自定义注解实现参数校验

    目录 1. 为什么要进行参数校验 2. 如何实现参数校验 3. 注解实现参数校验 4. 自定义注解实现参数校验 1. 为什么要进行参数校验 在后端进行工作时,需要接收前端传来的数据去数据库查询,但是如果有些数据过于离谱,我们就可以直接把它pass掉,不让这种垃圾数据接触数据库,减小数据库的压力. 有时候会有不安分的人通过一些垃圾数据攻击咱们的程序,让咱们的服务器或数据库崩溃,这种攻击虽然低级但不得不防,就像QQ进行登录请求时,它们向后端发送 账号=123,密码=123 的数据,一秒钟还发1w次,

  • 使用自定义注解进行restful请求参数的校验方式

    目录 自定义注解进行restful请求参数的校验 1.首先我们使用@interface定义一个注解 2.实现注解实现类(和@interface定义的注解在同一个包下) 3.在需要校验的对象的字段上加上@ByteLength注解 springboot小技巧:restful接口参数校验,自定义校验规则 restful风格接口参数校验 自定义参数校验注解方法 自定义注解进行restful请求参数的校验 在使用springmvc开发的时候,我们通常会在controller中的方法参数实体类中加上@Not

  • 使用@Valid+BindingResult进行controller参数校验方式

    目录 @Valid+BindingResult进行controller参数校验 Controller层方法的参数校验 全局统一异常拦截器 @Valid+BindingResult进行controller参数校验 由于controller是调用的第一层,经常参数校验将在这里完成,常见有非空校验.类型校验等,常见写法为以下伪代码: public void round(Object a){ if(a.getLogin() == null){ return "手机号不能为空!"; } } 但是

  • 校验非空的注解@NotNull如何取得自定义的message

    目录 校验非空的注解@NotNull如何取得自定义的message 用法:定义一个全局异常处理 @NotNull 等注解的简单使用 2.3以前则不需要引入maven包 Controller层 附上 部分注解 校验非空的注解@NotNull如何取得自定义的message 由于项目表单需要校验字段过多,一个一个去判空太麻烦,所以用了@NotNull注解,字段为空会抛出MethodArgumentNotValidException异常. 接下来要取得@NotNull(message="自定义异常&qu

随机推荐