Spring AOP:如何从 URI 模板中读取路径变量值?

Mic*_*ksa 4 spring aspectj spring-mvc spring-aop

我想创建 Spring 方面,它将通过自定义注释注释的方法参数设置为由 URI 模板中的 id 标识的特定类的实例。路径变量名是注解的参数。与 Spring@PathVariable所做的非常相似。

所以控制器方法看起来像:

@RestController
@RequestMapping("/testController")
public class TestController {

    @RequestMapping(value = "/order/{orderId}/delete", method = RequestMethod.GET)
    public ResponseEntity<?> doSomething(
            @GetOrder("orderId") Order order) {

        // do something with order
    }

}
Run Code Online (Sandbox Code Playgroud)

而不是经典:

@RestController
@RequestMapping("/testController")
public class TestController {

    @RequestMapping(value = "/order/{orderId}/delete", method = RequestMethod.GET)
    public ResponseEntity<?> doSomething(
            @PathVariable("orderId") Long orderId) {

        Order order = orderRepository.findById(orderId);
        // do something with order
    }
}
Run Code Online (Sandbox Code Playgroud)

注释来源:

// Annotation
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface GetOrder{

    String value() default "";
}
Run Code Online (Sandbox Code Playgroud)

方面来源:

// Aspect controlled by the annotation
@Aspect
@Component
public class GetOrderAspect {

    @Around( // Assume the setOrder method is called around controller method )
    public Object setOrder(ProceedingJoinPoint jp) throws Throwable{

        MethodSignature signature = (MethodSignature) jp.getSignature();
        @SuppressWarnings("rawtypes")
        Class[] types = signature.getParameterTypes();
        Method method = signature.getMethod();
        Annotation[][] annotations = method.getParameterAnnotations();
        Object[] values = jp.getArgs();

        for (int parameter = 0; parameter < types.length; parameter++) {
            Annotation[] parameterAnnotations = annotations[parameter];
            if (parameterAnnotations == null) continue;

            for (Annotation annotation: parameterAnnotations) {
                // Annotation is instance of @GetOrder
                if (annotation instanceof GetOrder) {
                    String pathVariable = (GetOrder)annotation.value();                        

                    // How to read actual path variable value from URI template?
                    // In this example case {orderId} from /testController/order/{orderId}/delete

                    HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder
                            .currentRequestAttributes()).getRequest();
                    ????? // Now what?

                }
           } // for each annotation
        } // for each parameter
        return jp.proceed();
    }
}
Run Code Online (Sandbox Code Playgroud)

2017 年 4 月 4 日更新:

Mike Wojtyna给出的答案回答了这个问题 -> 因此它被接受了。

OrangeDog给出的答案从不同的角度解决了现有 Spring 工具的问题,而不会冒险使用新方面的实现问题。早知道就不会问这个问题了。

谢谢!

Mik*_*yna 5

如果您已经有权访问HttpServletRequest,则可以使用HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTEspring 模板来选择请求中所有属性的映射。你可以这样使用它:

request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE)
Run Code Online (Sandbox Code Playgroud)

结果是一个Map实例(不幸的是您需要强制转换为它),因此您可以迭代它并获取您需要的所有参数。