简体   繁体   中英

Read RequestMapping annotation value

To be able to do stats per endpoint, I want to be able to get the @RequestMapping annotation value, the parameterized version. My monitoring tool otherwise will consider different ids as different urls:

@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 = ????
  }

How can I grab /customers/{customerId}/items/{itemId} at runtime? My tool allows me to intercept methods and capture its parameters, so I could also monitor a specific method in the Spring framework to catch the setting or getting of something for example.

You can use Java reflection to do so, you just need to do like this:

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

For the getDeclaredMethod the first parameter is the name of method and the other parameters are the parameters' types of that method.

Another approach will be

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

  }

Update 1:

Assuming the controller is annotated with @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 = ????
  }

}

following Aspect can be used to get the URI path without altering the controller methods.

@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);
            }
        }

    }
}

This would print

@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}

for a request to URI : /customers/1234/items/5678

Update 2:

Another way is to import

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

and get the path using the following code

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

This is adapted from my answer to another question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM