【发布时间】:2017-04-03 11:32:36
【问题描述】:
我想创建 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
}
}
而不是经典:
@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
}
}
注解来源:
// Annotation
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface GetOrder{
String value() default "";
}
方面来源:
// 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();
}
}
2017 年 4 月 4 日更新:
Mike Wojtyna 给出的答案回答了问题 -> 因此它被接受了。
OrangeDog 给出的答案使用现有 Spring 工具从不同的角度解决了问题,而不会冒新方面的实施问题的风险。如果我早知道,就不会问这个问题了。
谢谢!
【问题讨论】:
-
您是否查看了
@PathVariable使用方式的来源? -
不,我没有,老实说我不知道从哪里开始,这很模糊。
-
顺便说一句,您应该对
/order/{orderId}的网址使用带有删除动词的@DeleteMapping,而不是带有/order/{orderId}/delete网址的“get”。此外,ID 通常更适合作为 uuid,而不是数字。此外,在删除之前不加载资源会浪费计算资源,因为在大多数后备存储中,您可以发出delete by key类型命令。 -
哦,是的,没发现。如果您使用 GET 进行状态更改操作,您将会遇到麻烦。
-
这只是一个例子,简化了实际问题,仅此而已。谢谢您的建议。
标签: spring spring-mvc aspectj spring-aop