SpringBoot三大组件之过滤器(Filter)
<h1 id="一概述">一、概述</h1><h2 id="11-含义">1.1 含义</h2>
<p>过滤器是<code>Web</code>三大组件之一,也是项目中常用的工具。过滤器由<code>Servlet</code>提供,基于函数回调实现链式对网络请求和响应的拦截与修改。由于基于<code>Servlet</code>,几乎可以拦截<code>Web</code>服务器管理的所有资源(<code>JSP</code>、图片文件、<code>HTML</code>文件、<code>CSS</code>文件等)。</p>
<p>定义过滤器需要实现<code>javax.servlet.Filter</code>接口。过滤器不是<code>Servlet</code>,无法直接生成对客户端的响应,只能拦截已有请求并预处理不需要或不一致的信息资源。</p>
<h2 id="12-流程原理">1.2 流程原理</h2>
<p>在<code>Web</code>应用中,可以开发编写多个过滤器,这些过滤器组合称为<strong>过滤器链</strong>。用户发起请求后,请求信息会按过滤器链中过滤器的顺序依次进入每个过滤器。经过每层过滤器时,需通过过滤器的校验逻辑并放行才能进入下一层过滤器,直至服务器获取资源。服务器成功获取资源并响应过滤器后,会按反向顺序经过层层过滤器,最终响应用户。</p>
<p><img src="https://i-blog.csdnimg.cn/img_convert/d68164a6c7b3a06621fbb64e2268e3d9.png" alt="1.png" loading="lazy"></p>
<h2 id="13-分类">1.3 分类</h2>
<p>Servlet 2.5:</p>
<ul>
<li>REQUEST: 用户直接访问页面时,<code>WEB</code>容器会调用过滤器链。</li>
<li>FORWARD: 通过<code>RequestDispatcher</code>的<code>forward</code>访问目标资源时调用此过滤器。</li>
<li>INCLUDE: 通过<code>RequestDispatcher</code>的<code>include</code>方法调用目标资源时调用。</li>
<li>ERROR: 通过声明式异常处理机制调用目标资源时调用过滤器链。</li>
</ul>
<p>Servlet 3.0:</p>
<ul>
<li>ASYNC: 支持异步处理。</li>
</ul>
<h1 id="二定义过滤器">二、定义过滤器</h1>
<table>
<thead>
<tr>
<th>返回值类型</th>
<th>方法声明</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>void</td>
<td>doFilter(ServletRequest request, ServletResponse response, FilterChain chain)</td>
<td>实现实际过滤操作。当客户端请求方法与过滤器设置的<code>URL</code>匹配时,<code>Servlet</code>容器会先调用过滤器的<code>doFilter</code>方法。<code>FilterChain</code>用于访问后续过滤器。</td>
</tr>
<tr>
<td>void</td>
<td>init(FilterConfig filterConfig)</td>
<td><code>Web</code>应用启动时,<code>Web</code>服务器创建过滤器实例对象并调用其<code>init</code>方法完成对象初始化(过滤器对象仅创建一次,<code>init</code>方法仅执行一次)。开发者可通过<code>init</code>方法参数执行读取配置文件等初始化操作。</td>
</tr>
<tr>
<td>void</td>
<td>destroy()</td>
<td><code>Servlet</code>容器销毁过滤器实例前调用此方法。用于释放过滤器占用的资源。</td>
</tr>
</tbody>
</table>
<ul>
<li>request: 代表客户端的请求对象。</li>
<li>response: 代表服务器向客户端发送的响应对象。</li>
<li>chain: 用于调用下一个<code>Filter</code>或目标<code>Servlet</code>的<code>FilterChain</code>对象。</li>
</ul>
<h1 id="三使用过滤器">三、使用过滤器</h1>
<h2 id="31-注解方式">3.1 注解方式</h2>
<p>创建步骤:</p>
<ol>
<li>
<p>实现<code>Filter</code>接口,添加<code>@WebFilter</code>和<code>@Order</code>注解配置过滤器:</p>
<pre><code class="language-java">@Order(1)
@WebFilter(filterName = "myFilter", urlPatterns = {"*"})
public class MyCustomFilter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) {
//TODO...
}
@Override
public void destroy() {}
}
</code></pre>
</li>
<li>
<p>在启动类添加<code>@ServletComponentScan</code>注解:</p>
<pre><code class="language-java">@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
</code></pre>
</li>
</ol>
<h2 id="32-注册bean方式">3.2 注册Bean方式</h2>
<ol>
<li>创建实现<code>Filter</code>接口的过滤器类:<pre><code class="language-java">public class MyCustomFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { }
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) {
//TODO...
}
@Override
public void destroy() { }
}
</code></pre>
</li>
<li>创建过滤器配置类,注册过滤器:<pre><code class="language-java">@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean customFilter(){
FilterRegistrationBean<MyCustomFilter2> filterBean = new FilterRegistrationBean<>();
filterBean.setFilter(new MyCustomFilter2());
filterBean.setName("myFilter");
filterBean.addUrlPatterns("/*");
return filterBean;
}
}
</code></pre>
</li>
</ol>
<h1 id="四注解方式">四、注解方式</h1>
<h2 id="41-参数说明">4.1 参数说明</h2>
<p><code>@WebFilter</code>可配置多个参数,部分参数说明如下:</p>
<table>
<thead>
<tr>
<th>参数名称</th>
<th>参数类型</th>
<th>参数描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>description</td>
<td>String</td>
<td>设置过滤器的描述信息</td>
</tr>
<tr>
<td>displayName</td>
<td>String</td>
<td>要显示的过滤器名称</td>
</tr>
<tr>
<td>initParams</td>
<td>WebInitParam[]</td>
<td>你可以在初始化时配置一些参数</td>
</tr>
<tr>
<td>filterName</td>
<td>String</td>
<td>过滤器的名称</td>
</tr>
<tr>
<td>servletNames</td>
<td>String[]</td>
<td>设置要过滤的Servlets</td>
</tr>
<tr>
<td>value</td>
<td>String[]</td>
<td>urlPatterns属性与urlPatterns属性的作用相同,两者都指定要拦截的路径</td>
</tr>
<tr>
<td>urlPatterns</td>
<td>String[]</td>
<td>指定要拦截的路径</td>
</tr>
<tr>
<td>dispatcherTypes</td>
<td>DispatcherType[]</td>
<td>设置过滤器过滤的请求类型。<br>支持以下属性:REQUEST(默认情况下,它过滤所有类型的请求),<br>ASYNC, ERROR, FORWARD, INCLUDE</td>
</tr>
<tr>
<td>asyncSupported</td>
<td>boolean</td>
<td>设置过滤器是否支持异步模式</td>
</tr>
</tbody>
</table>
<h2 id="42-使用示例">4.2 使用示例</h2>
<p>(1) 创建Controller类</p>
<pre><code class="language-java">@RestController
public class TestController {
@GetMapping("/a/hello")
public String hello1() {
return "hello world! a";
}
@GetMapping("/b/hello")
public String hello2() {
return "hello world! b";
}
@GetMapping("/c/hello")
public String hello3() {
return "hello world! c";
}
}
</code></pre>
<p>(2) 创建过滤器类</p>
<pre><code class="language-java">@Order(1)
@WebFilter(filterName = "myFilter", urlPatterns = {"/a/*", "/b/*"}, description = "自定义过滤器")
public class MyCustomFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) {
System.out.println("过滤器初始化");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("请求处理前...");
chain.doFilter(request, response);// 放行请求
System.out.println("请求处理后...");
}
@Override
public void destroy() {
System.err.println("过滤器销毁");
}
}
</code></pre>
<p>(3) 创建启动类</p>
<pre><code class="language-java">@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
</code></pre>
<h1 id="五注册bean方式">五、注册Bean方式</h1>
<h2 id="51-方法参数说明">5.1 方法参数说明</h2>
<table>
<thead>
<tr>
<th>方法名称</th>
<th>方法描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>setName()</td>
<td>设置过滤器的名称。</td>
</tr>
<tr>
<td>setFilter()</td>
<td>设置要注册的过滤器。</td>
</tr>
<tr>
<td>setOrder()</td>
<td>设置过滤器的顺序位置。</td>
</tr>
<tr>
<td>setAsyncSupported()</td>
<td>设置过滤器是否支持异步模式。</td>
</tr>
<tr>
<td>addUrlPatterns()</td>
<td>添加拦截的路径。</td>
</tr>
<tr>
<td>setUrlPatterns()</td>
<td>设置拦截的路径。</td>
</tr>
<tr>
<td>addServletNames()</td>
<td>添加过滤器的servlet名称。</td>
</tr>
<tr>
<td>setServletNames()</td>
<td>设置注册过滤器的servlet名称。</td>
</tr>
<tr>
<td>setInitParameters()</td>
<td>设置初始化参数。</td>
</tr>
<tr>
<td>addInitParameter()</td>
<td>添加初始化参数。</td>
</tr>
<tr>
<td>setMatchAfter()</td>
<td>设置是否在Servlet上下文中声明的任何过滤器映射之后匹配过滤器映射。</td>
</tr>
<tr>
<td>setDispatcherTypes()</td>
<td>设置过滤器过滤的请求类型。<br>支持的属性如下:REQUEST(默认情况下,它过滤所有类型的请求),<br>ASYNC, ERROR, FORWARD, INCLUDE。</td>
</tr>
</tbody>
</table>
<h2 id="52-使用示例">5.2 使用示例</h2>
<p>(1) 创建Controller类</p>
<pre><code class="language-java">@RestController
public class TestController {
@GetMapping("/a/hello")
public String hello1(){
return"hello world! a";
}
@GetMapping("/b/hello")
public String hello2(){
return"hello world! b";
}
@GetMapping("/c/hello")
public String hello3(){
return"hello world! c";
}
}
</code></pre>
<p>(2) 创建过滤器类</p>
<pre><code class="language-java">public class MyCustomFilter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) {
System.out.println("过滤器初始化");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("请求处理前...");
chain.doFilter(request, response);// 放行请求
System.out.println("请求处理后...");
}
@Override
public void destroy() {
System.err.println("过滤器销毁");
}
}
</code></pre>
<p>(3) 创建过滤器配置类</p>
<pre><code class="language-java">@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean customFilter() {
FilterRegistrationBean<MyCustomFilter1> filterBean = new FilterRegistrationBean<>();
filterBean.setFilter(new MyCustomFilter1());
filterBean.setName("FilterController");
filterBean.addUrlPatterns("/c/*", "/b/*");
return filterBean;
}
}
</code></pre>
<p>(4) 创建启动类</p>
<pre><code class="language-java">@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
</code></pre>
<h1 id="六使用场景">六、使用场景</h1>
<ol>
<li>日志记录<br>
过滤器可记录请求和响应的关键信息,便于排查问题和分析系统运行状态。例如记录请求<code>URL</code>、参数、响应状态码等。</li>
<li>数据统计<br>
用于采集各类数据指标,如统计请求次数、响应时间分布等,为系统优化提供依据。</li>
<li>数据格式转换<br>
不同系统交互时,过滤器可转换数据格式,例如将<code>JSON</code>转为<code>XML</code>。</li>
<li>为数据设置默认值<br>
检查输入数据,为缺失字段设置默认值,保证数据完整性。</li>
<li>权限认证、黑白名单<br>
实现用户权限认证和访问控制,限制特定<code>IP</code>或用户的访问。</li>
<li>数据加解密、签名验证<br>
对敏感数据加解密以保证安全,同时进行签名验证确保数据完整性。</li>
</ol><br><br>
来源:https://www.cnblogs.com/ciel717/p/18865719
頁:
[1]