Java | Use aspect AOP to intercept and modify Controller interface request parameters

Follow common wx: CodingTechWork

introduction

  During the development process, there will be some requirements to fully convert some method input parameters of the controller layer. The easiest thing to think of may be that when calling the service method of the lower layer, the public method is called to perform input parameter conversion. The only problem brought about at this time The code is unsightly and redundant. So is there any way to solve this problem more elegantly? The answer is yes: facets.
  We implement an AOP aspect program to perform special conversion on the parameters that need to be converted in the input parameters, without the need to perform conversion processing in each method of each controller layer.

practice

controller class

package com.test.selfcoding.controller;

import com.test.selfcoding.bean.PersonBean;
import com.test.selfcoding.service.HelloWorldService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @Description controller
 * @Author Liao Jy
 * @Date 2023/6/28
 */
@RestController
@RequestMapping("/hello/world")
public class HelloWorldController {
    
    

    @Autowired
    private HelloWorldService helloWorldService;

    @GetMapping("/test1")
    public String testGetHelloWorld() {
    
    
        return helloWorldService.getHelloWolrd();
    }

    @PostMapping("/test2")
    public String testPostHelloWord(@RequestBody PersonBean personBean) {
    
    
        return helloWorldService.postHelloWorld(personBean);
    }

    @GetMapping("/test3")
    public String testPostHelloWord(@RequestParam String personName) {
    
    
        return personName + ", hi world!";
    }

}

Noodles

package com.test.selfcoding.aspect;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
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.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;

/**
 * @Description DefaultArgumentsAspect
 * @Author LiaoJy
 * @Date 2023/6/28
 */

@Component
@Aspect
@Slf4j
public class DefaultArgumentsAspect {
    
    
    @Before(value = "execution(* com.test.selfcoding.controller..*(..))")
    public void doBefore(JoinPoint joinPoint) {
    
    
        try {
    
    
        	//获取入参列表
            Object[] args = joinPoint.getArgs();
            log.info("args: {}", JSON.toJSONString(args));
            //入参判空
            if (null == args || args.length == 0) {
    
    
                log.info("no fields!");
                return;
            }
            //获取第一个入参(主要针对@RequestBody,一般只会有一个入参,若遇到多个@RequestParam,需循环处理)
            Object arg = args[0];
            //获取字段域
            Field[] fields = arg.getClass().getDeclaredFields();
            log.info("getDeclaredFields: {}", JSON.toJSONString(fields));
			//判断入参中是否有"name"
            if (Arrays.stream(fields).noneMatch(item -> "name".equals(item.getName()))) {
    
    
                log.info("no name field!");
                return;
            }
            //入参中有"name",获取该字段
            Field field = arg.getClass().getDeclaredField("name");
            //判断是否可使用
            boolean accessible = ((!Modifier.isPublic(field.getModifiers())
                    || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
                    || Modifier.isFinal(field.getModifiers())) && !field.isAccessible());
            //若不可用,则需要进行setAccessible
            if (accessible) {
    
    
                ServletRequestAttributes attributes
                        = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                // 获取request对象
                HttpServletRequest request = attributes.getRequest();
                log.info("method name: {}", request.getRequestURI());
                field.setAccessible(true);
                //将name参数替换为system
                field.set(arg, "system");
            }
        } catch (Exception e) {
    
    
            log.error("切面参数设置异常", e);
        }
    }
}

verify

No parameter test interface 1

  1. interface call
    insert image description here
  2. console log
2023-06-28 18:06:06.060  INFO 6495 --- [nio-8001-exec-1] c.t.s.aspect.DefaultArgumentsAspect      : args: []
2023-06-28 18:06:06.061  INFO 6495 --- [nio-8001-exec-1] c.t.s.aspect.DefaultArgumentsAspect      : no fields!
2023-06-28 18:06:06.066  INFO 6495 --- [nio-8001-exec-1] c.t.s.s.impl.HelloWorldServiceImpl       : getHelloWolrd() get str success.
result: hugh, hello world!
  1. Result Analysis
    No parameters are obtained, and the interface is used normally. Print no fields!without converting arguments.

Does not contain the specified parameter test interface 2

  1. interface call
    insert image description here

  2. console log

2023-06-28 18:08:04.040  INFO 6495 --- [nio-8001-exec-5] c.t.s.aspect.DefaultArgumentsAspect      : args: ["xiaowang"]
2023-06-28 18:08:04.055  INFO 6495 --- [nio-8001-exec-5] c.t.s.aspect.DefaultArgumentsAspect      : getDeclaredFields: [{
    
    "accessible":false,"annotatedType":{
    
    "annotatedGenericComponentType":{
    
    "annotations":[],"declaredAnnotations":[],"type":"char"},"annotations":[],"declaredAnnotations":[],"type":"[C"},"annotations":[],"declaringClass":"java.lang.String","enumConstant":false,"genericType":"[C","modifiers":18,"name":"value","synthetic":false,"type":"[C"},{
    
    "accessible":false,"annotatedType":{
    
    "annotations":[],"declaredAnnotations":[],"type":"int"},"annotations":[],"declaringClass":"java.lang.String","enumConstant":false,"genericType":"int","modifiers":2,"name":"hash","synthetic":false,"type":"int"},{
    
    "accessible":false,"annotatedType":{
    
    "annotations":[],"declaredAnnotations":[],"type":"long"},"annotations":[],"declaringClass":"java.lang.String","enumConstant":false,"genericType":"long","modifiers":26,"name":"serialVersionUID","synthetic":false,"type":"long"},{
    
    "accessible":false,"annotatedType":{
    
    "annotatedGenericComponentType":{
    
    "annotations":[],"declaredAnnotations":[],"type":"java.io.ObjectStreamField"},"annotations":[],"declaredAnnotations":[],"type":"[Ljava.io.ObjectStreamField;"},"annotations":[],"declaringClass":"java.lang.String","enumConstant":false,"genericType":"[Ljava.io.ObjectStreamField;","modifiers":26,"name":"serialPersistentFields","synthetic":false,"type":"[Ljava.io.ObjectStreamField;"},{
    
    "accessible":false,"annotatedType":{
    
    "annotatedActualTypeArguments":[{
    
    "annotations":[],"declaredAnnotations":[],"type":"java.lang.String"}],"annotations":[],"declaredAnnotations":[],"type":{
    
    "actualTypeArguments":["java.lang.String"],"rawType":"java.util.Comparator","typeName":"java.util.Comparator<java.lang.String>"}},"annotations":[],"declaringClass":"java.lang.String","enumConstant":false,"genericType":{
    
    "$ref":"$[4].annotatedType.type"},"modifiers":25,"name":"CASE_INSENSITIVE_ORDER","synthetic":false,"type":"java.util.Comparator"}]
2023-06-28 18:08:04.056  INFO 6495 --- [nio-8001-exec-5] c.t.s.aspect.DefaultArgumentsAspect      : no name field!
  1. Result Analysis
    The specified parameters are not obtained, and the interface is used normally. Print no name field!without converting arguments.

Contains the specified parameter test interface 3

  1. interface call
    insert image description here

  2. console log

2023-06-28 18:10:15.481  INFO 6495 --- [nio-8001-exec-9] c.t.s.aspect.DefaultArgumentsAspect      : args: [{
    
    "age":1,"name":"xiaohong"}]
2023-06-28 18:10:15.482  INFO 6495 --- [nio-8001-exec-9] c.t.s.aspect.DefaultArgumentsAspect      : getDeclaredFields: [{
    
    "accessible":false,"annotatedType":{
    
    "annotations":[],"declaredAnnotations":[],"type":"java.lang.String"},"annotations":[],"declaringClass":"com.test.selfcoding.bean.PersonBean","enumConstant":false,"genericType":"java.lang.String","modifiers":2,"name":"name","synthetic":false,"type":"java.lang.String"},{
    
    "accessible":false,"annotatedType":{
    
    "annotations":[],"declaredAnnotations":[],"type":"int"},"annotations":[],"declaringClass":"com.test.selfcoding.bean.PersonBean","enumConstant":false,"genericType":"int","modifiers":2,"name":"age","synthetic":false,"type":"int"}]
2023-06-28 18:10:15.482  INFO 6495 --- [nio-8001-exec-9] c.t.s.aspect.DefaultArgumentsAspect      : method name: /hello/world/test2
  1. Result analysis
    The specified parameter is obtained, and the name value is replaced with system, and the aspect conversion parameter is successful.

Guess you like

Origin blog.csdn.net/Andya_net/article/details/131442326