一、Filter介绍
过滤器概念
- 客户端与服务器资源文件之间的一道过滤网;
- 管理Web服务器的所有资源,例如对JSP、Servlet、静态图片文件或静态HTML文件等进行拦截;
- 可以过滤几乎所有的请求,完成一些特殊的功能;
- Filter依赖于Servlet容器,属于Servlet规范的一部分;
- Filter的执行由Servlet容器回调完成;
- Filter的生命周期由Servlet容器管理。
过滤器使用场景
完成通用的操作:登陆验证、URL级别的权限访问控制、压缩响应信息、统一编码处理、过滤敏感字符等等。
过滤器实现步骤
- 定义一个类,实现javax.servlet.Filter接口;
- 复写方法,尤其是doFilter方法,必须实现;
- 配置过滤器信息。
- web.xml
- @WebFilter注解
- @Configuration配置类
过滤器生命周期
Filter的生命周期由Servlet容器管理:
- init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源。
- doFilter:每一次请求被拦截资源时,会执行。执行多次。
- destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源。
过滤器拦截路径配置
- 具体的资源路径: /hello.jsp 只访问hello.jsp资源时,过滤器才会被执行
- 拦截目录: /hello/* 访问/hello下的所有资源时,过滤器才会被执行
- 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器才会被执行
- 拦截所有资源: /* 访问所有资源时,过滤器才会被执行
过滤器拦截请求调度方式配置
- 请求调度方式
- REQUEST:默认值。浏览器直接请求资源
- FORWARD:转发访问资源
- NCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC:异步访问资源
- web.xml配置:<filter-mapping>中的<dispatcher>标签
- @WebFilter注解配置:dispatcherTypes属性
- @Configuration配置类:FilterRegistrationBean对象的dispatcherTypes属性
过滤器链(多个过滤器)调用的先后顺序
- web.xml: <filter-mapping>定义在上边的,先执行
- @WebFilter注解:按照类名的字符串比较规则比较,值小的先执行(注意不是配置的filter的名字)
- 如: AFilter 和 BFilter,AFilter就先执行了。
- 如: AFilter17 和 AFilter6,AFilter17就先执行了。
- @Order注解:值小的先执行
- Configuration配置类:FilterRegistrationBean对象的order属性:值小的先执行
- @WebFilter指定的过滤器优先级都高于FilterRegistrationBean配置的过滤器
过滤器链(多个过滤器)执行的先后顺序
- FilterChain的执行顺序遵循先进后出原则
- 以doFilter方法中调用filterChain.doFilter(servletRequest,servletResponse)的位置为准,这里放行到下一个过滤器;
- filterChain.doFilter位置之前的代码先执行,然后再放行;
- filterChain.doFilter位置之后的代码是响应回来后再执行;
- Request请求被所有的Filter处理之后,返回的顺序是从最后一个开始返回,直到返回给客户端
二、Filter使用
Java Web使用Filter
基于实现Filter + web.xml配置
创建一个类,实现javax.servlet.Filter接口,尤其是doFilter方法;
package com.liutit.filter;
import javax.servlet.*;
import java.io.IOException;
public class DemoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 客户端发送请求经过过滤器,
// 这里一般处理请求对象Request
System.out.println("filter in....");
// 放行
filterChain.doFilter(servletRequest,servletResponse);
// 服务器响应请求后,经过此处,然后再到客户端,
// 这里一般处理响应对象Response
System.out.println("filter out....");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
在web.xml中配置过滤器信息;
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<filter>
<filter-name>demo</filter-name>
<filter-class>com.liutit.filter.DemoFilter</filter-class>
</filter>
<!-- filter-mapping标签定义的位置决定多个过滤器调用的顺序,由上而下依次调用, 与filter标签的定义位置无关-->
<filter-mapping>
<filter-name>demo</filter-name>
<!-- 拦截路径 -->
<url-pattern>/*</url-pattern>
<!-- 拦截方式 -->
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
</web-app>
基于实现Filter + @WebFilter注解
创建一个类,实现javax.servlet.Filter接口,尤其是doFilter方法,并在类上添加@WebFilter注解;
package com.liutit.filter;
import javax.servlet.*;
import java.io.IOException;
@WebFilter("/*")
public class DemoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 客户端发送请求经过过滤器,
// 这里一般处理请求对象Request
System.out.println("filter in....");
// 放行
filterChain.doFilter(servletRequest,servletResponse);
// 服务器响应请求后,经过此处,然后再到客户端,
// 这里一般处理响应对象Response
System.out.println("filter out....");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
Spring Boot使用Filter
pom.xml导入pring-boot-starter-web包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
基于实现Filter + 配置Configuration类
package com.liutit.filter;
import javax.servlet.*;
import java.io.IOException;
public class DemoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 客户端发送请求经过过滤器,
// 这里一般处理请求对象Request
System.out.println("filter in....");
// 放行
filterChain.doFilter(servletRequest,servletResponse);
// 服务器响应请求后,经过此处,然后再到客户端,
// 这里一般处理响应对象Response
System.out.println("filter out....");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
Configuration类
package com.liutit.config;
import com.liutit.filter.DemoFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.DispatcherType;
@Configuration
public class FilterConfiguration {
@Bean
public FilterRegistrationBean registrationFilter() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
// 设置过滤器
filterRegistration.setFilter(new DemoFilter());
// 指定url策略
filterRegistration.addUrlPatterns("/*");
// 指定过滤请求调度方式,默认REQUEST
filterRegistration.setDispatcherTypes(DispatcherType.REQUEST);
// 设置过滤器名称
filterRegistration.setName("demoFilter");
// 过滤器顺序:数字越小,越先执行
filterRegistration.setOrder(1);
return filterRegistration;
}
}
基于实现Filter + @WebFilter注解 + @ServletComponentScan注解
package com.liutit.filter;
import javax.servlet.*;
import java.io.IOException;
@Order(1)
@WebFilter("/*")
public class DemoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 客户端发送请求经过过滤器,
// 这里一般处理请求对象Request
System.out.println("filter in....");
// 放行
filterChain.doFilter(servletRequest,servletResponse);
// 服务器响应请求后,经过此处,然后再到客户端,
// 这里一般处理响应对象Response
System.out.println("filter out....");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
启动类上添加@ServletCoponentScan注解
在启动类上使用@ServletComponentScan注解后,
Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册。
package com.liutit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}