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. (原)堆叠hourglass网络

    转载请注明出处: https://www.cnblogs.com/darkknightzh/p/11486185.html 论文: https://arxiv.org/abs/1603.06937 官 ...

  2. Linux的网络参数设置

    前面讲解了lLinux 的IP组成,下面就讲一下Linux的网络设置和数据传递. 其实这地方对运维的人员来说,不会要精通,但还是要了解.必要时刻还会用到的 电脑之间数据的传递: 数据的传递要分为下面几 ...

  3. 豆瓣读书isbn 查询

    最近学习微信小程序,做一个类似"书库"的小demo,大致流程使用摄像头获取书本后面的isbn,通过豆瓣读书API得到书本介绍.豆瓣评分.图书评论等信息,然鹅https://api. ...

  4. 【HttpServlet】HttpServlet类

    创建时间:6.15 HttpServlet 但在实际开发中,我们不会直接去实现Servlet接口,因为那样需要覆盖的方法太多,    我们一般创建类继承HttpServlet 实现步骤: 1)创建类继 ...

  5. python中列表(list)函数及使用

    序列是Python中最基本的数据结构.序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推. Python有6个序列的内置类型,但最常见的是列表和元组. 序列 ...

  6. Python GIL、CPU密集型、IO密集型

    Python GIL(Global Interpreter Lock(全局解释器锁)) 1:进程里面多个线程,线程 共享A=10 2:Python解释器,A改完值之后会传回进程容器,为了防止A和B同时 ...

  7. ActiveMQ消息可靠性-持久性

    三个方面保证消息的可靠性 1.消息的持久 2.事物 3.签收 一:PERSISTENT:持久性   参数说明:1.持久   2.非持久 Java里面设置持久化和非持久 持久: 将持久性设置为持久 宕机 ...

  8. celery异步任务、定时任务

    阅读目录 一 什么是Celery? 二 Celery的使用场景 三 Celery的安装配置 四 Celery异步任务 五Celery定时任务 六在Django中使用Celery   一 什么是Cele ...

  9. python与javascript 引入模块的方法对比

    1.引入整体模块对比 python 方法一: # 引入全部函数 from xxx import * # 直接使用模块里面的各函数或者属性 test() 方法二: # 引入全局的模块 import gl ...

  10. ESA2GJK1DH1K基础篇: 关于各大物联网平台的MQTT通信

    前言 这节稍微唠叨点 其实我很长时间都没有出怎么连接现成的物联网平台的教程, 一直写的是教给大家自己搭建服务器,主要原因是因为我感觉连接现有的学不到东西. 现在出这种教程,是因为发现确实很多人喜欢用. ...