本文介绍: 在开发过程中,会有一些需求controller层的一些方法入参进行全量转换,最容易想到的可能是在调用下层service方法时,调用公共方法进行入参转换,这时带来的唯一问题就是代码不雅观,比较冗余。那还有什么方法可以更优雅的解决这个问题吗?答案是有的:切面我们实现一个AOP切面程序,对入参中的需转换的参数进行专项转换,而无需在各个controller层的各个方法中进行转换处理

关注common wx: CodingTechWork

引言

  在开发过程中,会有一些需求controller层的一些方法入参进行全量转换,最容易想到的可能是在调用下层service方法时,调用公共方法进行入参转换,这时带来的唯一问题就是代码不雅观,比较冗余。那还有什么方法可以更优雅的解决这个问题吗?答案是有的:切面
  我们实现一个AOP切面程序,对入参中的需转换的参数进行专项转换,而无需在各个controller层的各个方法中进行转换处理

实践

controller

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!";
    }

}

切面

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);
        }
    }
}

验证

无参测试接口1

  1. 接口调用
    在这里插入图片描述
  2. 控制台日志
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. 结果分析
    获取参数,正常走接口打印no fields!,无需转换参数

包含指定参数测试接口2

  1. 接口调用
    在这里插入图片描述

  2. 控制台日志

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. 结果分析
    获取指定参数,正常走接口。打印no name field!,无需转换参数。

包含指定参数测试接口3

  1. 接口调用
    在这里插入图片描述

  2. 控制日志

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. 结果分析
    获取指定的参数,进行name值替换system切面转换参数成功

原文地址:https://blog.csdn.net/Andya_net/article/details/131442326

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_43236.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注