spring AOP实现@Around输出请求参数和返回参数

 更新时间:2022年02月16日 11:13:29   作者:haodong1024  
这篇文章主要介绍了spring AOP实现@Around输出请求参数和返回参数,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

@Around输出请求参数和返回参数

spring 的AOP是通过cglib动态代理和jdk的动态代理实现的。

先把我的打印日志代码贴出来

package com.zhd.exploit.api.config;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletResponseWrapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.ExtendedServletRequestDataBinder;
import com.alibaba.fastjson.JSONObject;
@Aspect
@Component
@Order(1)
public class ControllerLogInterceptor {
	private static final Logger log = LoggerFactory.getLogger(ControllerLogInterceptor.class);
    //创建Pointcut表示式,表示所有controller请求
	@Pointcut("execution(* com..*.controller..*(..))")
	private void controllerAspect() {
	}// 请求method前打印内容
	@Around(value = "controllerAspect()")
	public void around(ProceedingJoinPoint pjp) throws Throwable {
	//通过uuid关联请求参数和返回参数
		String uuid = UUID.randomUUID().toString().replaceAll("-", "");
		methodBefore(pjp, uuid);
		try {
			Object proceed = pjp.proceed();
			methodAfterReturing(proceed, uuid);
		} catch (Exception e) {
			log.error("[{}]Response异常内容:{}", uuid, e);
			throw e;
		}
	}
	public void methodBefore(JoinPoint joinPoint, String uuid) {
		// 打印请求内容
		try {
			// 下面两个数组中,参数值和参数名的个数和位置是一一对应的。
			Object[] objs = joinPoint.getArgs();
			String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); // 参数名
			Map<String, Object> paramMap = new HashMap<String, Object>();
			for (int i = 0; i < objs.length; i++) {
				if (!(objs[i] instanceof ExtendedServletRequestDataBinder) && !(objs[i] instanceof HttpServletResponseWrapper)) {
					paramMap.put(argNames[i], objs[i]);
				}
			}
			if (paramMap.size() > 0) {
				log.info("\n[{}]方法:{}\n参数:{}", uuid, joinPoint.getSignature(), JSONObject.toJSONString(paramMap));
			}
		} catch (Exception e) {
			log.error("[{}]AOP methodBefore:", uuid, e);
		}
	}
	public void methodAfterReturing(Object o, String uuid) {
		try {
			if (o != null)
				log.info("[{}]Response内容:{}", uuid, JSONObject.toJSON(o));
		} catch (Exception e) {
			log.error("[{}]AOP methodAfterReturing:", uuid, e);
		}
	}
}

测试

请求参数类型1

    @RequestMapping(value = "/test0", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
    public Result test0(@RequestParam String name, @RequestParam String password) {
        System.out.println("test0 OK");
        return new Result("1", "mock a Result");
    }

打印日志:

[fe7155a3089b4dd7896b759a933cf958]方法:Result com.zhd.exploit.api.controller.TestController.test0(String,String)
参数:{"password":"123","name":"zhang"}

请求参数类型2

    @RequestMapping(value = "/test1", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
    public Result test1(PayDTO payDTO) {
        System.out.println("test1 OK");
        return new Result("1", "mock a Result");
    }

打印日志:

[a2f7d19dea834c54a45b480bd4e8c3cd]方法:Result com.zhd.exploit.api.controller.TestController.test1(PayDTO)
参数:{"payDTO":{"appmount":"10","paytype":"1"}}

请求参数类型3

    @RequestMapping(value = "/test2", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
    public Result test2(@RequestBody PayDTO payDTO) {
        System.out.println("test2 OK");
        return new Result("2", "mock a Result");
    }

打印日志:

[cd6a3d9d05244eee95bbf3c607d038cc]方法:Result com.zhd.exploit.api.controller.TestController.test2(PayDTO)
参数:{"payDTO":{"appmount":"10","paytype":"1"}}

spring AOP中Around切面处理参数

最近遇到一个场景,在业务流程处理中,很多的方法都需要对传入的参数对象做公共的处理【比如:添加编辑人信息】,而且这些传入对象都继承自一个父类,同时需要用到HttpServletRequest。

解决的办法

使用自定义annotation+aop来实现预处理 具体的处理流程是

1、自定义一个annotation用于标记需要处理的地方

2、创建切面类,在pointcut时对annotation进行拦截,在@Around环绕通知里面获取@annotation对应的当前对象,获取当前对象参数,并修改参数内容,然后proceed一下,继续执行

具体的代码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Operate {
}
@Aspect
@Component
public class OperateInterceptor { 
    @Pointcut("@annotation(com.yili.web.entity.Operate)")
    public void interceptor() {
    }
 
    @Resource
    private SqlObjectUtil sqlObjectUtil;
 
    @Around(value = "interceptor()")
    public Object check(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("进入interceptor");
        Signature signature = pjp.getSignature();
        if (!(signature instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只适用于方法");
        }
        Object[] objects = pjp.getArgs();
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) attributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String loginToken = getLoginToken(request);        
        for (int i=0;i<objects.length;i++){
            if (SqlObject.class.isAssignableFrom(objects[i].getClass()))) {
                sqlObjectUtil.setOperatorInfo(loginToken,(SqlObject)objects[i]);
            }
        }
        return pjp.proceed(objects);
    }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • springboot接口返回数据类型全面解析

    springboot接口返回数据类型全面解析

    这篇文章主要介绍了springboot接口返回数据类型问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Springboot配置文件相关说明解析

    Springboot配置文件相关说明解析

    这篇文章主要介绍了Springboot配置文件相关说明解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • java线程的基础实例解析

    java线程的基础实例解析

    这篇文章主要介绍了java线程的基础实例解析,具有一定借鉴价值,需要的朋友可以参考下
    2017-12-12
  • 详解springboot中junit回滚

    详解springboot中junit回滚

    本篇文章主要介绍了springboot中junit回滚,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • Java 实现一个汉诺塔实战练习

    Java 实现一个汉诺塔实战练习

    汉诺塔是源于印度一个古老传说的益智玩具。大梵天创造世界时做了三根石柱,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,三根柱子之间一次只能移动一个圆盘
    2021-10-10
  • idea out目录与target目录的区别详解

    idea out目录与target目录的区别详解

    这篇文章主要介绍了idea out目录与target目录的区别详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • java高并发的ReentrantLock重入锁

    java高并发的ReentrantLock重入锁

    这篇文章主要介绍了如何教你完全理解ReentrantLock重入锁,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,下面我们来一起学习一下吧
    2021-10-10
  • 分享Spring的下载组件

    分享Spring的下载组件

    这篇文章主要为大家分享了Spring的下载组件,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • Spring RestTemplate如何利用拦截器打印请求参数和返回状态

    Spring RestTemplate如何利用拦截器打印请求参数和返回状态

    这篇文章主要介绍了Spring RestTemplate如何利用拦截器打印请求参数和返回状态问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • IDEA搭建Maven模块化项目的实现

    IDEA搭建Maven模块化项目的实现

    本文主要介绍了IDEA搭建Maven模块化项目的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05

最新评论