基本概念
- Filter 过滤器它是 JavaEE 的规范,也就是接口
- Filter 过滤器它的作用是:拦截请求,过滤响应
- 拦截请求常见的应用场景有: 1、权限检查 2、日记操作 3、事务管理 等等
应用
- 有一个 admin 目录。这个 admin 目录下的所有资源(html 页面、jpg 图片、jsp 文件、等等)都必须是用户登录之后才允许访问
- 过滤所有在
admin
文件夹内的文件public class AdminFilter 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 httpServletRequest = (HttpServletRequest) request; HttpSession session = httpServletRequest.getSession(); // 判断是否有已经登录的记录 Object user = session.getAttribute("user"); if (user == null) { request.getRequestDispatcher("/login.jsp").forward(request, response); return; } chain.doFilter(request, response); } }
<filter> <filter-name>AdminFilter</filter-name> <filter-class>com.du.javaweb.filter.AdminFilter</filter-class> </filter> <filter-mapping> <filter-name>AdminFilter</filter-name> <url-pattern>/admin/*</url-pattern> </filter-mapping>
admin
文件夹内的文件<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>管理员界面</title> </head> <body> 这是管理员界面 </body> </html>
- 登录界面及
Servlet
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登录界面</title> <base href="http://localhost:8080/filter/"> </head> <body> <form action="LoginServlet" method="post"> <label for="name"> 登录名 </label><input type="text" name="name" id="name"><br/> <label for="password"> 密码 </label><input type="password" name="password" id="password"><br/> <input type="submit" value="登录"> </form> </body> </html>
@WebServlet(name = "LoginServlet", value = "/LoginServlet") public class LoginServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=UTF-8"); String name = request.getParameter("name"); String password = request.getParameter("password"); if ("jack".equals(name) && "123".equals(password)) { response.getWriter().write("登录成功"); request.getSession().setAttribute("user", true); // 在session中保存登录成功记录,只要是非空就好 return; } RequestDispatcher dispatcher = request.getRequestDispatcher("/login.jsp"); dispatcher.forward(request, response); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } }
Filter 的生命周期
- Filter 的生命周期包含几个方法
- 构造器方法
- init 初始化方法。
- doFilter 过滤方法 第 3 步,每次拦截到请求,就会执行
- destroy 销毁 第 4 步,停止 web 工程的时候,就会执行(停止 web 工程,也会销毁 Filter 过滤器)
第 1、2 步,在 web 工程启动的时候执行(Filter 已经创建)
FilterConfig 类
FilterConfig
类,它是 Filter 过滤器的配置文件类。- Tomcat 每次创建
Filter
的时候,也会同时创建一个FilterConfig
类,这里包含了Filter
配置文件的配置信息public void init(FilterConfig config) throws ServletException { System.out.println("这是AdminFilter的init()方法"); // 获取过滤器的名字 String filterName = config.getFilterName(); System.out.println(filterName); // 获取servletContext对象 ServletContext servletContext = config.getServletContext(); System.out.println(servletContext); System.out.println(servletContext.getInitParameter("context_param")); // 获取初始化参数的值 String param = config.getInitParameter("param"); System.out.println(param); // 获取所有初始化参数的名字 Enumeration<String> initParameterNames = config.getInitParameterNames(); while (initParameterNames.hasMoreElements()) { System.out.println(initParameterNames.nextElement()); } }
<filter> <filter-name>AdminFilter</filter-name> <filter-class>com.du.javaweb.filter.AdminFilter</filter-class> <init-param> <param-name>param</param-name> <param-value>value</param-value> </init-param> </filter> <filter-mapping> <filter-name>AdminFilter</filter-name> <url-pattern>/admin/*</url-pattern> </filter-mapping>
FilterChain 过滤器链
@WebFilter(filterName = "Filter1", urlPatterns = "/index.jsp")
public class Filter1 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 {
System.out.println("Filter1 开始");
chain.doFilter(request, response);
System.out.println("Filter1 结束");
}
}
@WebFilter(filterName = "Filter2", urlPatterns = "/index.jsp")
public class Filter2 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 {
System.out.println("Filter2 开始");
chain.doFilter(request, response);
System.out.println("Filter2 结束");
}
}
- 就像一个栈一样,输出顺序是。两个
Filter
的先后顺序主要看在xml的声明顺序。(这个例子用注解声明,那就不知道怎么确定了。可能是ASCII码吧)Filter1 开始 Filter2 开始 Filter2 结束 Filter1 结束
Filter 的拦截路径
- 精确匹配
以上配置的路径,表示请求地址必须为:<url-pattern>/target.jsp</url-pattern>
http://ip:port/工程路径/target.jsp
- 目录匹配
以上配置的路径,表示请求地址必须为:<url-pattern>/admin/*</url-pattern>
http://ip:port/工程路径/admin/*
- 后缀名匹配
以上配置的路径,表示请求地址必须以.html 结尾才会拦截到<url-pattern>*.html</url-pattern>
- Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在!!!所以,就算请求的网页不存在,只要URL在过滤器的“管辖范围”,就会对它进行管制。