java通过AOP修改请求中的参数值

发布时间 2024-01-09 10:48:37作者: 浪迹天涯的派大星

1、背景

项目中存在一个需求,当用户不传项目ID时,将其赋值为默认值,初步分析后,发现接口数量众多,且绝大多数接口都需要传递项目ID。Controller接口的参数形式很多,大多数的Post请求都是以对象的方式接收参数,部分Post的form-data请求和Get请求是以多个基本数据类型的方式接收参数,一般这种多接口的公共处理,都是采用AOP的方式处理,所以此处也采用相同的方式。

2、切面中排除部分接口

@Aspect
@Component
@Order(-99)
public class SdkDefaultProjectAspect{

    @Pointcut("execution( public * com.test.controller.client.*Controller.*( .. ))")
    public void openApiController(){
    }
    
    @Around("!openApiController() && execution(public * com.test..*Controller.*( .. ))")
    public Object dealSdkProjectId(ProceedingJoinPoint joinPoint){
        joinPoint.proceed();
    }

}

@Pointcut表示匹配com.test.controller.client包路径下,所有以Controller结尾的接口

@Around 表示匹配com.test包路径下,所有的以Controller结尾的接口,并排除了上面@Pointcut匹配的接口

@Order用来控制切面执行的顺序,数字越小,越早执行

3、修改请求参数的值

@Aspect
@Component
@Order(-99)
public class SdkDefaultProjectAspect{

    @Pointcut("execution( public * com.test.controller.client.*Controller.*( .. ))")
    public void openApiController(){
    }
    
    @Around("!openApiController() && execution(public * com.test..*Controller.*( .. ))")
    public Object dealSdkProjectId(ProceedingJoinPoint joinPoint){
        //获取方法签名
        MethodSignature ms = (MethodSignature)joinPoint.getSignature();
        Class<?> targetCls = joinPoint.getTarget().getClass();
        Method method = targetCls.getDeclaredMethod(ms.getName(),ms.getParameterTypes());
        //获取指定方法的参数名
        ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
        String[] parameterNames = pnd.getParameterNames(method);
        //循环判断处理方法参数
        Object[] args = joinPoint.getArgs();
        for(int i = 0;i<args.length;i++){
            String parameterName = parameterNames[i];
            Object target = args[i];
            if("projectId".equals(parameterName)){
                args[i] = DEFAULT_PROJEECT;
                break;
            }else if(target instanceof BaseAuthDTO && ((BaseAuthDTO)target).getProjectId == null){
                (BaseAuthDTO)target).setProjectId(DEFAULT_PROJEECT);
                break;
            }
        }
        joinPoint.proceed(args);
    }

}

1、ParameterNameDiscoverer用于获取方法参数的名称,例如方法为void test(String name,Integer age);,则返回["name","age"]的数组。

2、要使修改的参数值生效,需要使用joinPoint.proceed(Object[] args);将修改的参数传递进去,否则无法修改。如下图,joinPoint.proceed()有两个重载的方法,方法带入参的才能修改参数值。