Excluding URLs for a Filter in a Spring Web Application
1.概述
大多数Web应用程序都有执行诸如请求日志记录,验证或身份验证之类的操作的用例。而且,此类任务通常在一组HTTP端点之间共享。
好消息是,Spring Web框架为此提供了一种过滤机制。
在本教程中,我们将学习如何针对给定的URL集在执行中包括或排除执行过滤器样式的任务。
2.过滤特定的URL
假设我们的Web应用程序需要记录一些有关其请求的信息,例如它们的路径和内容类型。一种方法是创建日志记录过滤器。
2.1。记录过滤器
首先,让我们在LogFilter类中创建日志记录过滤器,该类扩展了OncePerRequestFilter类并实现doFilterInternal方法:
1 2 3 4 5 6 7 8 | @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String path = request.getRequestURI(); String contentType = request.getContentType(); logger.info("Request URL path : {}, Request content type: {}", path, contentType); filterChain.doFilter(request, response); } |
2.1。规则过滤器
假设我们只需要对某些URL模式(即/ health,/ faq / *)执行日志记录任务。为此,我们将使用FilterRegistrationBean注册日志记录过滤器,使其仅匹配所需的URL模式:
1 2 3 4 5 6 7 | @Bean public FilterRegistrationBean<LogFilter> logFilter() { FilterRegistrationBean<LogFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new LogFilter()); registrationBean.addUrlPatterns("/health","/faq/*"); return registrationBean; } |
2.2。排除规则过滤器
如果要从执行日志记录任务中排除URL,可以通过两种方式轻松实现:
对于新网址,请确保它与过滤器使用的网址格式不匹配
对于较早启用了日志记录的旧URL,我们可以修改URL模式以排除此URL
3.筛选所有可能的URL
我们很轻松地满足了我们以前的用例,只需很少的工作即可在LogFilter中包括URL。但是,如果过滤器使用通配符(*)来匹配所有可能的URL模式,则将变得更加棘手。
在这种情况下,我们需要自己编写包含和排除逻辑。
3.1。 CustomFilter
客户端可以使用请求标头将有用的信息发送到服务器。假设我们的Web应用程序当前仅在美国运行,这意味着我们不想处理来自其他国家的请求。
让我们进一步想象一下,我们的Web应用程序通过X-Country-Code请求标头指示语言环境。因此,每个请求都包含此信息,并且我们有明确的理由使用过滤器。
让我们实现一个用于检查标题的过滤器,拒绝不符合我们条件的请求:
1 2 3 4 5 6 7 8 9 10 11 12 | @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String countryCode = request.getHeader("X-Country-Code"); if (!"US".equals(countryCode)) { response.sendError(HttpStatus.BAD_REQUEST.value(),"Invalid Locale"); return; } filterChain.doFilter(request, response); } |
3.2。筛选注册
首先, span> 让我们使用 span> 星号(*)通配符来注册我们的过滤器 span> 以匹配所有可能的URL模式: span>
1 2 3 4 5 6 7 | @Bean public FilterRegistrationBean<HeaderValidatorFilter> headerValidatorFilter() { FilterRegistrationBean<HeaderValidatorFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new HeaderValidatorFilter()); registrationBean.addUrlPatterns("*"); return registrationBean; } |
稍后,我们可以排除执行验证区域设置请求标头信息的任务不需要的URL模式。 span>
3.3。网址排除
再次假设我们在/ health处有一个Web路由,可用于对应用程序进行ping-pong运行状况检查。
到目前为止,所有请求都将触发我们的过滤器。我们可以猜测,这是我们进行健康检查的开销。
因此,通过从过滤器主体中排除/ health请求,可以简化它:
1 2 3 4 5 6 7 8 9 10 11 12 | @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String path = request.getRequestURI(); if ("/health".equals(path)) { filterChain.doFilter(request, response); return; } String countryCode = request.getHeader("X-Country-Code"); // ... same as before } |
我们必须注意,在doFilter方法中添加此自定义逻辑会导致/ health端点与我们的过滤器之间的耦合。因此,这不是最佳方法,因为如果更改运行状况检查端点而没有在doFilter方法内进行相应更改,则可能破坏过滤逻辑。
4。结论
在本教程中,我们探讨了如何在两种情况下从Spring Boot Web应用程序的servlet过滤器中排除URL模式:日志记录和请求标头验证。
此外,我们了解到,为使用*通配符匹配所有可能的URL模式的过滤器排除一组特定的URL变得很棘手。
与往常一样,该教程的完整源代码可在GitHub上获得。