Spring boot实现基于注解的aop面向切面编程

news2024/11/26 4:28:14

Spring boot实现基于注解的aop面向切面编程

背景

从最开始使用Spring,AOP和IOC的理念就深入我心。正好,我需要写一个基于注解的AOP,被这个注解修饰的参数和属性,就会被拿到参数并校验参数。

一,引入依赖

当前spring boot版本为2.7.18,我引入的aspectjweaver版本为1.9.5。

     <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.5</version>
      </dependency>

二,写注解

这个注解用来修饰方法,相当于一个切点,加上这个注解,这个方法就被被aop执行。

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamInterceptor {
    boolean checkParam() default true;
}

在这里插入图片描述
这个注解是用来修饰参数和属性的。被修饰的参数和属性在aop中会通过反射取出数据并判断

@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VerifyParam {

    int min() default -1;

    int max() default -1;

    boolean required() default false;

    VerifyRegexEnum regex() default VerifyRegexEnum.NO;
}

这个是用到的VerifyRegexEnum 枚举类

@AllArgsConstructor
@Getter
public enum VerifyRegexEnum {
    NO("", "不校验"),
    IP("^((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})$", "ip地址"),
    POSITIVE_INTEGER("^\\d+$", "正整数"),
    NUMBER_LETTER_UNDER_LINE("\\w+$", "数字字母下划线"),
    PHONE("^1[3-9]\\d{9}$", "手机号"),
    EMAIL("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$", "邮箱"),
    ID_CARD("^\\d{17}(\\d|x|X)$", "身份证"),
    PASSWORD("^[a-zA-Z0-9]{6,20}$", "密码"),
    MONEY("^\\d+(\\.\\d+)?$", "金额"),
    ;

    private String regex;
    private String desc;
    public static boolean isMatch(String regex, String str) {
        return str.matches(regex);
    }

}

三,编写切面aspect

该切面类就实现了,对参数和属性的校验。

@Aspect
@Component
@Slf4j
public class CdesAspect {

    @Before("@annotation(com.cdes.annotation.ParamInterceptor)")
    public void before(JoinPoint point) {
        Object[] args = point.getArgs();
        Method method = ((MethodSignature) point.getSignature()).getMethod();
        log.info("参数校验,方法名:{}",method.getName());
        ParamInterceptor paramInterceptor = method.getAnnotation(ParamInterceptor.class);
        if (paramInterceptor == null ) {
            return;
        }
        if(!paramInterceptor.checkParam()){
            return;
        }
        try{
            checkParam(method,args);
        }catch (BizException e){
            throw new BizException("400",e.getErrorMsg());
        }catch (Exception e){
            throw new BizException("400",e.getMessage());
        }
    }

    private void checkParam(Method method, Object[] args) throws IllegalAccessException {
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            Object paramValue = args[i];

            VerifyParam paramAnnotation = parameter.getAnnotation(VerifyParam.class);
            //取方法参数上的注解,如果有,则校验参数,如果没有,取该参数的属性,看是否有该注解
            if (paramAnnotation != null) {
                if(paramAnnotation.required() && paramValue == null){
                    throw new BizException( "400",parameter.getName()+":参数不能为空");
                }
                if(paramAnnotation.max() != -1){
                    if (paramValue.toString().length() > paramAnnotation.max()) {
                        throw new BizException( "400",parameter.getName()+":参数长度不能超过"+paramAnnotation.max());
                    }
                }
                if(paramAnnotation.min() != -1){
                    if (paramValue.toString().length() < paramAnnotation.min()) {
                        throw new BizException( "400",parameter.getName()+":参数长度不能小于"+paramAnnotation.min());
                    }
                }
                if(paramAnnotation.regex() != null && paramAnnotation.regex() != VerifyRegexEnum.NO){
                    if(!VerifyRegexEnum.isMatch(paramAnnotation.regex().getRegex(),paramValue.toString())){
                        throw new BizException( "400",parameter.getName()+":参数不符合正则表达式");
                    }
                }
            }else{
                //取属性上的注解,看是否需要校验
                Field[] fields = paramValue.getClass().getDeclaredFields();
                if(fields == null || fields.length == 0){
                    continue;
                }
                for (Field field : fields) {
                    field.setAccessible(true);
                    VerifyParam ann = field.getAnnotation(VerifyParam.class);
                    if(ann == null){
                        continue;
                    }
                    Object filedValue = field.get(paramValue);
                    if(ann.required() && filedValue == null){
                        throw new BizException( "400",field.getName()+":属性不能为空");
                    }
                    if(ann.max() != -1){
                        if (filedValue.toString().length() > ann.max()) {
                            throw new BizException( "400",field.getName()+":属性长度不能超过"+ann.max());
                        }
                    }
                    if(ann.min() != -1){
                        if (filedValue.toString().length() < ann.min()) {
                            throw new BizException( "400",field.getName()+":属性长度不能小于"+ann.min());
                        }
                    }
                    if(ann.regex() != null && ann.regex() != VerifyRegexEnum.NO){
                        if(!VerifyRegexEnum.isMatch(ann.regex().getRegex(),filedValue.toString())){
                            throw new BizException( "400",field.getName()+":属性不符合正则表达式");
                        }
                    }
                }
            }
        }
    }
}

四,使用

controller中的login方法加上了ParamInterceptor注解,然后这个方法的入参LoginDTO中的属性加上了VerifyParam注解
在这里插入图片描述

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginDTO {
    @VerifyParam(regex = VerifyRegexEnum.PHONE)
    private String phone;
    @VerifyParam(regex = VerifyRegexEnum.PASSWORD)
    private String password;
    @VerifyParam(required = true)
    private String verifyCode;
    @VerifyParam(required = true)
    private String codeId;
}

总结

经过测试,校验参数功能正常。可以看到,spring boot的aop功能使用起来还是相当简单的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1805757.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何用群晖当异地组网服务器?

在当今信息化时代&#xff0c;远程通信成为了企业和个人之间不可或缺的一部分。特别是对于跨地区的通信需求&#xff0c;一个可靠的异地组网服务器是必不可少的。而群晖&#xff08;Synology&#xff09;作为一款功能强大的网络存储设备&#xff0c;可以被用作办公室或家庭的异…

力扣1712.将数组分成三个子数组的方案数

力扣1712.将数组分成三个子数组的方案数 确定左边界的值 然后二分求右边界的范围 右边界处的前缀和满足 2*s[i] < s[r] < (s[n] s[i]) / 2 int s[100010];const int N 1e97;class Solution {public:int waysToSplit(vector<int>& nums) {int n nums.siz…

Vue12-计算属性

一、姓名案例 1-1、插值语法实现 1、v-bind v-bind的问题&#xff1a; 所以&#xff1a;v-bind是单向绑定。 2、v-model 解决v-bind的问题。 3、输出全名 方式一&#xff1a; 方式二&#xff1a; 需求优化&#xff1a;全名中的姓氏&#xff0c;只取输入框中的前三位&#xf…

MATLAB数学建模——数据拟合

文章目录 一、简介二、多项式拟合&#xff08;一&#xff09;指令介绍&#xff08;二&#xff09;代码 三、指定函数拟合&#xff08;一&#xff09;指令介绍&#xff08;二&#xff09;代码 一、简介 曲线拟合也叫曲线逼近&#xff0c;主要要求拟合的曲线能合理反映数据的基本…

AtCoder Beginner Contest 357 A~E(F更新中...)

A.Sanitize Hands(模拟) 题意 有 n n n个外星人排队对手消毒&#xff0c;其中第 i i i个外星人有 H i H_i Hi​只手需要消毒&#xff0c;已知消毒液共能使用 M M M次&#xff0c;每次可以对一只手消毒&#xff0c;问&#xff1a;总共有多少个外星人的全部手都完成消毒了。 分…

Docker高级篇之Docker网络

文章目录 1. Docker Network简介2. Docker 网络模式3. Docker 网络模式之bridge4. Docker 网络模式之host5. Docker 网络模式之none6. Docker 网络模式之container7. Docker 网络模式之自定义网络模式 1. Docker Network简介 从Docker的架构和运作流程来看&#xff0c;Docker是…

normalizing flows vs 直方图规定化

normalizing flows名字的由来 The base density P ( z ) P(z) P(z) is usually defined as a multivariate standard normal (i.e., with mean zero and identity covariance). Hence, the effect of each subsequent inverse layer is to gradually move or “flow” the da…

【报文数据流中的反压处理】

报文数据流中的反压处理 1 带存储体的反压1.1 原理图1.2 Demo 尤其是在NP芯片中&#xff0c;经常涉及到报文的数据流处理&#xff1b;为了防止数据丢失&#xff0c;和各模块的流水处理&#xff1b;因此需要到反压机制&#xff1b; 反压机制目前接触到的有两种&#xff1a;一是基…

【Python入门与进阶】Anaconda环境配置

目录 1.Conda换源 2.pip换源 3.环境管理 4.可视化界面完成上述操作 1.Conda换源 1.1.打开Anaconda Powershell Prompt 1.2.在界面中输入以下命名&#xff08;加入清华源并设置搜索优先级&#xff09;&#xff1a; conda config --add channels https://mirrors.ustc.edu.…

android集成百度文心一言实现对话功能,实战项目讲解,人人都能拥有一款ai应用

大家好&#xff0c;今天给大家讲解下如何实现一个基于百度文心一言的app功能&#xff0c;app内部同时集成了讯飞的语音识别。本文适用于有android基础的小伙伴阅读&#xff0c;文章末尾放上本项目用到的全部实例代码&#xff0c;在使用前请务必看完本文章。 先来给大家看看效果…

鲜为人知的英伟达创始人:早早退出,身价不如黄仁勋零头

内容提要 普里姆因为婚姻纠纷等个人生活的干扰无法专注在工作上&#xff0c;在成立公司的10年后&#xff0c;也就是2003年宣布退休离开英伟达&#xff0c;并在2006年出售剩余的所有英伟达股份&#xff0c;过上不与外界联系、离群索居的生活&#xff0c;在家中鼓捣着如何“拯救…

【深度学习】深度学习之巅:在 CentOS 7 上打造完美Python 3.10 与 PyTorch 2.3.0 环境

【深度学习】深度学习之巅&#xff1a;在 CentOS 7 上打造完美Python 3.10 与 PyTorch 2.3.0 环境 大家好 我是寸铁&#x1f44a; 总结了一篇【深度学习】深度学习之巅&#xff1a;在 CentOS 7 上打造完美Python 3.10 与 PyTorch 2.3.0 环境✨ 喜欢的小伙伴可以点点关注 &#…

【MySQL】(基础篇三) —— 创建数据库和表

管理数据库和表 管理数据库 创建数据库 在MySQL中&#xff0c;创建数据库的SQL命令相对简单&#xff0c;基本语法如下&#xff1a; CREATE DATABASE 数据库名;如果你想避免在尝试创建已经存在的数据库时出现错误&#xff0c;可以添加 IF NOT EXISTS 子句&#xff0c;这样如…

transformer - 注意力机制

Transformer 的注意力机制 Transformer 是一种用于自然语言处理任务的模型架构&#xff0c;依赖于注意力机制来实现高效的序列建模。注意力机制允许模型在处理一个位置的表示时&#xff0c;考虑输入序列中所有其他位置的信息&#xff0c;而不仅仅是前面的几个位置。这种机制能…

学会python——九九乘法表+斐波那契数列(python实例一)

目录 1、认识Python 2、环境与工具 2.1 python环境 2.2 pycharm编译 2、九九乘法表 2.1 代码构思 2.2 代码示例 2.3 运行结果 3、斐波那契数列 3.1 代码构思 3.2 代码示例 3.3 运行结果 1、认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对…

Mac清洁神器CleanMyMac2024一键轻松解决电脑垃圾问题

【CleanMyMac】苹果mac电脑垃圾清理软件 大家好&#xff01;今天我要给大家种草一个超级好用的苹果mac电脑垃圾清理软件&#xff0c;那就是 CleanMyMac。相信很多人都遇到过电脑运行速度变慢、存储空间不足的问题&#xff0c;而这款软件就是解决这些问题的救星&#xff01;让我…

UML交互图-协作图

概述 协作图和序列图都表示出了对象间的交互作用&#xff0c;但是它们侧重点不同。序列图清楚地表示了交互作用中的时间顺序&#xff0c;但没有明确表示对象间的关系。协作图则清楚地表示了对象间的关系&#xff0c;但时间顺序必须从顺序号获得。序列图常常用于表示方案&#…

物理机宕机后,虚拟机出现(无响应),虚拟机无法开机

物理机宕机后&#xff0c;虚拟机出现&#xff08;无响应&#xff09;&#xff0c;虚拟机无法开机 解决方案&#xff1b;看存储池中&#xff0c;文件是否还存在&#xff1b;如果存在&#xff0c;新建虚拟机&#xff0c;加载存储池中的磁盘&#xff0c;重启虚拟机就可以了 重新创…

matlab---app

一 基础 标签和信号灯没有回调函数 clc,clear,close all %清理命令区、工作区&#xff0c;关闭显示图形 warning off %消除警告 feature jit off %加速代码运行 ysw{i}i %循环赋值 celldisp(ysw) %显示元胞数组ysw.y1{1}[1,2] …

【机器学习300问】108、什么是多项式回归模型?

一、多项式回归是什么 &#xff08;1&#xff09;举例说明 假设你经营着一家农场&#xff0c;想要根据土地面积来预测作物的产量。如果你只用线性模型&#xff08;即&#xff09;&#xff0c;你可能会发现它并不足以描述实际的产量情况&#xff0c;因为实际产量可能会随着土地…