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

网友投稿 1245 2022-08-28


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

目录@Around输出请求参数和返回参数先把我的打印日志代码贴出来测试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 paramMap = new HashMap();

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 = servhttp://letRequestAttributes.getRequest();

String loginToken = getLoginToken(request);

for (int i=0;i

if (SqlObject.class.isAssignableFrom(objects[i].getClass()))) {

sqlObjectUtil.setOperatorInfo(loginToken,(SqlObject)objects[i]);

}

}

return pjp.proceed(objects);

}

if (SqlObject.class.isAssignableFrom(objects[i].getClass()))) {

sqlObjectUtil.setOperatorInfo(loginToken,(SqlObject)objects[i]);

}

}

return pjp.proceed(objects);

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:PyQt4对话框(dialog类型介绍)
下一篇:PyQt汇率兑换工具实现的代码,需要引用上一节写的DataMake类
相关文章

 发表评论

暂时没有评论,来抢沙发吧~