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(全局事件) ...
随机推荐
- java mybatis Column 'AAA' in where clause is ambiguous
今天在java mybatis项目中遇到一个问题,“java mybatis Column 'AAA' in where clause is ambiguous”, 这是由于在多表连接查询的时候,遇上 ...
- C# 读取Excel文件数据
1.首先需要在管理NuGet程序包中添加外部包:ExcelDataReader,添加好后,不要忘记在命名空间那里引用. 2.定义文件流,将文件流传入IExcelDataReader类型的对象excel ...
- 【Spring AOP】Spring AOP之你必须知道的AOP相关概念(1)
一.什么是AOP AOP(Aspect-oriented Programming)即面向切面编程,是对OOP( Object-oriented Programming)即面向对象编程的一种补充,AOP ...
- docker部署zabbix
我相信大家都已经会再物理机上跑zabbix并且监控了,那么有没有想过在docker中跑zabbix?下面咱们来看看如何在docker中搭建zabbix并且监控 部署环境 2台物理机机器: zabbix ...
- <h1>~<h6> 标题标签
<h1>~</h6>标题系列标签 解释:h1到h6 中h1标签最大,h6标签最小,逐一递增. 例如: <h1>标签</h1> <h2>标签& ...
- python测试开发django-71.自定义标签tag
前言 django的模板里面有很多标签可以快速实现一些功能,比如{% url url_name%} 可以快捷的导入一个本地url地址. 上一篇我们可以自定义一些过滤器https://www.cnblo ...
- 利用多线程使socket服务端可以与多个客户端同时通讯
利用多线程使socket服务端可以与多个客户端同时通讯 server import socket 1. 符合TCP协议的手机 server = socket.socket(socket.AF_INET ...
- Python 编码错误解决方案
Python 编码错误解决方案 Python UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 7: ordin ...
- C#中的函数(二) 有参有返回值的函数
接上一篇 C#中的函数(-) 无参无返回值的函数 http://www.cnblogs.com/fzxiaoyi/p/8502613.html 这次研究下C#中的函数(二) 有参有返回值的函数 依然写 ...
- JAVA web 框架集合
“框架”犹如滔滔江水连绵不绝, 知道有它就好,先掌握自己工作和主流的框架: 在研究好用和新框架. 主流框架教程分享在Java帮帮-免费资源网 其他教程需要时间制作,会陆续分享!!! 152款框架,你还 ...