SpringBoot:切面AOP权限校验:实例演示与注解全解( 四 )
package com.example.demo;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 PermissionAdvice {@Pointcut("@annotation(com.example.demo.PermissionsAnnotation)")private void permissionCheck() {}@Around("permissionCheck()")public Object permissionCheck(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("===================开始增强处理===================");//获取请求参数 , 详见接口类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);// 修改入参JSONObject object = new JSONObject();object.put("id", 8);object.put("name", "lisi");objects[0] = object;// 将修改后的参数传入return joinPoint.proceed(objects);}}
同样使用JMeter调用接口 , 传入参数:{"id":-5,"name":"admin"} , 响应结果表明:@Around截取到了接口的入参 , 并使接口返回了切面类中的结果 。
文章插图
3.3 @Before@Before 注解指定的方法在切面切入目标方法之前执行 , 可以做一些 Log 处理 , 也可以做一些信息的统计 , 比如获取用户的请求 URL 以及用户的 IP 地址等等 , 这个在做个人站点的时候都能用得到 , 都是常用的方法 。 例如下面代码:
@Aspect@Component@Slf4jpublic class LogAspectHandler {/*** 在上面定义的切面方法之前执行该方法* @param joinPoint jointPoint*/@Before("pointCut()")public void doBefore(JoinPoint joinPoint) {log.info("====doBefore方法进入了====");// 获取签名Signature signature = joinPoint.getSignature();// 获取切入的包名String declaringTypeName = signature.getDeclaringTypeName();// 获取即将执行的方法名String funcName = signature.getName();log.info("即将执行方法为: {} , 属于{}包", funcName, declaringTypeName);// 也可以用来记录一些信息 , 比如获取请求的 URL 和 IPServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();// 获取请求 URLString url = request.getRequestURL().toString();// 获取请求 IPString ip = request.getRemoteAddr();log.info("用户请求的url为:{} , ip地址为:{}", url, ip);}}
JointPoint 对象很有用 , 可以用它来获取一个签名 , 利用签名可以获取请求的包名、方法名 , 包括参数(通过 joinPoint.getArgs() 获取)等 。
搜索程序员麦冬公众号 , 回复“888” , 送你一份2020最新Java面试题手册.pdf
3.4 @After@After 注解和 @Before 注解相对应 , 指定的方法在切面切入目标方法之后执行 , 也可以做一些完成某方法之后的 Log 处理 。
@Aspect@Component@Slf4jpublic class LogAspectHandler {/*** 定义一个切面 , 拦截 com.mutest.controller 包下的所有方法*/@Pointcut("execution(* com.mutest.controller..*.*(..))")public void pointCut() {}/*** 在上面定义的切面方法之后执行该方法* @param joinPoint jointPoint*/@After("pointCut()")public void doAfter(JoinPoint joinPoint) {log.info("==== doAfter 方法进入了====");Signature signature = joinPoint.getSignature();String method = signature.getName();log.info("方法{}已经执行完", method);}}
到这里 , 我们来写个 Controller 测试一下执行结果 , 新建一个 AopController 如下:
@RestController@RequestMapping("/aop")public class AopController {@GetMapping("/{name}")public String testAop(@PathVariable String name) {return "Hello " + name;}}
启动项目 , 在浏览器中输入:localhost:8080/aop/csdn , 观察一下控制台的输出信息:
====doBefore 方法进入了====即将执行方法为: testAop , 属于com.itcodai.mutest.AopController包用户请求的 url 为:http://localhost:8080/aop/name , ip地址为:0:0:0:0:0:0:0:1==== doAfter 方法进入了====方法 testAop 已经执行完
从打印出来的 Log 中可以看出程序执行的逻辑与顺序 , 可以很直观地掌握 @Before 和 @After两个注解的实际作用 。
搜索程序员麦冬公众号 , 回复“888” , 送你一份2020最新Java面试题手册.pdf
3.5 @AfterReturning@AfterReturning 注解和 @After 有些类似 , 区别在于 @AfterReturning 注解可以用来捕获切入方法执行完之后的返回值 , 对返回值进行业务逻辑上的增强处理 , 例如:
@Aspect@Component@Slf4jpublic class LogAspectHandler {/*** 在上面定义的切面方法返回后执行该方法 , 可以捕获返回对象或者对返回对象进行增强* @param joinPoint joinPoint* @param result result*/@AfterReturning(pointcut = "pointCut()", returning = "result")public void doAfterReturning(JoinPoint joinPoint, Object result) {Signature signature = joinPoint.getSignature();String classMethod = signature.getName();log.info("方法{}执行完毕 , 返回参数为:{}", classMethod, result);// 实际项目中可以根据业务做具体的返回值增强log.info("对返回参数进行业务上的增强:{}", result + "增强版");}}
- SpringBoot+MyBatis+MySQL读写分离实现
- SpringBoot构造流程源码分析:Web应用类型推断
- 搭建私有Sentry日志收集系统并集成到springboot
- SpringBoot扫描不到组件?给你提供几种方案
- SpringBoot自定义错误页面
- SpringBoot实现反向代理
- SpringBoot内置源码解析WebServer初始化过程
- SpringBoot外化配置源码解析:命令参数获取文件加载
- 写了个牛逼的日志切面,甩锅更方便了
- SpringBoot外化配置源码解析:外化配置简介、参数处理