使用注解实现入参参数校验(springboot+AOP)的一种实现方式_使用注解标识输入参数-程序员宅基地

技术标签: spring  java  aop  反射  

使用注解实现入参参数校验

工作场景中,参数校验必不可少,最近利用自定义注解实现入参参数校验,在入参校验方面,有不错的扩展性,可重用性。

效果

接口调用,如果入参是实体类,就在实体类的变量上方标记。
在这里插入图片描述
实体类例子
在这里插入图片描述

返回结果
在这里插入图片描述

实现

先自定义一个注解,用来标记需要校验的参数。

@Target({
    ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.CONSTRUCTOR, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Examine {
    
    String value() default "isNull";
}

利用注解的标记,定义一个aop,实现对参数的获取和校验

@Component
@Aspect
public class ExamineAop {
    

    @Around("@annotation(examine)")
    public Object paramCheck(ProceedingJoinPoint joinPoint, Examine examine) throws Throwable {
    
    	//获取方法传入参数数组
        Object[] args = joinPoint.getArgs();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Parameter[] parameters = signature.getMethod().getParameters();
        //循环数组
        for (int i = 0; i < parameters.length; i++) {
    
            Parameter parameter = parameters[i];
            //处理类似String Integer的类
            if (isPrimite(parameter.getType())) {
    
            //获取参数上是否带有自定义注解,不为空则代表有
                Examine annotation = parameter.getAnnotation(Examine.class);
                if (annotation == null) {
    
                    continue;
                }
                //判断传入参数是否为null
                if (args[i] == null) {
    
                //抛出自定义异常,会被我的全局异常处理捕获,返回固定的返回体
                    throw new ExamineException();
                }
                //利用反射,调用自定义注解中的参数方法
                Method verificationUtil = VerificationUtil.class.getMethod(annotation.value(), Object.class);
                Object invoke = verificationUtil.invoke(null, args[i]);
                if (invoke.equals(false)) {
    
                    throw new ExamineException();
                }
                continue;
            }
			//处理自定义实体类中带有自定义注解的成员变量,验证方法相同
            Class<?> paramClazz = parameter.getType();
            Object arg = Arrays.stream(args).filter(ar -> paramClazz.isAssignableFrom(ar.getClass())).findFirst().get();
            Field[] declaredFields = paramClazz.getDeclaredFields();
            for (Field field : declaredFields) {
    
                field.setAccessible(true);
                Examine annotation = field.getAnnotation(Examine.class);
                if (annotation == null) {
    
                    continue;
                }
                if (args[i] == null) {
    
                    throw new ExamineException();
                }
                Method verificationUtil = VerificationUtil.class.getMethod(annotation.value(), Object.class);
                Object invoke = verificationUtil.invoke(null, field.get(arg));
                if (invoke.equals(false)) {
    
                    throw new ExamineException();
                }
                continue;
            }
        }
        return joinPoint.proceed();
    }

    /**
     * 判断是否为基本类型:包括String
     *
     * @param clazz clazz
     * @return true:是; false:不是
     */
    private boolean isPrimite(Class<?> clazz) {
    
        return clazz.isPrimitive() || clazz == String.class;
    }
}

验证工具类,在aop实现类中利用反射调用,在本类中可以添加自己的验证,在注解中,传入方法名字,即可调用方法来验证参数,如(Examine(isPhone)String phone)。

public class VerificationUtil {
    
    /**
     * 验证是否手机号
     *
     * @param phone
     * @return
     */
    public static Boolean isPhone(Object phone) {
    
        String pattern = "^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})|(17[0-9]{1}))+\\d{8})?$";
        return phone.toString().matches(pattern);
    }

    /**
     * 验证是否为空
     *
     * @param value
     * @return
     */
    public static Boolean isNull(Object value) {
    
        return value != null || String.valueOf(value).length() > 0;
    }
 }


结尾

在本程序中还有异常类和全局捕获异常没有写出,百度一大堆。
如有错误和bug,欢迎指正。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dsfdgfhdsad/article/details/119352674

智能推荐

SIT2596,可替代LM2596,40V 输入 150KHz 3A 降压型电源转换器-程序员宅基地

文章浏览阅读655次。SIT2596 封装形式包括标准的 5 脚 TO-220 封装(DIP)和 5 脚 TO-263 表贴封装(SMD)。输出电压,电压输出范围在 1.2V-37V,输入电压最高可达 40V,输出电流可达 3A;SIT2596 是一款降压型开关电压调节芯片,可固定输出 3.3V、5V、12V,也可根据需要调节。准电感,这更优化了 SIT2596 的使用,极大地简化了开关电源电路的设计,节约了外围的成本。可选固定输出 3.3V、5V、12V 电压或输出电压可调;优异的线性调整率和负载调整率;_替代lm2596

直接扩频通信系统工作原理_直接序列扩频码本的概念-程序员宅基地

文章浏览阅读973次。接收端的本振信号与发射端射频载波相差一个中频,接收端收到的宽带射。波形相乘,得到复合信号,实现信号频谱的展宽,展宽后的信号再调制射频载波发送出去。一般扩频调制时一个信息码包含一个周期的伪码,用扩频后的复合信号对载波进。在发端输入的信息与扩频码发生器产生的伪随机码序列(这里使用的是 m 序列)进行。直接序列扩频,就是直接用高码率的扩频码序列在发端去扩展信号的频谱,在收端用相。的扩频码序列进行波形相乘,实现相关解扩,再经信息解调,恢复出原始信号。同的扩频码去解扩,把展宽的扩频信号还原成原始的基带信号。_直接序列扩频码本的概念

EMV规范(八)——持卡人验证(CVM)二_9f34 emv tag-程序员宅基地

文章浏览阅读2.4k次。现在到了TVR和CVM Results部分了。TVR是Terminal Verification Results,也就是终端验证的结果,包括了脱机数据认证,持卡人认证,处理限制等等是否成功。所以只要交易结果不是我们期望的,我们总是先拿TVR出来看看是哪里出了问题。CVM Results是持卡人认证结果,针对CVM。一. TVRtag:‘95’ length:5 bytes第..._9f34 emv tag

2023国赛信息安全管理与评估样题及规程解读,2024京东最新网络安全面试真题解析-程序员宅基地

文章浏览阅读845次,点赞25次,收藏30次。还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!【完整版领取方式在文末!!

阿里云服务器绑定域名及IIS配置访问网站_阿里云服务器部署iis-程序员宅基地

文章浏览阅读436次。注:阿里云网站申请需要进行IPC备案,如果不通过备案仅可本机IP地址访问,其它IP地址访问失败或是提示未进行备案。解决办法:开始菜单-服务器管理器-管理(M)-添加角色和功能-按步骤添加Web服务器(IIs)注:云服务器选择的阿里云windows系统,同时使用的是IIS进行服务器配置。解决办法:清理浏览器缓存后刷新,或是更换成其它浏览器。问题2:关于更改网站内容,刷新仍然保存旧界面。问题1:关于云服务器中没有IIS管理器。_阿里云服务器部署iis

使用vscode开发C#+unity没有代码提示问题_vs code没有c#的提示-程序员宅基地

文章浏览阅读1.9k次,点赞4次,收藏2次。最近在使用VS Code遇到了 OmniSharp 的各种报错导致没有了代码提示。这个问题是由于本身C#的更新版本造成的。1.在设置里搜索 Use Modern Net,取消勾选,重启 VS Code!2.改了依然有错误,提示或Could not locate MSBuild instance to register with OmniSharp.C# extension插件回到1.24.4,同时把Visual Studio Code Editor包升级到1.2.5又可以了。_vs code没有c#的提示

随便推点

简单图形界面初学 :tkinter+阿里云接口+爬虫,实现全国天气查询_tkinter显示爬虫七天天气折线图-程序员宅基地

文章浏览阅读1.1k次。 可能需要的环境: Python 3.6官网下载 需要下载的第三方库:requests 其余为python自带不需要下载 首先看下效果图具体写作过程参考b站视频传送门:GUI天气预报接下来实现过程,首先创建窗口,设置标题,布局窗口,设置标签,按钮,就直接粘贴代码:如果对创建窗口的函数不熟悉:请点击python中tkinter的使用(控件整理)(一..._tkinter显示爬虫七天天气折线图

JavaScript 逐点突破之单线程与异步,作为前端必知必会-程序员宅基地

文章浏览阅读638次,点赞12次,收藏28次。优点:实现比较简单,执行环境相对单纯缺点:只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段 Javascript 代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。为了解决这个问题,JavaScript 语言将任务的执行模式分为两种:同步和异步。

Python 学习路线思维导图, 经典收藏!-程序员宅基地

文章浏览阅读271次。目前为止,我总结了Python的知识体系,并且暂时包括了十五章内容。 Python简介 基础知识 列表和元祖 字符串 字典 条件、循环和其他语句 抽象 更加抽象 异常 魔法方法、属性和迭代器 模块 文件和流 图形用户界面 数据库支持 网络编程 ...

PHP 系统学习-程序员宅基地

文章浏览阅读640次。define("god","123",true);// 定义常量(true 为不区分大小写)constant("god")."";//输出常量echo (define("god").""); //输出常量是否被定义 预定义变量echo $_SERVER["SERVER_ADDR"];//服务器ip地址 echo $_SERVER["SERVER_NAME"];//

反常积分发散-程序员宅基地

文章浏览阅读6.3k次。反常积分与暇点反常积分又叫广义积分,是对普通定积分的推广,指含有无穷上限/下限,或者被积函数含有瑕点的积分,前者称为无穷限广义积分,后者称为瑕积分(又称无界函数的反常积分)。如果函数f(x)在点a的一个邻域内无界,那么点a称为函数f(x)的瑕点(也称无界间断点)。无界函数的反常积分又称为瑕积分。反常积分的敛散性参考:https://zhuanlan.zhihu.com/p/101310338..._反常积分发散

项目——交通灯管理系统_城市道路十字路口信号灯控制系统,模拟实现十字路口的信号控制功能。要实现基-程序员宅基地

文章浏览阅读2.1k次。---------------------JavaEE+Android开发、Java培训、期待与您交流! ---------------------- 交通灯管理系统一.交通灯管理项目的需求 模拟实现十字路口的交通灯管理系_城市道路十字路口信号灯控制系统,模拟实现十字路口的信号控制功能。要实现基