动态地拦截请求和响应,变换或使⽤包含在请求或响应中的信息
在客户端的请求访问后端资源之前,拦截这些请求
在服务器的响应发送回客户端之前,处理这些响应
init(FilterConfig filterConfig) //只容器初始化的时候调⽤⼀次,即应⽤启动的时候加载⼀次
doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 只要命中
过滤规则就触发,可以在filter中根据条件决定是否调⽤chain.doFilter(request, response)⽅
法, 即是否让⽬标资源执⾏
destroy() //只容器销毁的时候调⽤⼀次,即应⽤停⽌的时候调⽤⼀次
package jakarta.servlet;
import java.io.IOException;
public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {
}
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
default void destroy() {
}
}
- 自定义filter时,使用@WebFilter的参数
//该Filter是否⽀持异步操作模式
asyncSupported
//指定Filter对那种dispatcher模式进⾏过滤 该属性⽀持 Async,Error
Forward,include,request
dispatcherType
//Filter 显示的名称
displayName
//Filter的名称
filterName
//Filter的配置参数
initParams
//过滤的Servlet可以指定多个,表示对这⼏个特定的的servlet 进⾏过滤
servletNames
//指定 Filter拦截的 URL,和上⾯的servletNames配置⼀样,⽤*可以表示通配符,但是不⽤字⺟后
加*,应该按照模块划分,⽐如/user/*
urlPatterns/value
@WebFilter(filterName = "testFilter",urlPatterns = {"/*"})
public class CustomFilter implements Filter {
/**
* filter初始化
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CustomFilter init ");
}
/**
* filter 拦截处理
* @param request
* @param response
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("CustomFilter doFilter ");
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
// 请求放行
chain.doFilter(request,response);
}
/**
* filter销毁的方法
*/
@Override
public void destroy() {
System.out.println("CustomFilter destroy ");
}
}
# 启动项目时,filter初始化
Connected to server
[2022-04-14 11:12:36,794] Artifact web06:war exploded: Artifact is being deployed, please wait...
14-Apr-2022 11:12:37.891 警告 [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom 使用[SHA1PRNG]创建会话ID生成的SecureRandom实例花费了[574]毫秒。
CustomFilter init
- 自定义的filter拦截了所有请求,任意访问一个请求,控制台打印如下,说明filter执行了拦截,并放行
http://localhost:8081/get_cookie_test
CustomFilter doFilter
null
JSESSIONID
47797EAAB1641E2992D93DD3E33C5B21
过滤器配置类,可以通过这个获取过滤器基本信息
package jakarta.servlet;
import java.util.Enumeration;
public interface FilterConfig {
String getFilterName();
ServletContext getServletContext();
String getInitParameter(String var1);
Enumeration<String> getInitParameterNames();
}
- dispatcherTypes参数: 指定Filter对那种dispatcher模式进⾏过滤,不符合的则不进⾏过滤
REQUEST:默认值,浏览器直接请求的资源会被过滤器拦截
FORWARD:转发访问资源会被过滤器拦截
INCLUDE:包含访问资源
ERROR:错误跳转资源
ASYNC:异步访问资源
# 编写CustomFilterTest:设置filter名称,要拦截的url,初始化配置,要拦截的类型
# DispatcherType.FORWARD表示转发的时候被拦截
@WebFilter(filterName = "filterTest",urlPatterns = {"/*"},initParams = {
@WebInitParam(name = "encoding",value = "UTF-8"),
@WebInitParam(name = "loginPage",value = "/login.jsp"),
},dispatcherTypes = {DispatcherType.FORWARD})
# 编写如下,可在filter的重写的方法中使用默认的属性
private FilterConfig filterConfig;
private String encoding;
private String loginPage;
# 发送一个默认的请求http://localhost:8081/get_cookie_test,控制台打印如下,说明没有进入filter,
null
JSESSIONID
B7AAFF00C73C44DE9ECD1F5FB53681C5
# 发送一个转发的请求http://localhost:8081/forward,控制台打印如下,说明转发类型的请求被拦截了
DispatchServlet doGet
CustomFilter doFilter
filter进行登录拦截
@WebFilter(filterName = "loginFilter",urlPatterns = {"/user/*","/order/*"},initParams = {
@WebInitParam(name = "encoding",value = "UTF-8"),
@WebInitParam(name = "loginPage",value = "/login.jsp"),
})
public class LoginFilter implements Filter {
private FilterConfig filterConfig;
private String encoding;
private String loginPage;
/**
* filter 初始化
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CustomFilter init ");
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
this.loginPage = filterConfig.getInitParameter("loginPage");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("CustomFilter doFilter ");
request.setCharacterEncoding(encoding);
response.setCharacterEncoding(encoding);
response.setContentType("text/html;charset=utf-8");
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
HttpServletResponse httpServletResponse = (HttpServletResponse)response;
// 获取session里的用户信息
if(httpServletRequest.getSession().getAttribute("loginUser") !=null){
// 放行
chain.doFilter(request,response);
}else {
httpServletRequest.setAttribute("msg","非法访问,请登录");
httpServletRequest.getRequestDispatcher(loginPage).forward(httpServletRequest,httpServletResponse);
}
}
/**
* filter销毁
*/
@Override
public void destroy() {
System.out.println("CustomFilter destroy ");
}
}
- 测试,访问登录页面
- 输入正确的用户名和密码,跳转到user.jsp,控制台打印如下,说明先请求先进入filter初始化 -> loginServlet -> filter过滤器的doFilter()方法
loginServlet doPost
CustomFilter doFilter
- 退出登录或未登录状态下直接访问user.jsp,访问失败
http://localhost:8081/user/user.jsp