Maison >Java >javaDidacticiel >Springboot implémente le transfert dynamique de paramètres via spel combiné avec aop
Avant de commencer à écrire le code, comprenez d'abord les expressions SpEl (Spring Expression Language), qui sont un outil puissant dans le framework Spring
Spring peut construire des expressions complexes et accéder aux objets au moment de l'exécution via les attributs SpEl, appels de méthode objet, etc.
Un exemple simple pour faciliter la compréhension, comme suit
//定义了一个表达式 String expressionStr = "1+1"; ExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression(expressionStr); Integer val = expression.getValue(Integer.class); System.out.println(expressionStr + "的结果是:" + val);
Grâce aux cas ci-dessus, il n'est pas difficile de comprendre que ce qu'on appelle SpEl est en fait une expression analytique.
À propos des expressions SpEl Si vous Si vous êtes intéressé, vous pouvez vérifier les informations par vous-même. Cet article n'en discutera pas en détail
Ayez une brève compréhension des expressions SpEl, puis commençons directement par le code.
Introduisez d'abord la dépendance pom nécessaire, en fait, uniquement la dépendance aop, SpEl lui-même est pris en charge par Spring, il n'est donc pas nécessaire de l'introduire en plus
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
Définir une classe d'outils SpEl SpelUtil
public class SpelUtil { /** * 用于SpEL表达式解析. */ private static final SpelExpressionParser parser = new SpelExpressionParser(); /** * 用于获取方法参数定义名字. */ private static final DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer(); /** * 解析SpEL表达式 * * @param spELStr * @param joinPoint * @return */ public static String generateKeyBySpEL(String spELStr, ProceedingJoinPoint joinPoint) { // 通过joinPoint获取被注解方法 MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); Method method = methodSignature.getMethod(); // 使用Spring的DefaultParameterNameDiscoverer获取方法形参名数组 String[] paramNames = nameDiscoverer.getParameterNames(method); // 解析过后的Spring表达式对象 Expression expression = parser.parseExpression(spELStr); // Spring的表达式上下文对象 EvaluationContext context = new StandardEvaluationContext(); // 通过joinPoint获取被注解方法的形参 Object[] args = joinPoint.getArgs(); // 给上下文赋值 for (int i = 0; i < args.length; i++) { context.setVariable(paramNames[i], args[i]); } // 表达式从上下文中计算出实际参数值 /*如: @annotation(key="#user.name") method(User user) 那么就可以解析出方法形参的某属性值,return “xiaoming”; */ return expression.getValue(context).toString(); } }
Définir une annotation basée sur des paramètres. SpelGetParm
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface SpelGetParm { String parm() default ""; }
Définir une annotation basée sur des paramètres SpelGetParmAop
@Aspect @Slf4j @Component public class SpelGetParmAop { @PostConstruct public void init() { log.info("SpelGetParm init ......"); } /** * 拦截加了SpelGetParm注解的方法请求 * * @param joinPoint * @param spelGetParm * @return * @throws Throwable */ @Around("@annotation(spelGetParm)") public Object beforeInvoce(ProceedingJoinPoint joinPoint, SpelGetParm spelGetParm) throws Throwable { Object result = null; // 方法名 String methodName = joinPoint.getSignature().getName(); //获取动态参数 String parm = SpelUtil.generateKeyBySpEL(spelGetParm.parm(), joinPoint); log.info("spel获取动态aop参数: {}", parm); try { log.info("执行目标方法: {} ==>>开始......", methodName); result = joinPoint.proceed(); log.info("执行目标方法: {} ==>>结束......", methodName); // 返回通知 log.info("目标方法 " + methodName + " 执行结果 " + result); } finally { } // 后置通知 log.info("目标方法 " + methodName + " 结束"); return result; }
Ce qui précède a essentiellement implémenté les fonctions de base du cas. Ensuite, nous pouvons utiliser cette annotation pour définir une entité User
@Getter @Setter @NoArgsConstructor @JsonSerialize @JsonInclude(Include.NON_NULL) public class User implements Serializable { private static final long serialVersionUID = -7229987827039544092L; private String name; private Long id; }
Nous pouvons directement utiliser cette annotation avec des paramètres dans. le UserController
@CrossOrigin @RestController @RequestMapping("/user") public class UserController { @PostMapping("/param") @SpelGetParm(parm = "#user.name") public R repeat(@RequestBody User user) { return R.success(user); } }
Enfin la demande
On peut voir que l'aspect a obtenu avec succès la valeur du nom de l'entité "Zhang San".
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!