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. nginx的 ngx.var ngx.ctx ngx.req

    ngx.var 是获取 Nginx 的变量,需要经历字符串 hash.hash 表查找等过程. ngx.ctx 仅仅是一个 Lua table 而已,它的引用存放在 ngx_lua 的模块上下文(ct ...

  2. 模型选择---KFold,StratifiedKFold k折交叉切分

    StratifiedKFold用法类似Kfold,但是他是分层采样,确保训练集,测试集中各类别样本的比例与原始数据集中相同. 例子: import numpy as np from sklearn.m ...

  3. jenkins pipeline之stash/unstash

    在使用jenkins时,经常会问到文件怎么存储? 正好jenkins有一个stash的功能,下面简单介绍下: 先看看官方是怎么解释的: stash: Stash some files to be us ...

  4. graalvm native image 试用

    graalvm 提供的native 模式,可以加速应用的启动,不同可以让应用不再依赖jvm 运行时环境,但是 也有一些限制 参考 https://github.com/oracle/graal/blo ...

  5. windows下 zabbix agent心跳数据获取异常

    模板中的心跳监控项默认是主动性的,在windows下直接装上客户端后,如果不协调时间,可能会出现心跳数据异常, 因为是主动式的监控,agent上的数据主动的推送到server上,但是从server上看 ...

  6. python相对导包问题

    导包分为:绝对路径.相对路径 在测试时发现不能够使用相对路径 查过之后才知道: 运行模块(如:main.py)中导包只能使用绝对路径,不能使用相对路径 官方文档: Note that relative ...

  7. selenium--页面元素相关的操作

    获取元素的标签和元素大小 from selenium import webdriver import unittest class Test_BasicInfo(unittest.TestCase): ...

  8. shell中使用expect命令进行远程执行命令脚本

    expect是用来实现自动交互功能的工具之一,使用expect-send来实现交互过程. 注意: 1.脚本的执行方法与bash shell不一样,比如:expect example.sh 2.向一个脚 ...

  9. 如何下载最新版本和旧版本的eclipse?

    1.进入官网,点击download,进入download界面,如果想要最新的版本的eclipse,直接点击下载即可,如图所示: 2.如果想下载旧版本的eclipse的话,可以点击上图的的downloa ...

  10. 【mysql】'XXX.XXX.XXX' isn't in GROUP BY问题解决

    原因是mysql的版本低于5.7,使用的GROUP BY 例如:数据库名称为db,表为t,sql为SELECT id, user_name FROM sys_user GROUP BY id 报错为 ...