赞
踩
目录
在 Tomcat 中,Filter 是一种用于拦截请求和过滤响应的组件,可以在请求到达 Servlet 之前或响应离开 Servlet 之后对其进行处理。
Filter 的主要应用场景包括:
Filter 的生命周期由 Tomcat 容器管理,包含以下几个方法:
Filter 接口
- public interface Filter {
- // 容器创建的时候调用, 即启动 Tomcat 的时候调用
- public void init(FilterConfig filterConfig) throws ServletException;
- // 由 FilterChain 调用, 并且传入 FilterChain 本身, 最后回调 FilterChain 的 doFilter() 方法
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException;
- // 容器销毁的时候调用, 即关闭 Tomcat 的时候调用
- public void destroy();
- }
FilterChain 接口
- public interface FilterChain {
- // 由 Filter.doFilter() 中的 chain.doFilter 调用
- public void doFilter(ServletRequest request, ServletResponse response)
- throws IOException, ServletException;
- }
当 Tomcat 接收到 URL 请求时,它会根据在 web.xml 文件中配置的过滤器和映射路径来创建 FilterChain。如果某个请求匹配了一些过滤器的映射路径,那么这些过滤器将被添加到 FilterChain。创建了 FilterChain 之后,就开始执行 doFilter,进行请求的链式处理。
过滤器执行顺序:
如图是 Filter 拦截过程示意图。所有 Filter 和 Web 资源都默认执行在同一个线程中(因为Filter 和 Web 资源通常是在 HttpServlet 容器中运行的,而 HttpServlet 容器是基于单线程模型的)。对于 FilterChain 中的 Filter,它们都使用同一 Request 对象。
以下是 Filter 拦截过程的一般步骤:
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- // 1、获取 Filter 的名称 filter-name 的内容
- System.out.println("filter-name 的值是:" + filterConfig.getFilterName());
- // 2、获取在 web.xml 中配置的 init-param 初始化参数
- System.out.println("初始化参数 username 的值是:" + filterConfig.getInitParameter("username"));
- System.out.println("初始化参数 url 的值是:" + filterConfig.getInitParameter("url"));
- // 3、获取 ServletContext 对象
- System.out.println(filterConfig.getServletContext());
- }
工程目录
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_4_0.xsd"
- version="4.0">
-
- <!-- <display-name> 元素常用于配置 servlet、过滤器或其他 Web 组件的显示名称。
- 这个显示名称主要用于在管理界面或日志中标识该组件,以方便识别和管理。 -->
- <!-- 标识项目名 -->
- <display-name>ServletTest</display-name>
-
- <!-- 定义首页文件,也就是用户直接输入域名时跳转的页面(如http://localhost:8080/)-->
- <welcome-file-list>
- <welcome-file>login.jsp</welcome-file>
- </welcome-file-list>
-
-
- <!--filter 标签用于配置一个 Filter 过滤器-->
- <filter>
- <!--给 filter 起一个别名-->
- <filter-name>AdminFilter1</filter-name>
- <!--配置 filter 的全类名-->
- <filter-class>com.test.AdminFilter1</filter-class>
- <!-- 设置 Servlet 初始化参数
- 可以通过 FilterConfig.getInitParamenter(String name) 方法访问初始化参数 -->
- <init-param>
- <param-name>username</param-name>
- <param-value>root</param-value>
- </init-param>
- <init-param>
- <param-name>url</param-name>
- <param-value>jdbc:mysql://localhost3306/test</param-value>
- </init-param>
- </filter>
- <!-- 设置 filter 映射 -->
- <filter-mapping>
- <!-- 和 filter 标签中的 filter-name 对应 -->
- <filter-name>AdminFilter1</filter-name>
- <!-- 设置匹配的路径,这里设置为 /img/* 表示访问 img 目录下的图片都会调用该 filter(AdminFilter) -->
- <url-pattern>/img/*</url-pattern>
- </filter-mapping>
- <filter>
- <filter-name>AdminFilter2</filter-name>
- <filter-class>com.test.AdminFilter2</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>AdminFilter2</filter-name>
- <url-pattern>/img/*</url-pattern>
- </filter-mapping>
- </web-app>
login.jsp
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>登录</title>
- </head>
- <body>
- <form action="http://localhost:8080/servlettest/loginServlet" method="get">
- 用户名: <input type="text" name="username"/> <br>
- 密 码: <input type="password" name="password"/> <br>
- <input type="submit" />
- </form>
- </body>
- </html>
LoginServlet 类
- package com.test;
-
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- @WebServlet("/loginServlet")
- public class LoginServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
- IOException {
- resp.setContentType("text/html; charset=UTF-8");
- String username = req.getParameter("username");
- String password = req.getParameter("password");
- if ("root".equals(username) && "123456".equals(password)) {
- System.out.println("设置 Seesion: {user : " + username + " }");
- req.getSession().setAttribute("user",username);
- System.out.println("登录成功!");
- resp.getWriter().write("登录 成功!!!");
- } else {
- System.out.println("登录失败!");
- req.getRequestDispatcher("/login.jsp").forward(req,resp);
- }
- }
- }
AdminFilter1 类
- package com.test;
-
- import javax.servlet.*;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpSession;
- import java.io.IOException;
-
- public class AdminFilter1 implements Filter {
-
- // doFilter 方法,专门用于拦截请求。可以做权限检查
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain
- filterChain) throws IOException, ServletException {
- System.out.println("过滤器 AdminFilter1");
- HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
- HttpSession session = httpServletRequest.getSession();
- Object user = session.getAttribute("user");
- // System.out.println("登录用户: " + user);
- // 如果等于 null,说明还没有登录
- if (user == null) {
- System.out.println("未登录,跳转到登录页面");
- servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
- return;
- } else {
- // 让程序继续往下访问用户的目标资源
- System.out.println("AdminFilter1 调用 doFilter 方法");
- filterChain.doFilter(servletRequest,servletResponse);
- System.out.println("AdminFilter1 结束了 doFilter 方法的调用");
- }
- }
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- // 1、获取 Filter 的名称 filter-name 的内容
- System.out.println("filter-name 的值是:" + filterConfig.getFilterName());
- // 2、获取在 web.xml 中配置的 init-param 初始化参数
- System.out.println("初始化参数 username 的值是:" + filterConfig.getInitParameter("username"));
- System.out.println("初始化参数 url 的值是:" + filterConfig.getInitParameter("url"));
- // 3、获取 ServletContext 对象
- System.out.println(filterConfig.getServletContext());
- }
- }
AdminFilter2 类
- package com.test;
-
- import javax.servlet.*;
- import java.io.IOException;
-
- public class AdminFilter2 implements Filter {
-
- // doFilter 方法,专门用于拦截请求。可以做权限检查
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain
- filterChain) throws IOException, ServletException {
- System.out.println("过滤器 AdminFilter2");
- System.out.println("AdminFilter2 调用 doFilter 方法");
- filterChain.doFilter(servletRequest,servletResponse);
- System.out.println("AdminFilter2 结束了 doFilter 方法的调用");
- }
- }
运行演示图
运行流程:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。