spring Aop切面中的@Before @Around等执行顺序与请求参数统一解码
1.背景
在实际开发中,我可能会对请求接口做统一日志输出,或者统一参数解析,验签,统一响应加密等,通常会用到aop,实际案例如下
2.代码
package com.qianxingniwo.log; import com.alibaba.fastjson.JSON;
import com.qianxingniwo.exception.ParamException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; /**
* @Copyright (C)
* @Author:
* @Date: 2019/4/8 10:11
* @Description: <p>
* aop的几个重要概念
* 切面(做什么事情,切入后要执行的业务)
* 切入点(在什么地点,具体到方法,一般使用通配符 或 注解)
* 切入时机(在什么时候,方法执行前,方法执行后,抛异常的时候)
* </p>
*/
@Aspect//定义切面
@Component //加入spring容器
@SuppressWarnings("all")//注解主要用在取消一些编译器产生的警告
public class SystemLogAspect {
/**
* 本地异常日志记录对象
*/
private static final Logger log = LoggerFactory.getLogger(SystemLogAspect.class); /**
* Controller层切点
*/
@Pointcut("execution(* com.qianxingniwo.*.controller.*Controller.*(..))")
public void controllerAspect() {
} /**
* 可以修改请求参数,如实际生成中,将请求参数解密等
*
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("controllerAspect()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("@Around=1=方法执行前" + System.currentTimeMillis());
Object[] obj = joinPoint.getArgs();
System.out.println("@Around=2=请求参数" + JSON.toJSONString(obj));
// Object obj2 = joinPoint.proceed();
// System.out.println("@Around=3=方法后" + System.currentTimeMillis() + "--" + obj2);
// System.out.println("@Around:被织入的目标对象为:" + joinPoint.getTarget());
// System.out.println("@Around:原返回值:" + JSON.toJSONString(obj2) + ",这是返回结果的后缀");
// JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(obj[0]));
//通过反射实例化参数对象
//获取字节码
Class<?> aClass = obj[0].getClass();
//实例化对象
Object instance = aClass.newInstance();
//获取执行方法 获取父类方法 setDataList
//Method method = aClass.getDeclaredMethod("put", Object.class);
Method method = aClass.getSuperclass().getMethod("put", Object.class); List<Integer> dataList = new ArrayList<>();
dataList.add(1);
dataList.add(2);
//执行方法
method.invoke(instance, dataList);
// jsonObject.put("dataList", dataList); obj[0] = instance;
//obj[0] = MAPPER.writeValueAsString("");
System.out.println("=====修改参数==========");
return joinPoint.proceed(obj);
} /**
* 切入时机
*
* @param joinPoint
* @Description 前置通知 用于拦截Controller层记录用户的操作
*/
@Before("controllerAspect()")
public void doBefore(JoinPoint joinPoint) throws ParamException {
System.out.println("@Before==" + System.currentTimeMillis());
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
Thread.currentThread().setName(UUID.randomUUID().toString().substring(0, 12));
String params = "";
if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
String data = JSON.toJSONString(joinPoint.getArgs()[0]);
params += data;
}
//获取用户请求方法的参数并序列化为JSON格式字符串
//打印请求内容
String url = request.getRequestURL().toString();
log.info("===============请求内容===============");
log.info("请求地址:" + url);
log.info("请求方式:" + request.getMethod());
log.info("请求类方法:" + joinPoint.getSignature());
log.info("请求类方法参数:" + params);
log.info("===============请求内容===============");
} @After("controllerAspect()")
public void After(JoinPoint point) {
System.out.println("@After==" + System.currentTimeMillis());
/* System.out.println("@After:模拟释放资源...");
System.out.println("@After:目标方法为:" +
point.getSignature().getDeclaringTypeName() +
"." + point.getSignature().getName());
System.out.println("@After:参数为:" + Arrays.toString(point.getArgs()));
System.out.println("@After:被织入的目标对象为:" + point.getTarget());*/
} /**
* 统一修改响应结果,如加密等
*
* @param joinPoint
* @param o
* @throws Exception
*/
@AfterReturning(returning = "o", pointcut = "controllerAspect()")
public void methodAfterReturing(JoinPoint joinPoint, Object o) throws Exception {
System.out.println("@AfterReturning==" + System.currentTimeMillis());
System.out.println("@AfterReturning:模拟日志记录功能...");
log.info("--------------返回内容----------------");
log.info("Response内容:" + JSON.toJSONString(o));
log.info("--------------返回内容----------------"); /* ResponseMessage responseMessage = (ResponseMessage) o;
byte[] a = Base64Utils.encode(JSON.toJSONString(o).getBytes());
responseMessage.setMsg(new String(a )); log.info("请求返回值【{}】", object.toString());*/
} @AfterThrowing("controllerAspect()")
public void AfterThrowing() {
System.out.println("@AfterThrowing==" + System.currentTimeMillis());
System.out.println("异常通知....");
} }
执行结果如下:

3.执行流程图解

完美!
spring Aop切面中的@Before @Around等执行顺序与请求参数统一解码的更多相关文章
- spring aop切面中获取代理bean的名字以及bean
//切面中搞: Map<String , Object> map = (Map)ApplicationContextHelper.getBean(proceedingJoinPoint.g ...
- Spring AOP @Before @Around @After 等 advice 的执行顺序
用过spring框架进行开发的人,多多少少会使用过它的AOP功能,都知道有@Before.@Around和@After等advice.最近,为了实现项目中的输出日志和权限控制这两个需求,我也使用到了A ...
- 转 Spring AOP @Before @Around @After 等 advice 的执行顺序
转自:http://blog.csdn.net/rainbow702/article/details/52185827 情况一: 一个方法只被一个Aspect类拦截 正常情况: 异常情况: 情况二 ...
- Spring AOP 切面编程记录日志和接口执行时间
最近客户现在提出系统访问非常慢,需要优化提升访问速度,在排查了nginx.tomcat内存和服务器负载之后,判断是数据库查询速度慢,进一步排查发现是因为部分视图和表查询特别慢导致了整个系统的响应时间特 ...
- spring AOP(切面) 表达式介绍
在 spring AOP(切面) 例子基础上对表达式进行介绍 1.添加接口删除方法 2.接口实现类 UserDaoServer 添加实现接口删除方法 3.测试类调用delUser方法 4. 输出结果截 ...
- 使用Spring AOP切面解决数据库读写分离
http://blog.jobbole.com/103496/ 为了减轻数据库的压力,一般会使用数据库主从(master/slave)的方式,但是这种方式会给应用程序带来一定的麻烦,比如说,应用程序如 ...
- 利用Spring AOP切面对用户访问进行监控
开发系统时往往需要考虑记录用户访问系统查询了那些数据.进行了什么操作,尤其是访问重要的数据和执行重要的操作的时候将数记录下来尤显的有意义.有了这些用户行为数据,事后可以以用户为条件对用户在系统的访问和 ...
- Spring AOP切面的时候参数的传递
Spring AOP切面的时候参数的传递 Xml: <?xml version="1.0" encoding="UTF-8"?> <beans ...
- jquery ajax中success与complete的执行顺序
jquery ajax中success与complete的执行顺序 jquery中各个事件执行顺序如下: 1.ajaxStart(全局事件) 2.beforeSend 3.ajaxSend(全局事件) ...
随机推荐
- mysql 多条数据中,分组获取值最大的数据记录
摘要: 多条纪录中,几个字段相同,但是其中一个或者多个字段不同,则去该字段最大(这里只有一个不同) 源数据: 目的是移除:在同一天中只能存在一天数据,则取审核日期最大,数据库脚本如下: SELECT ...
- eclipse IDE 32位汉化方法及常用软件汉化包寻找办法
今天听说小组开发人员遇到安装eclipse不能汉化问题.了解到其他同事用的都是64位操作系统,这个同事用的32位系统.通常情况下常用软件都有各路大神发的成熟汉化包,不会出现无法安装汉化包的情况. 先找 ...
- pymysql操作(老版本的,新版有基础不同)
导入库 import pymysql 创建链接 conn=pymysql.connect(host='127.0.0.1',port='3306',user='root',passwd='123456 ...
- Linux shell if条件判断2
前面介绍linux shell的if判断的语法,现在再补充一点. Linux shell if条件判断1 分支判断结构 if , case 下面两个结构语法,已经在前面有过示例. 结构1: ...
- maven中,dependency 中的 classifier属性
classifier元素用来帮助定义构件输出的一些附属构件.附属构件与主构件对应,比如主构件是 kimi-app-2.0.0.jar 该项目可能还会通过使用一些插件生成 如 kimi-app-2.0. ...
- 性能测试:TPS和QPS的区别
做测试,各种ps,jps,tps,qps,rps,hps,你理解几个? 技术群里,问得最多的就是tps和qps,有相似的地方,也有差异的地方,我简单谈下自己的理解.(由于比较忙,下面部分摘抄自网络) ...
- 解决opencart设置SSL后评论不能翻页的问题
为了网站的安全和seo,我们为客户的opencart网站添加了SSL加密实现https,并设置了301跳转使http跳到https,基本所有的功能都完好,就是有一点评论分页无法加载分页,去分析了链接源 ...
- 07-C#笔记-运算符
1. 支持++和-- 含义和C++中相同 2. 条件运算 同C++ 3. 位运算 ^ 异或 ~ 取反 4. 支持?:运算 5. 特殊 is 判断对象是否为某一类型. If( Ford is Car) ...
- JSOI 2010 连通数
洛谷 P4306 [JSOI2010]连通数 洛谷传送门 题目描述 度量一个有向图联通情况的一个指标是连通数,指图中可达顶点对个的个数. 如图 顶点 11 可达 1,~2,~3,~4,~51, 2, ...
- 网络协议 17 - HTTPDNS
全球统一的 DNS 是很权威,但是我们都知道“适合自己的,才是最好的”.很多时候,标准统一化的 DNS 并不能满足我们定制的需求,这个时候就需要 HTTPDNS 了. 上一节我们知道了 DNS ...