赞
踩
在开发过程中,会有一些需求将controller层的一些方法入参进行全量转换,最容易想到的可能是在调用下层service方法时,调用公共的方法进行入参转换,这时带来的唯一问题就是代码不雅观,比较冗余。那还有什么方法可以更优雅的解决这个问题吗?答案是有的:切面。
我们实现一个AOP切面程序,对入参中的需转换的参数进行专项转换,而无需在各个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); } } }
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!
no fields!
,无需转换参数。接口调用
控制台日志
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!
no name field!
,无需转换参数。接口调用
控制台日志
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
system
,切面转换参数成功。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。