SpringBoot:切面AOP权限校验:实例演示与注解全解( 二 )
项目启动后 , 请求http://localhost:8085/aop/getTest接口:
文章插图
请求http://localhost:8085/aop/postTest接口 , 控制台无输出 , 证明切点确实是只针对被GetMapping修饰的方法 。
2.2 第二个实例下面我们将问题复杂化一些 , 该例的场景是:
- 自定义一个注解PermissionsAnnotation
- 创建一个切面类 , 切点设置为拦截所有标注PermissionsAnnotation的方法 , 截取到接口的参数 , 进行简单的权限校验
- 将PermissionsAnnotation标注在测试接口类的测试接口test上
- 使用@Target、@Retention、@Documented自定义一个注解:
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface PermissionAnnotation{}
- 创建第一个AOP切面类 ,, 只要在类上加个 @Aspect 注解即可 。 @Aspect 注解用来描述一个切面类 , 定义切面类的时候需要打上这个注解 。 @Component 注解将该类交给 Spring 来管理 。 在这个类里实现第一步权限校验逻辑:
package com.example.demo;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component;@Aspect@Component@Order(1)public class PermissionFirstAdvice { // 定义一个切面 , 括号内写入第1步中自定义注解的路径@Pointcut("@annotation(com.mu.demo.annotation.PermissionAnnotation)")private void permissionCheck() {}@Around("permissionCheck()")public Object permissionCheckFirst(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("===================第一个切面===================:" + System.currentTimeMillis());//获取请求参数 , 详见接口类Object[] objects = joinPoint.getArgs();Long id = ((JSONObject) objects[0]).getLong("id");String name = ((JSONObject) objects[0]).getString("name");System.out.println("id1->>>>>>>>>>>>>>>>>>>>>>" + id);System.out.println("name1->>>>>>>>>>>>>>>>>>>>>>" + name);// id小于0则抛出非法id的异常if (id < 0) {return JSON.parseObject("{\"message\":\"illegal id\",\"code\":403}");}return joinPoint.proceed();}}
- 创建接口类 , 并在目标方法上标注自定义注解 PermissionsAnnotation:
package com.example.demo;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import org.springframework.web.bind.annotation.*;@RestController@RequestMapping(value = "http://kandian.youth.cn/permission")public class TestController {@RequestMapping(value = "http://kandian.youth.cn/check", method = RequestMethod.POST)// 添加这个注解@PermissionsAnnotation()public JSONObject getGroupList(@RequestBody JSONObject request) {return JSON.parseObject("{\"message\":\"SUCCESS\",\"code\":200}");}}
在这里 , 我们先进行一个测试 。 首先 , 填好请求地址和header:文章插图
其次 , 构造正常的参数:
文章插图
可以拿到正常的响应结果:
文章插图
然后 , 构造一个异常参数 , 再次请求:
文章插图
响应结果显示 , 切面类进行了判断 , 并返回相应结果:
文章插图
有人会问 , 如果我一个接口想设置多个切面类进行校验怎么办?这些切面的执行顺序如何管理?
很简单 , 一个自定义的AOP注解可以对应多个切面类 , 这些切面类执行顺序由@Order注解管理 , 该注解后的数字越小 , 所在切面类越先执行 。
下面在实例中进行演示:
创建第二个AOP切面类 , 在这个类里实现第二步权限校验:
package com.example.demo;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component;@Aspect@Component@Order(0)public class PermissionSecondAdvice {@Pointcut("@annotation(com.example.demo.PermissionsAnnotation)")private void permissionCheck() {}@Around("permissionCheck()")public Object permissionCheckSecond(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("===================第二个切面===================:" + System.currentTimeMillis());//获取请求参数 , 详见接口类Object[] objects = joinPoint.getArgs();Long id = ((JSONObject) objects[0]).getLong("id");String name = ((JSONObject) objects[0]).getString("name");System.out.println("id->>>>>>>>>>>>>>>>>>>>>>" + id);System.out.println("name->>>>>>>>>>>>>>>>>>>>>>" + name);// name不是管理员则抛出异常if (!name.equals("admin")) {return JSON.parseObject("{\"message\":\"not admin\",\"code\":403}");}return joinPoint.proceed();}}
- SpringBoot+MyBatis+MySQL读写分离实现
- SpringBoot构造流程源码分析:Web应用类型推断
- 搭建私有Sentry日志收集系统并集成到springboot
- SpringBoot扫描不到组件?给你提供几种方案
- SpringBoot自定义错误页面
- SpringBoot实现反向代理
- SpringBoot内置源码解析WebServer初始化过程
- SpringBoot外化配置源码解析:命令参数获取文件加载
- 写了个牛逼的日志切面,甩锅更方便了
- SpringBoot外化配置源码解析:外化配置简介、参数处理