1. 使用 Servlet 过滤器的解决方案(在 Filter doFilter 之后)## 这里不推荐该解决方案。
过滤器拦截请求在到达 DispatcherServlet 之前,因此它们非常适合处理粗粒度任务,例如:
- 认证
- 日志记录和审计
- 图像和数据压缩
- 任何我们想要与 Spring MVC 解耦的功能
注意* 在尝试调用 getAttribute 之前,先进行 doFilter
您的控制器
@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;
}
}
自定义筛选器
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
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);
}
}
}
输出:
Request template is, /user/variables/{name}
请注意:在尝试调用getAttribute之前,请先执行chain.doFilter。
2. 使用拦截器的解决方案
HandlerIntercepors用于在DispatcherServlet和我们的控制器之间拦截请求。这是在Spring MVC框架内完成的,提供对处理程序和ModelAndView对象的访问。
自定义拦截器
@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;
}}
在InterceptorRegistry中注册它。
@Component
public class CustomServiceInterceptorAppConfig implements WebMvcConfigurer {
@Autowired
LoggerInterceptor loggerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggerInterceptor);
}
}
3. 使用Java反射API的解决方案。
单例作用域的Bean并设置为预实例化(默认情况下)是在容器创建时创建的。这是一个一次性的过程,您不必担心性能问题。
您可以预先扫描所有的@RequestMapping,@GetMapping, @PostMapping等注释,并保留它们,然后在过滤器中匹配模式以获取所需结果。
以下是示例:
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");
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;
}
自定义筛选器
@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 {
try {
System.out.println(con.getPatterns());
} catch (ClassNotFoundException e) {
}
chain.doFilter(request, response);
}
Set<RequestMappingInfo> patterns
,该集合在ContextRefreshedEvent
中被填充。因此,当我在过滤器中时,可以遍历 RequestMappingInfo 并使用getMatchingCondition(HttpRequest)
获取将要使用的映射,然后使用getPatternsCondition
访问模式。 - moretti.fabio