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等执行顺序与请求参数统一解码的更多相关文章

  1. spring aop切面中获取代理bean的名字以及bean

    //切面中搞: Map<String , Object> map = (Map)ApplicationContextHelper.getBean(proceedingJoinPoint.g ...

  2. Spring AOP @Before @Around @After 等 advice 的执行顺序

    用过spring框架进行开发的人,多多少少会使用过它的AOP功能,都知道有@Before.@Around和@After等advice.最近,为了实现项目中的输出日志和权限控制这两个需求,我也使用到了A ...

  3. 转 Spring AOP @Before @Around @After 等 advice 的执行顺序

    转自:http://blog.csdn.net/rainbow702/article/details/52185827 情况一: 一个方法只被一个Aspect类拦截 正常情况:  异常情况:  情况二 ...

  4. Spring AOP 切面编程记录日志和接口执行时间

    最近客户现在提出系统访问非常慢,需要优化提升访问速度,在排查了nginx.tomcat内存和服务器负载之后,判断是数据库查询速度慢,进一步排查发现是因为部分视图和表查询特别慢导致了整个系统的响应时间特 ...

  5. spring AOP(切面) 表达式介绍

    在 spring AOP(切面) 例子基础上对表达式进行介绍 1.添加接口删除方法 2.接口实现类 UserDaoServer 添加实现接口删除方法 3.测试类调用delUser方法 4. 输出结果截 ...

  6. 使用Spring AOP切面解决数据库读写分离

    http://blog.jobbole.com/103496/ 为了减轻数据库的压力,一般会使用数据库主从(master/slave)的方式,但是这种方式会给应用程序带来一定的麻烦,比如说,应用程序如 ...

  7. 利用Spring AOP切面对用户访问进行监控

    开发系统时往往需要考虑记录用户访问系统查询了那些数据.进行了什么操作,尤其是访问重要的数据和执行重要的操作的时候将数记录下来尤显的有意义.有了这些用户行为数据,事后可以以用户为条件对用户在系统的访问和 ...

  8. Spring AOP切面的时候参数的传递

    Spring AOP切面的时候参数的传递 Xml: <?xml version="1.0" encoding="UTF-8"?> <beans ...

  9. jquery ajax中success与complete的执行顺序

    jquery ajax中success与complete的执行顺序 jquery中各个事件执行顺序如下: 1.ajaxStart(全局事件) 2.beforeSend 3.ajaxSend(全局事件) ...

随机推荐

  1. 串口 PLC 编程FAQ

    1. 不要频繁打开关闭串口,这是个耗时的过程,如果多个工位都争夺串口资源,则会出现卡顿,死锁. 2. PLC 的读写估计100毫秒,如果并发的写,有的写操作会失败,需要Delay或重试. 3. 通常一 ...

  2. 解决securecrt连接慢(而xshell秒连)的问题

    打开securecrt的跟踪选项,观察输出信息来诊断 解决方法: 1)首先,将全局设置中,GSSAPI属性由自动改为GSSAPI   2)其次,将不支持的多余的密钥交换去掉   3)最后,可以将服务端 ...

  3. Mysql-5.5版本搭建实例的部分库的从库

    由于业务需要在Mysql实例中创建部分库的从库,已有的Mysql实例的版本是mysql-5.5.49,是一个非常老的版本. 本文档涉及到服务器中运行多实例和构建实例中部分库的从库. 服务器 mysql ...

  4. MySQL修炼之路四

    1. 外键(foreign key) 1. 定义:让当前表字段的值在另一个表的范围内选择 2. 语法 foreign key(参考字段名) references 主表(被参考字段名) on delet ...

  5. Python程序 #!/usr/bin/python 的解释

    关于脚本第一行的 #!/usr/bin/python 的解释,相信很多不熟悉 Linux 系统的同学需要普及这个知识,脚本语言的第一行,只对 Linux/Unix 用户适用,用来指定本脚本用什么解释器 ...

  6. jQuery对象和DOM对象转换,解决jQuery对象不能使用js方法的问题

    有时候想要jQuery对象使用js方法,但是jQuery对象是什么js方法都不能用,怎么办呢?方法其实很简单,只要转换jQuery和DOM对象就可以了. 方法一: var $cr = $(" ...

  7. 将HashMap转换为List

    背景 ​ SpringBoot中,使用@RquestBody注解 hashMap 接收多个参数的json字符串数据,包括一个数组和一个int值.数组中为一个个的对象组成. 问题 ​ 使用 map.ge ...

  8. MYSQL:基于哈希的索引和基于树的索引有什么区别?

    B+树是一个平衡的多叉树.B+树从根节点到叶子节点的搜索效率基本相当,不会出现大幅波动. 哈希索引采用一定的哈希算法,把键值换成新的哈希值,检索时不需要类似B+树那样从根节点逐级查找,只需一次哈希算法 ...

  9. 基于web公交查询系统自我安排进度

    这周完成站点信息管理

  10. Docker环境下的前后端分离项目部署与运维(八)使用Docker部署RabbitMQ集群

    下载RabbitMQ镜像 镜像地址RabbitMQ Docker官方认证镜像地址:https://hub.docker.com/_/rabbitmq 安装命令安装之前,切记把Docker Hub设置为 ...