AOP的另类用法 (权限校验自定义注解)
👳我亲爱的各位大佬们好😘😘😘
♨️本篇文章记录的为 AOP的另类用法 (权限校验&&自定义注解) 相关内容,适合在学Java的小白,帮助新手快速上手,也适合复习中,面试中的大佬🙉🙉🙉。
♨️如果文章有什么需要改进的地方还请大佬不吝赐教❤️🧡💛
👨🔧 个人主页 : 阿千弟
🔥 上期内容👉👉👉 : “速通“ 老生常谈的HashMap [实现原理&&源码解读]
前言 :
告别了OOP编程, 迎来了一个新的AOP编程时代👍👍👍, 最近有同学问我AOP除了写日志还能干什么, 其实AOP能干的事情挺多的, 可能只是他们写的代码中暂时用不到. 其实如果当我们写一些简单的程序的时候, SpringSecurity完全用不到的时候, 就可以使用AOP与自定义注解来为角色的访问权限进行鉴定, 绝对比Security更轻量👉👉👉.
文章目录
- 前言 :
- 自定义注解
- AOP回顾
- 基本概念
- 声明一个切入点
- 切入点指示器(PCD)
- 基本通知
- 通知的参数
- AOP整合自定义注解校验接口权限
- 引入依赖
- 自定义注解
- 定义切面
- AopController
- 测试结果
自定义注解
我们在接触框架的时候经常会用到注解, 但是我们自己自定义注解的情况比较少, 一般都是配合切面编程使用
自定义一个注解非常简单, 它就和创建一个接口一样, 如果我们创建的是一个接口的话, 那么就用interface关键字表示, 如果我们是要自定义一个注解, 那么就在interface关键字前面加上一个@符号
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HasRole {String name() default "";String value() default "";
}
- 自定义注解里面还存在一些属性, 这些属性有点类似与我们的抽象方法, 是不能加方法体的, 加了是会报错的
- 自定义的属性是可以赋默认值的
// name的默认值是 ""
String name() default "";
-
它的返回类型必须是基础类型或者是String类型, 不可以是封装类型
-
@Target
标志自定义的注解的作用范围
类型 | 作用范围 |
---|---|
TYPE | 允许被修饰的注解作用在类, 接口和枚举上 |
FIELD | 允许作用在属性字段上 |
METHOD | 允许作用在方法上 |
PARAMETER | 允许作用在方法参数上 |
CONSTRUCTOR | 允许作用在构造器上 |
LOCAL_VARIABLE | 允许作用在本地局部变量上 |
ANNOTATION_TYPE | 允许作用在注解上 |
PACKAGE | 允许作用在包上 |
5. @Retention
标志自定义的作用是定义被它所注解的注解保留多久(生命周期)
一共有三种策略,定义在 RetentionPolicy 枚举中. 从注释上看:
类型 | 解释 |
---|---|
source | 注解只保留在源文件,当 Java 文件编译成 cláss 文件的时候,注解被遗弃;被编译器忽略 |
class | 注解被保留到 class 文件,但 jvm 加载 class 文件时候被遗弃,这是默认的生命周期 |
runtime | 注解不仅被保存到 class 文件中,jym 加载 class 文件之后,仍然存在 |
AOP回顾
基本概念
Aspect(切面)
: 一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。Join point(连接点 )
: 在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。Advice(通知)
: 在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包括“around”、“before”和“after”等通知。 通知的类型将在后面部分进行讨论。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链。Pointcut(切入点 )
: 匹配连接点(Joinpoint)的断言。通知和一个【切入点表】达式关联,并在满足这个切入点的连接点上运行。 【切入点表达式如何和连接点匹配】是AOP的核心:Spring缺省使用AspectJ切入点语法。Introduction(引入)
: Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。例如,你可以使用一个引入来使bean实现 IsModified 接口,以便简化缓存机制。Target object(目标对象)
:被一个或者多个切面(aspect)所通知(advise)的对象。也有人把它叫做 被通知(advised) 对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个 被代理(proxied) 对象。AOP代理 AOP proxy
: 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
8 .Weaving(织入)
: 把切面(aspect)连接到其它的应用程序类型或者对象上,并创建一个被通知(advised)的对象,这个过程叫织入。 这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。 Spring和其他纯Java AOP框架一样,在运行时完成织入。
声明一个切入点
【切入点确定感兴趣的连接点】,从而使我们能够控制通知何时运行。
切入点声明由两部分组成:包含【名称和方法签名】,以及确定我们感兴趣的方法执行的【切入点表达式】。
怎么确定一个方法:public void com.ddd.service.impl.*(…)
@Pointcut("execution(* transfer(..))") // the pointcut expression
private void anyOldTransfer() {} // the pointcut signature
切入点指示器(PCD)
这里只先回顾一下这两个常用的注解
@execution
: (常用)用于匹配方法执行的连接点,这是在使用Spring AOP时使用的主要切入点指示符。(匹配方法)
模式 | 描述 |
---|---|
public * *(…) | 任何公共方法的执行 |
cn.javass…IPointcutService.*() | cn.javass包及所有子包下IPointcutService接口中的任何无参方法 |
cn.javass….*(…) | cn.javass包及所有子包下任何类的任何方法 |
cn.javass…IPointcutService.(*) | cn.javass包及所有子包下IPointcutService接口的任何只有一个参数方法 |
(!cn.javass…IPointcutService+).(…) | 非“cn.javass包及所有子包下IPointcutService接口及子类型”的任何方法 |
cn.javass…IPointcutService+.() | cn.javass包及所有子包下IPointcutService接口及子类型的的任何无参方法 |
cn.javass…IPointcut.test*(java.util.Date) | cn.javass包及所有子包下IPointcut前缀类型的的以test开头的只有一个参数类型为java.util.Date的方法,注意该匹配是根据方法签名的参数类型进行匹配的,而不是根据执行时传入的参数类型决定的.如定义方法:public void test(Object obj);即使执行时传入java.util.Date,也不会匹配的; |
@annotation
: (常用)于匹配当前执行方法持有指定注解的方法。(方法上的注解)
基本通知
注解 | 说明 |
---|---|
@Before | 前置通知,在被切的方法执行前执行 |
@After | 后置通知,在被切的方法执行后执行,比return更后 |
@AfterRunning | 返回通知,在被切的方法return后执行 |
@AfterThrowing | 异常通知,在被切的方法抛异常时执行 |
@Around | 环绕通知,这是功能最强大的Advice,可以自定义执行顺序 |
通知的参数
任何通知方法都可以声明一个类型为【org.aspectj.lang.JoinPoint】
的参数作为它的【第一个参数】(注意,around
通知需要声明类型为( ProceedingJoinPoint )
的第一个参数,它是【JoinPoint】
的一个子类。 【JoinPoint】
接口提供了许多有用的方法:
getArgs()
: 返回方法参数。getThis()
: 返回代理对象。getTarget()
: 返回目标对象。getSignature
(): 返回被通知的方法的签名。toString()
: 打印被建议的方法的有用描述。
AOP整合自定义注解校验接口权限
在我们的业务开发中, 常常会遇到这样的问题 : 每当我们进行一个对数据库的操作, 通常需要鉴权用户是否具有一个正确的访问权限, 然而每次都对不同的业务流程中添加相同的鉴权的执行流程, 势必会造成代码的冗余, 而且也不利于后期代码的拓展
这时候我们可以对鉴权的业务进行切点织入, 织入切面, 化繁为简
引入依赖
pom.xml
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>29.0-jre</version></dependency>
自定义注解
这里先模拟一个缓存的类, 因为在真实业务交易权限的过程中我们一般都是把查出的用户数据放在缓存中, 以至于不用每次使用用户信息时都需要从数据库中查询
public class CacheManager {//保存用户和具有的角色之间对应关系public static final Map<String, Set<String>> USER_ROLE_MAP = new HashMap<>();static{//用户zhangsan具有user和admin两个角色Set<String> roleSet3 = Sets.newHashSet("admin","user");USER_ROLE_MAP.put("zhangsan",roleSet3);//用户lisi具有user一个角色Set<String> roleSet4 = Sets.newHashSet("user");USER_ROLE_MAP.put("lisi",roleSet4);}}
定义切面
【编写方法】声明一个切入点,该切入点在匹配连接点时“提供”‘Account’对象值,然后从通知中引用指定的切入点
@Component
@Aspect
public class AopConfig {//定义一个切点(通过注解)@Pointcut("@annotation(com.example.aopdemo.annotation.HasRole))")public void pointcut(){}//前置通知@Before("pointcut()")public void before(JoinPoint joinPoint){System.out.println("before-------------");//获取到HttpServletRequest,ThreadLocalRequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;HttpServletRequest request = servletRequestAttributes.getRequest();String username = request.getParameter("username");//获取当前用户的角色集合Set<String> userRoles = CacheManager.USER_ROLE_MAP.get(username);//获取当前请求的方法上的注解hasRole中设置的角色MethodSignature signature = (MethodSignature)joinPoint.getSignature();//反射获取当前被调用的方法Method method = signature.getMethod();//判断当前方法是否有hasRole注解//如果有,判断是否用户具有注解属性中要求的角色//如果没有hasRole注解,那么说明方法不需要判断用户的角色,可以匿名访问HasRole hasRole = method.getDeclaredAnnotation(HasRole.class);if(hasRole != null && (userRoles == null || !userRoles.contains(hasRole.value()))){throw new RuntimeException("用户没有访问权限");}}
}
这里只是配置了一个固定的注解再在pointcut上,是不需要判断的。但是如果我们不是指定某一个具体的注解的话,那么需要增加判断。因为我们的前置通知里面除了判断接口权限,还可以做很多其他的事情
AopController
@RestController
public class AopController {//访问这个方法需要用户具有admin的角色@HasRole("admin")@GetMapping("query1")public String query1(){return "query1 需要 admin 角色";}//访问这个方法需要用户具有user的角色@HasRole("user")@GetMapping("query2")public String query2(){return "query2 需要 user 角色";}//任何用户都可以访问@GetMapping("query3")public String query3(){return "query3 可以匿名访问";}
}
测试结果
测试1
因为我们本次的传参是username=lbw, 然而lbw并没有admin权限, 所以此时我们的AOP生效进行拦截
测试2
测试3
这里可以匿名访问是因为, 我们并没有在query3方法上添加@HasRole注解, 这时请求的参数不会走AOP, AOP拦截不生效, 所以可以匿名访问
如果这篇【文章】有帮助到你💖,希望可以给我点个赞👍,创作不易,如果有对Java后端或者对
spring
感兴趣的朋友,请多多关注💖💖💖
👨🔧 个人主页 : 阿千弟
相关文章:
AOP的另类用法 (权限校验自定义注解)
👳我亲爱的各位大佬们好😘😘😘 ♨️本篇文章记录的为 AOP的另类用法 (权限校验&&自定义注解) 相关内容,适合在学Java的小白,帮助新手快速上手,也适合复习中,面试中的大佬🙉🙉…...
[数据结构]:12-快速排序(顺序表指针实现形式)(C语言实现)
目录 前言 已完成内容 快速排序实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-PSeqListFunction.cpp 04-SortCommon.cpp 05-SortFunction.cpp 结语 前言 此专栏包含408考研数据结构全部内容,除其中使用到C引用外,全为C语言代…...
运算符——“Python”
各位CSDN的uu们你们好呀,好久没有更新Python文章了,今天,小雅兰的内容就是Python中的操作符啦,那么现在,就让我们进入Python的世界吧 注释 注释是什么 注释的语法 注释的规范 输入输出 和用户交互 通过控制台输出 通…...
2022 IoTDB Summit:华为王超《Apache IoTDB 在华为云的实践》
12 月 3 日、4日,2022 Apache IoTDB 物联网生态大会在线上圆满落幕。大会上发布 Apache IoTDB 的分布式 1.0 版本,并分享 Apache IoTDB 实现的数据管理技术与物联网场景实践案例,深入探讨了 Apache IoTDB 与物联网企业如何共建活跃生态&#…...
C 语言网络编程 — PF_NETLINK sockets
目录 文章目录目录PF_NETLINK socketsPF_NETLINK sockets Linux 提供了 4 种 User Process 和 Kernel 之间进行通信的 IPC(Inter-Process Communicate,进程间通信)方式: /procioctlsysfsPF_NETLINK sockets(Netlink …...
广州银行冲刺A股上市:不良贷款规模突破100亿元,不良率飙升
又一家城商行平移申报IPO。近日,广州银行股份有限公司(下称“广州银行”)递交招股书,准备在深圳证券交易所主板上市。本次冲刺上市,广州银行计划募资约94.79亿元,国泰君安证券为其保荐机构。 截至目前&…...
【C++】bsearch函数的使用及二分法查找介绍
写程序的时候,肯定避免不了需要从集合中找到符合条件的元素,一般情况下,最简单也最常用的就是循环遍历元素,这种方法虽然写的简单,但是小数据量还行,但是数据过大的话,这样效率就低了。循环的时…...
分布式系统中的补偿机制设计问题
我们知道,应用系统在分布式的情况下,在通信时会有着一个显著的问题,即一个业务流程往往需要组合一组服务,且单单一次通信可能会经过 DNS 服务,网卡、交换机、路由器、负载均衡等设备,而这些服务于设备都不一…...
类成员的方法
初识对象 生活中或是程序中,我们都可以使用设计表格、生产表格、填写表格的形式组织数据进行对比,在程序中: 设计表格,称之为:设计类(class) 打印表格,称之为:创建对象 …...
华为OD机试真题Python实现【端口合并】真题+解题思路+代码(20222023)
端口合并 题目 有M(1<=M<=10)个端口组, 每个端口组是长度为N(1<=N<=100)的整数数组, 如果端口组间存在 2 个及以上不同端口相同, 则认为这 2 个端口组互相关联,可以合并 第一行输入端口组个数 M,再输入 M 行,每行逗号分隔,代表端口组。 输出合并后的端口组…...
自考本科计算机网络原理(04741)历年大题真题【18年10月-22年10月】
文章目录一、简答题(历年真题)18年10月-22年10月历年简答题出题情况分析2018年10月2019年4月2019年10月2020年8月2020年10月2021年4月2021年10月2022年4月2022年10月二、综合题(历年真题)2018年10月2019年4月2019年10月2020年8月2…...
计算机SCI期刊投稿,除了投稿信,还要做什么准备? - 易智编译EaseEditing
投稿信的准备 期刊的编辑往往需要一些有关作者及其论文的信息。 而作者也希望给编辑提供一些有助于其全文送审及决策的信息。 这些信息都应该包括在投稿信中。 投稿信应包括以下几方面的内容: 文题和所有作者的姓名;稿件适宜的栏目; 为什么此论文适合于在该刊而…...
Allegro如何刷新封装和库里的封装同步操作指导
Allegro如何刷新封装和库里的封装同步操作指导 在做PCB设计的过程中,有时会因为库里的封装有更新,所以PCB上使用到了这个封装时候需要和库里的同步,如下图 如何刷新,具体操作如下 点击Place点击Update Symbols...
基于Vue3手写选课组件(含时区切换,拖拽选择)
环境说明 基于vue3vite 无关联别的ui框架,组件化 初次使用vue3,技术菜,大佬勿喷 main.ts "moment": "^2.29.4","moment-timezone": "^0.5.41",import moment from moment; import momentTz from &…...
准备好了吗?加入 GDE 成长计划,成为下一位谷歌开发者专家!
谷歌开发者专家 (Google Developer Experts,GDE),又称谷歌开发者专家项目,是由一群经验丰富的技术专家、具有社交影响力的开发者和思想领袖组成的全球性社区。通过在各项活动演讲以及各个平台上发布优质内容来积极助力开发者、企业和技术社区…...
搭建帮助中心的 8 个最佳工具
网站帮助中心的作用通过向客户表明您了解他们所面临的问题以及如何提供帮助来建立信任;通过回答常见问题来改善客户服务,增强专业的品牌形象;通过减少重复发送给支持人员的电话和电子邮件,节省时间和金钱;增强您在搜索…...
LQB小板焊接V3版本的小板原理图,PCB图,注意事项和步骤
第一部分,这个部分,可以不焊接,直接用买的下载器进行下载代码,外接一个下载器,网上大概是10元左右,以后学习stm32的芯片的时候,这个下载器就是一个串口转换器,也可以使用。。 当然也…...
华为OD机试真题Python实现【翻转单词顺序】真题+解题思路+代码(20222023)
翻转单词顺序 题目 输入一个英文文章片段 翻转指定区间的单词顺序,标点符号和普通字母一样处理 例如输入字符串 I am a developer. 区间[0,3]则输出 developer. a am I 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Python)真题目录汇总 ## 输入 使用换行隔…...
微机原理和计算机组成原理复习
1:冯诺依曼机器的主要特点? 1)计算机由运算器、存储器、控制器、输入设备和输出设备五大部分组成; 2)指令和数据存储在存储器中,并可以按地址访问; 3)指令和数据均以二进制表示&…...
mysql5.7.33安装配置教程【保姆级安装教程】
MySQL5.7.33安装教程 1、官方网站下载 点击这里跳转页面下载 1.1、看下你是什么系统,系统是64位还是32位 2、解压到D盘跟路径或者其下面纯英文路径 2.1、可见它没有data、log等文件夹,不需手动添加(下面执行命令自动初始化)!! …...
每天都和时间序列打交道,我总结了这篇文章!
Datawhale干货 作者:戳戳龍,上海交通大学,量化算法工程师前言🔴 平时工作中每天都在和时间序列打交道,对时间序列分析进行研究是有必要的🟡 分享和交流一些自己的在时序处理方面的心得,提供一…...
【Leetcode——重排链表】
文章目录一、重排链表思路1.思路2.总结一、重排链表 对于这道题,有两种思路: 思路1. 1.使用一个线性表,存储链表中的每个节点,然后按照题目的条件,来链接线性表的各个节点即可。 使用左下标和右下标来定位线性表中的…...
HCIP总结(一)
抽象语言---编码---二进制---电信号----处理电信号 (电脑工作流程) OSI参考模型 ----OSI/RM (核心思想:分层) 应用层----提供各种应用服务,将抽象语言转换成编码,提供人机交互的接口 表示层----将编码转换成二进制 …...
华为OD机试真题Python实现【黑板上色】真题+解题思路+代码(20222023)
题目 疫情过后希望小学终于又重新开学了,3 年 2 班开学第一天的任务是将后面的黑板报重新制作, 黑板上已经写上了N个正整数,同学们需要给这每个数分别上一种颜色, 为了让黑板报既美观又有学习意义,老师要求同种颜色的所有数都可以被这个颜色中最小的那个数整除, 现在帮小…...
C++中的利器——模板
前文本文主要是讲解一下C中的利器——模板,相信铁子们在学完这一节后,写代码会更加的得心应手,更加的顺畅。一,泛型编程想要学习模板,我们要先了解为什么需要模板,我们可以看看下面这个程序。int add(int&a…...
k8s控制器
目录 一、控制器简介 二、控制器类型 1、RC和RS 2、Deployment 3、DaemonSet 4、Job 5、CronJob 6、StateFulSet 7、HPA 一、控制器简介 在kubernetes中,按照Pod的创建方式可以将其分为两类: 自主式:kubernetes直接创建出来的Pod,…...
嵌入式学习笔记——认识STM32的 GPIO口
寄存器开发STM32GPIO口前言认识GPIOGPIO是什么GPIO有什么用GPIO怎么用STM32上GPIO的命名以及数量GPIO口的框图(重点)输入框图解析三种输入模式GPIO输入时内部器件及其作用1.保护二极管2.上下拉电阻(可配置)3.施密特触发器4.输入数…...
类和对象(中)
文章目录 继承的概念继承的语法父类成员访问super关键字子类构造方法super和this初始化protected关键字继承方式final关键字继承与组合一、继承的概念 继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类…...
Java——单词接龙
题目链接 leetcode在线oj题——单词接龙 题目描述 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> … -> sk: 每一对相邻的单词只差一个字母。 对于 1 < i < k 时ÿ…...
HTML DOM 事件监听器
通过JavaScript,我们可以给页面的某些元素添加事件的监听器,当元素触发相应事件的时候监听器就会捕捉到这个事件并执行相应的代码。addEventListener() 方法实例当用户点击按钮时触发监听事件:document.getElementById("myBtn").ad…...
网站推广是网站建设完成之后的长期工作。/如何推广我的网站
MJRefresh 是一个用法简单的下拉刷新框架,所以用它来完成gif动画的刷新也是很简单。 先看下需要用到的属性 property (nonatomic,strong) NSArray *datasArray; property (nonatomic,strong) UITableView *tableView; property (nonatomic,strong) NSMutableArray *…...
装修效果图免费软件/优化系统的软件
文章目录内容简介硬件原理软件原理添加user_key文件程序分析程序编辑程序下载内容简介 本实验是在ESP8266入门学习之使用软件定时器控制LED闪烁实验基础上进行的 实验内容: 使用软件定时器创建按键key扫描定时回调函数;按键key短按一次,led…...
成都网站建设 erp/搜索引擎谷歌入口
教育 -花卉栽培-章节资料考试资料-潍坊职业学院【】 庭院常用花卉栽培技术—单元作业 庭院常用花卉栽培技术—单元测验 1、【单选题】属于二年生花卉的是( )。 A、万寿菊 B、波斯菊 C、百日菊 D、羽衣甘蓝 参考资料【 】 2、【单选题】在北方寒冷地区冬天…...
企业头像logo设计/网站自然排名优化
一、GPT定时器简介 以前的延时函数采用空指令来实现,延时不准确且浪费cpu性能。当修改了6ull的主频以后,采用空指令延时函数就不准了。 因此需要一个高精度的延时函数,并且不随着主频的变化而改变。 stm32 使用 SYSTICK 这个硬件定时器来实现…...
申请免费网站域名/合肥网络公司排名
1、每条记录包含三个数据项: 0-201-70353-x 4 24.99 第一次项是书的ISBN号,第二项是售出的册数,最后一项是书的单价。书店老板需要查询此档案,计算每本书的销售量、销售额及平均售价。 划分子问题 1.定义变量 2.进行…...
广告网站建设网站排名优化/品牌营销是什么
在网页布局的学习中,我们经常会遇到弹性(Flex)布局,那么弹性(Flex)布局究竟是什么样子的呢?相信你学完了本篇文章就会明白Flex(弹性)布局的真正的意思了。 什么是Flexbo…...