Suivre wx commun : CodingTechWork
introduction
Au cours du processus de développement, il y aura des exigences pour convertir complètement certains paramètres d'entrée de méthode de la couche contrôleur. La chose la plus simple à laquelle penser peut être que lors de l'appel de la méthode de service de la couche inférieure, la méthode publique est appelée pour effectuer le paramètre d'entrée conversion Le seul problème apporté à ce moment Le code est disgracieux et redondant. Existe-t-il donc un moyen de résoudre ce problème de manière plus élégante? La réponse est oui : les facettes.
Nous implémentons un programme d'aspect AOP pour effectuer une conversion spéciale sur les paramètres qui doivent être convertis dans les paramètres d'entrée, sans qu'il soit nécessaire d'effectuer un traitement de conversion dans chaque méthode de chaque couche de contrôleur.
pratique
classe contrôleur
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!";
}
}
Nouilles
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);
}
}
}
vérifier
Pas d'interface de test de paramètres 1
- appel d'interface
- journal de la console
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!
- Analyse des résultats
Aucun paramètre n'est obtenu et l'interface est utilisée normalement. Imprimerno fields!
sans convertir les arguments.
Ne contient pas l'interface de test de paramètre spécifiée 2
-
appel d'interface
-
journal de la console
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!
- Analyse du résultat
Les paramètres spécifiés ne sont pas obtenus et l'interface est utilisée normalement. Imprimerno name field!
sans convertir les arguments.
Contient l'interface de test de paramètre spécifiée 3
-
appel d'interface
-
journal de la console
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
- Analyse du résultat
Le paramètre spécifié est obtenu, la valeur du nom est remplacée parsystem
, et le paramètre de conversion d'aspect est réussi.