一、web.xml配置:
Filter配置:
<filter>
<filter-name>demo1</filter-name>
<filter-class>cn.leader.web.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
<filter-name>demo1</filter-name>
<!-- url-pattern - 拦截路径-->
<url-pattern>/*</url-pattern>
<!-- Filter默认设置拦截方法-->
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
二、过滤器执行流程&生命周期
过滤器执行流程:
1 - 服务器被请求自动创建init方法
2 - 执行doFilter方法放行上方代码块 -> 过滤器放行 -> 执行放行下面的代码块
3 - 随着服务器正常关闭,destroy方法会释放资源,结束方法
public void init(FilterConfig config) throws ServletException {
System.out.println("init =========================");
}
public void destroy() {
System.out.println("destroy ======================");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("拦截Demo2 执行了----------------");
//放行
chain.doFilter(request, response);
System.out.println("拦截Demo2 回来了----------------");
}
过滤器生命周期:
1、init随着服务器被请求产生,仅执行一次,用于加载资源
2、doFilter方法,每访问一次资源文件便执行一次
3、destroy会在服务器正常关闭时执行一次,用于释放资源
三、过滤器拦截路径配置
@WebFilter("/*")
@WebFilter("*.jsp")
@WebFilter("/admin/*")
@WebFilter("/index.jsp")
四、Filter过滤器拦截方式设置:
浏览器只有直接请求index.jsp资源时(request)会执行:
@WebFilter(value="/index.jsp",dispatcherTypes=DispatcherType.REQUEST)
浏览器只有通过转发方式请求index.jsp资源时(forward)会执行:
@WebFilter(value="/index.jsp",dispatcherTypes=DispatcherType.FORWARD)
浏览器多种方式访问index.jsp资源时都会执行:
@WebFilter(value="/index.jsp",dispatcherTypes{DispatcherType.FORWARD},DispatcherType.REQUEST)
五、过滤器链 - 配置多个过滤器
执行顺序:有两个过滤器的情况下(过滤器一 和 过滤器二)
过滤器一执行 -> 过滤器二执行 -> 资源执行 -> 过滤器二执行 -> 过滤器一执行
注解的方式中:执行顺序按字典顺序(A - Z , 0 - 9)
xml的方式中:按定义先后顺序执行(filter-mapping)
六、过滤器使用案例
案例一:登录验证
需求:如果没有登录则不能访问index.jsp页面,需要登录(login.jsp)后(放行)再进行页面访问
分析:在浏览器访问资源中设过滤器(LoginFilter)
1、判断请求是否为登录相关资源 - 如login.jsp、验证码显示、相关js、css样式。如果是,直接放行,后再进行是否登录判断。
2、判断当前用户是否登录(session中是否有user对象),如果有 -> 登录成功;如果没有 -> 登录失败 -> 跳转到登录页面
package cn.leader.web.filter; /**
* Created by 加班狂人 on 2022/7/14 16:31
*/
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter("/*")
public class LoginFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//类型强制转换 接口不提供具体方法
HttpServletRequest req = (HttpServletRequest)request;
//获取资源请求路径
String uri = req.getRequestURI();
//System.out.println(uri);
//判断资源请求路径中是否包含登录相关用户资源
if (uri.contains("/managerLogin.jsp") || uri.contains("/loginServlet") || uri.contains("/css/") || uri.contains("/js/") || uri.contains("/fonts") || uri.contains("/verifyCodeImg")){
//包含说明用户要访问登录页面 直接放行
chain.doFilter(request,response);
}else {
//不包含则判断是否登录
//从session中获取user
Object user = req.getSession().getAttribute("lUser");
if (user != null){
//不等于空则放行
chain.doFilter(request, response);
}else {
//等于空代表没有user对象 没有登录 跳转登陆页面
req.setAttribute("login_msg","宁尚未登录,请先登录");
req.getRequestDispatcher("/managerLogin.jsp").forward(req,response);
}
}
}
}
注意变量名是否与servlet中一致,否则会出现登录不上的问题