1. Solution using Servlet filter(after Filter doFilter) ## Here, Not recommending this solution.
Filters intercept requests before they reach the DispatcherServlet, making them ideal for coarse-grained tasks such as:
- Authentication
- Logging and auditing
- Image and data compression
- Any functionality we want to be decoupled from Spring MVC
Note* Do the doFilter first before trying to do the call to getAttribute
Your Controller
@RequestMapping(path = "/user")
@RestController
public class ConfigUserController {
@GetMapping(path = "/variables/")
public ResponseEntity<List<Variable>> getAllVariables() {
return null;
}
@GetMapping(path = "/variables/{name}")
public ResponseEntity<Variable> getVariableByName(@PathVariable("name") String name) {
return new ResponseEntity<Variable>(new Variable(name), HttpStatus.OK);
}
@PutMapping(path = "/variables/{name}/{value}")
public ResponseEntity<Variable> setVariableByName() {
return null;
}
}
Custom Filter
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO
try {
chain.doFilter(request, response);
} catch (Exception e) {
} finally {
String pattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
System.out.println("Request template is, " + pattern);
}
}
}
O/P:
Request template is, /user/variables/{name}
Note* Do the chain.doFilter first before trying to do the call to getAttribute
2. Solution using Interceptor
HandlerIntercepors intercepts requests between the DispatcherServlet and our Controllers. This is done within the Spring MVC framework, providing access to the Handler and ModelAndView objects.
Custom Interceptor
@Component
public class LoggerInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception arg3)
throws Exception {
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView model)
throws Exception {
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
String path = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
System.out.println("path : " + path);
return true;
}}
Register it with InterceptorRegistry
@Component
public class CustomServiceInterceptorAppConfig implements WebMvcConfigurer {
@Autowired
LoggerInterceptor loggerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggerInterceptor);
}
}

3. Solution using Java Reflection API.
Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created. It's a one time process, you don't worry about the performance.
You may pre-scan all @RequestMapping,@GetMapping, @PostMApping etc.. annotations, keep it and then in the filter match the pattern to get the desired result.
Here is the sample
Bean
@Configuration
public class Config {
@Bean
public List<String> getPatterns() throws ClassNotFoundException {
List<String> str = new ArrayList<String>();
Class clazz = Class.forName("com.example.demo.controller.ConfigUserController"); // or list of controllers,
// //you can iterate that
// list
for (Method method : clazz.getMethods()) {
for (Annotation annotation : method.getDeclaredAnnotations()) {
if (annotation.toString().contains("GetMapping")) {
str.add(annotation.toString());
System.out.println("Annotation is..." + annotation.toString());
}
if (annotation.toString().contains("PutMapping")) {
str.add(annotation.toString());
System.out.println("Annotation is..." + annotation.toString());
}
if (annotation.toString().contains("PostMapping")) {
str.add(annotation.toString());
System.out.println("Annotation is..." + annotation.toString());
}
}
}
return str;
}
Custom Filter
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomFilter implements Filter {
@Autowired
Config con;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO
try {
//filter match the pattern to get the desired result
System.out.println(con.getPatterns());
} catch (ClassNotFoundException e) {
}
chain.doFilter(request, response);
}