【问题标题】:Read RequestMapping annotation value读取 RequestMapping 注解值
【发布时间】:2020-03-12 14:55:16
【问题描述】:

为了能够对每个端点进行统计,我希望能够获得 @RequestMapping 注释值,即参数化版本。否则我的监控工具会将不同的 id 视为不同的 url:

@RequestMapping(value = "/customers/{customerId}/items/{itemId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
  public ResponseEntity<ItemDetailsDto> getItemById(
      @PathVariable(value = "customerId") int customerId
      @PathVariable(value = "itemId") int itemId)
      throws Exception
  {
    //do stuff

    //I want this to be "/customers/{customerId}/items/{itemId}"
    //,not "/customers/15988/items/85"
    String s = ????
  }

如何在运行时获取/customers/{customerId}/items/{itemId}? 我的工具允许我拦截方法并捕获其参数,因此我还可以监视 Spring 框架中的特定方法以捕获设置或获取某些东西。

【问题讨论】:

    标签: java spring request-mapping


    【解决方案1】:

    你可以使用Java反射来做,你只需要这样做:

    String s= this.getClass().getDeclaredMethod("getItemById", int.class, int.class).getAnnotation(RequestMapping.class).value();
    

    getDeclaredMethod的第一个参数是方法的名称,其他参数是该方法的参数类型。

    【讨论】:

      【解决方案2】:

      另一种方法是

      private static final String URI_GET_ITEM_BY_ID ="/customers/{customerId}/items/{itemId}";
      
      @RequestMapping(value = URI_GET_ITEM_BY_ID, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
        public ResponseEntity<ItemDetailsDto> getItemById(
            @PathVariable(value = "customerId") int customerId
            @PathVariable(value = "itemId") int itemId)
            throws Exception
        {
          //do stuff
      
          // Use URI_GET_ITEM_BY_ID
      
        }
      

      更新 1:

      假设控制器用@RestController注解

      @RestController
      public class SampleController {
      
            @RequestMapping(value = "/customers/{customerId}/items/{itemId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
        public ResponseEntity<ItemDetailsDto> getItemById(
            @PathVariable(value = "customerId") int customerId
            @PathVariable(value = "itemId") int itemId)
            throws Exception
        {
          //do stuff
      
          //I want this to be "/customers/{customerId}/items/{itemId}"
          //,not "/customers/15988/items/85"
          String s = ????
        }
      
      }
      

      以下Aspect 可用于在不更改控制器方法的情况下获取 URI 路径。

      @Aspect
      @Component
      public class RestControllerAspect {
      
          @Pointcut("@within(org.springframework.web.bind.annotation.RestController) && within(rg.boot.web.controller.*)")
          public void isRestController() {
      
          }
      
          @Before("isRestController()")
          public void handlePost(JoinPoint point) {
              MethodSignature signature = (MethodSignature) point.getSignature();
              Method method = signature.getMethod();
      
              // controller method annotations of type @RequestMapping
              RequestMapping[] reqMappingAnnotations = method
                      .getAnnotationsByType(org.springframework.web.bind.annotation.RequestMapping.class);
              for (RequestMapping annotation : reqMappingAnnotations) {
                  System.out.println(annotation.toString());
                  for(String val : annotation.value()) {
                      System.out.println(val);
                  }
              }
      
          }
      }
      

      这会打印出来

      @org.springframework.web.bind.annotation.RequestMapping(path=[], headers=[], method=[GET], name=, produces=[application/json], params=[], value=[/customers/{customerId}/items/{itemId}], consumes=[])
      /customers/{customerId}/items/{itemId}
      

      对于 URI 的请求:/customers/1234/items/5678

      更新 2:

      另一种方式是导入

      import static org.springframework.web.servlet.HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE;
      import org.springframework.web.context.request.RequestContextHolder;
      

      并使用以下代码获取路径

       RequestAttributes reqAttributes = RequestContextHolder.currentRequestAttributes(); 
       String s = reqAttributes.getAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, 0);
      

      这是改编自我的answer另一个问题。

      【讨论】:

      • 是的,这是最简单的解决方案,但我有 200 多个控制器方法,我正试图找到一种在运行时获取它们的单一方法,而不是更改我的 200 个方法。
      • 啊!!那么Spring AOP呢?我也有类似的答案here
      猜你喜欢
      • 1970-01-01
      • 2011-11-27
      • 1970-01-01
      • 2014-07-11
      • 2017-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多