Spring使用spel表达式获取参数值

/ Java / 没有评论 / 1961浏览

spring使用spel表达式获取参数值

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- aop -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Limiter {
    /**
     * 使用spel表达式获取限流的key
     * @return
     */
    String value();
}

aop

@Aspect
@Component
public class LimiterAspect {
    private ExpressionParser parser = new SpelExpressionParser();
    private LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();

    @Pointcut("@annotation(limiter)")
    public void pointcut(Limiter limiter) {
    }

    @Around("pointcut(limiter)")
    public Object around(ProceedingJoinPoint pjp, Limiter limiter) throws Throwable {
        Method method = this.getMethod(pjp);
        String methodName = method.toString();

        //获取方法的参数值
        Object[] args = pjp.getArgs();
        EvaluationContext context = this.bindParam(method, args);

        //根据spel表达式获取值
        Expression expression = parser.parseExpression(limiter.value());
        Object key = expression.getValue(context);
        //打印
        System.out.println(key);

        return pjp.proceed();
    }

    /**
	 * 获取当前执行的方法
	 *
	 * @param pjp
	 * @return
	 * @throws NoSuchMethodException
	 */
    private Method getMethod(ProceedingJoinPoint pjp) throws NoSuchMethodException {
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        Method method = methodSignature.getMethod();
        Method targetMethod = pjp.getTarget().getClass().getMethod(method.getName(), method.getParameterTypes());
        return targetMethod;
    }

    /**
	 * 将方法的参数名和参数值绑定
	 *
	 * @param method 方法,根据方法获取参数名
	 * @param args   方法的参数值
	 * @return
	 */
    private EvaluationContext bindParam(Method method, Object[] args) {
        //获取方法的参数名
        String[] params = discoverer.getParameterNames(method);

        //将参数名与参数值对应起来
        EvaluationContext context = new StandardEvaluationContext();
        for (int len = 0; len < params.length; len++) {
            context.setVariable(params[len], args[len]);
        }
        return context;
    }
}

controller

@RestController
public class TestController {

	//获取名为id的参数
	@Limiter("#id")
	@GetMapping("test")
	public String test(Long id){
	    return "hello";
	}
}

测试

curl http://localhost:8080/test?id=123
控制台:
123