过滤器(Filter)和监听器(Listener)

1 Filter

1.1 介绍

Filter(过滤器)是Java Web应用中的一种组件,它用于在HTTP请求和HTTP响应之间执行某些操作,如修改请求或响应、过滤请求参数、验证用户身份、记录日志等。Filter通常用于处理与请求和响应相关的通用功能,可以在多个Servlet之间共享。

Filter具有以下主要功能和特点:

  1. 拦截请求和响应:Filter可以拦截所有进入Web应用程序的HTTP请求以及所有从Web应用程序发送出去的HTTP响应。

  2. 可链式调用:在一个Web应用程序中可以定义多个Filter,它们按照指定的顺序依次执行。这样可以构建一个Filter链,每个Filter可以处理不同的任务。

  3. 生命周期:Filter具有生命周期,包括初始化(init)、执行(doFilter)和销毁(destroy)三个阶段。

  4. 配置:Filter可以通过配置文件或注解进行配置,以确定哪些URL或资源应该被过滤。

  5. 处理请求和响应:Filter可以访问HTTP请求的信息,包括请求头、参数和请求体,并且可以修改它们。同样,它可以访问HTTP响应的信息,包括响应头和响应体,并且可以修改它们。

  6. 异常处理:Filter可以捕获异常,并根据需要进行处理,例如记录错误日志或向用户返回适当的错误页面。

1.2 FilterChain 过滤器链

在这里插入图片描述
Filter1

public class Filter1 implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("filter1 初始化方法");
	}
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,ServletException {
		System.out.println("filter1 前置 过滤方法 ");
		filterChain.doFilter(servletRequest, servletResponse);
		System.out.println("filter1 后置 过滤方法 ");
	}
	@Override
	public void destroy() {
		System.out.println("filter1 销毁方法");
	}
}

Filter2

public class Filter2 implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("filter2 初始化方法");
	}
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,ServletException {
		System.out.println("filter2 前置 过滤方法 ");
		filterChain.doFilter(servletRequest, servletResponse);
		System.out.println("filter2 后置 过滤方法 ");
	}
	@Override
	public void destroy() {
		System.out.println("filter1 销毁方法");
	}
}

web.xml配置

<filter>
	<filter-name>filter1</filter-name>
	<filter-class>com.lxs.demo.filter.Filter1</filter-class>
</filter>
<filter-mapping>
	<filter-name>filter1</filter-name>
	<url-pattern>/</url-pattern>
</filter-mapping>
<filter>
	<filter-name>filter2</filter-name>
	<filter-class>com.lxs.demo.filter.Filter2</filter-class>
</filter>
<filter-mapping>
	<filter-name>filter2</filter-name>
	<url-pattern>/</url-pattern>
</filter-mapping>

1.3 Filter 登录校验

1.3.1 准备工作

  • 要求:目标下的所有资源(html 页面、 jpg 图片、 jsp 文件、 等等) 都必须是用户登录之后才允许访问。

  • 原理:用户登录之后都会把用户登录的信息保存到 Session 域中。 所以要检查用户是否登录, 可以判断 Session 中否包含有用户登录的信息即可。

  • 原理图:
    在这里插入图片描述

1.3.2 过滤器配置

	<filter>
        <filter-name>authFilter</filter-name>
        <filter-class>com.kdx.demo.filter.AuthFilter</filter-class>
        <init-param>
            <param-name>passUrl</param-name>
            <param-value>/filter-demo/login.jsp;/filter-demo/login;/filter-demo/css;/filter-demo/img</param-value>
        </init-param>
    </filter>

1.3.3 AuthFilter

public class AuthFilter implements Filter {
    String pathUrl[];

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化");
        //读取web.xml配置
        pathUrl = filterConfig.getInitParameter("passUrl").split(";");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        HttpSession session = request.getSession();
        Object loginUser = session.getAttribute("loginUser");

        String path = request.getRequestURI();
        for (int i = 0; i < pathUrl.length; i++){
            if(path.startsWith(pathUrl[i])){
                filterChain.doFilter(request,response);
                return;
            }
        }

        if(loginUser == null){
            session.setAttribute("loginError","请登录后再访问!");
            response.sendRedirect("/filter-demo/login.jsp");
        }else {
            filterChain.doFilter(request,response);
        }
    }

    @Override
    public void destroy() {
        System.out.println("销毁");
    }
}

1.3.4 login.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
</head>
<script src="js/jquery-1.12.4.js"></script>
<link rel="stylesheet" href="css/main.css">
<body>
    <h4 id="h4">login.jsp <br>${loginError}</h4>
    <form action="/filter-demo/login" method="post">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit">
    </form>
    
    <img src="img/man04.jpg">
    <script>
        $(function(){
            console.log($("#h4").html());
        })
    </script>
</body>
</html>

1.3.5 LoginServlet

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        HttpSession session = request.getSession();

        if("kong".equals(username) && "123456".equals(password)){
            session.setAttribute("loginUser","kong");
            response.sendRedirect("/filter-demo/index.jsp");
        }else {
            request.setAttribute("loginError", "登录失败,请重新登录");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }
    }
}

1.4 Filter 的生命周期

Filter 的生命周期包含几个方法:与servlet大体相同

  1. 构造器方法

  2. init 初始化方法 :第 1, 2 步, 在 web 工程启动的时候执行(Filter 已经创建)

  3. doFilter 过滤方法,每次拦截到请求, 就会执行

  4. destroy 销毁, 停止 web 工程的时候, 就会执行(停止 web 工程, 也会销毁 Filter 过滤器)

1.5 FilterConfig 类

  • FilterConfig 类是 Filter的配置文件类。Tomcat 创建 Filter 时,也会同时创建 FilterConfig 类,该类包含 Filter 配置文件的信息。

  • FilterConfig 类的作用:获取 filter 过滤器的配置内容

    • 获取 Filter 的名称 filter-name 的内容

    • 获取在 Filter 中配置的 init-param 初始化参数

    • 获取 ServletContext 对象

  • 使用方法与servlet相同

Filter 过滤器它只关心请求的地址是否匹配, 不关心请求的资源是否存在

1.6 HttpServletRequestWrapper

HttpServletRequestWrapper 是 Java Servlet API 中的一个类,它是 HttpServletRequest 接口的包装器实现。它允许你在不改变原始请求对象的情况下修改或扩展请求对象的功能。

HttpServletRequestWrapper 是一个抽象类,通常需要自定义一个继承自它的类,并覆盖需要修改或扩展的方法。这个包装器类在很多情况下非常有用,例如:

  1. 修改请求参数: 你可以在包装器中覆盖 getParametergetParameterMap 方法,以修改请求参数的值或添加额外的参数。

  2. 修改请求头: 你可以覆盖 getHeadergetHeaderNames 方法来修改请求头的值或添加新的请求头。

  3. 修改请求方法: 你可以覆盖 getMethod 方法来改变请求的 HTTP 方法。

  4. 验证请求内容: 你可以在包装器中检查请求的内容,例如验证上传文件的大小或类型。

过滤敏感词案例:

public class Filter2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter2 初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //敏感词过滤
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        CustomHttpServletRequestWrapper requestWrapper = new CustomHttpServletRequestWrapper(request);

        System.out.println("Filter2 前置方法");
        filterChain.doFilter(requestWrapper,servletResponse);
        System.out.println("Filter2 后置方法");
    }

    @Override
    public void destroy() {
        System.out.println("Filter2 销毁");
    }

    class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {

        public CustomHttpServletRequestWrapper(HttpServletRequest request) {
            super(request);
        }

        @Override
        public String getParameter(String name) {
            String value = super.getParameter(name);
            // 对获取到的参数进行处理或修改
            if (name.equals("key")) {
                if ("李佳琦".equals(value)) {
                    return "XXX(和谐)";
                }
            }
            return value;
        }
    }
}

2 Listener

在JavaWeb应用程序中,Listener(监听器)是一种特殊的组件,它可以监听并响应Web应用程序中的事件。通过使用监听器,你可以捕获各种事件,例如HTTP请求、会话创建和销毁、属性变化等,从而执行一些自定义的逻辑。

在JavaWeb中,常见的主要的监听器有以下几种:

  1. ServletContextListener:用于监听Web应用程序的启动和关闭事件,可以在应用程序启动时进行初始化工作,或者在应用程序关闭时进行清理工作。

  2. HttpSessionListener:用于监听会话的创建和销毁事件,可以用来统计在线用户数量等。

  3. ServletRequestListener:用于监听HTTP请求的创建和销毁事件,可以用来记录请求日志、统计访问量等。

这些监听器接口都定义了一些回调方法,当相应的事件发生时,容器会自动调用这些方法,可以在这些方法中编写自己的业务逻辑。

分类:
在这里插入图片描述

以下是一个简单的示例,演示了如何创建一个ServletContextListener,以在Web应用程序启动时初始化一些资源:

public class MyServletContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        // 在应用程序启动时执行初始化逻辑
        ServletContext servletContext = servletContextEvent.getServletContext();
        // 执行一些初始化操作
        String appName = servletContext.getInitParameter("appName");
        System.out.println("Web应用程序 " + appName + " 启动了!");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        // 在应用程序关闭时执行清理逻辑
        ServletContext servletContext = servletContextEvent.getServletContext();
        // 执行一些清理操作
        System.out.println("Web应用程序关闭了!");
    }
}

要使用监听器,需要在web.xml文件中进行配置:

<listener>
    <listener-class>com.example.MyServletContextListener</listener-class>
</listener>

这个示例展示了如何创建一个ServletContextListener来监听Web应用程序的启动和关闭事件。当Web应用程序启动时,contextInitialized 方法会被调用,可以在其中执行初始化逻辑。当Web应用程序关闭时,contextDestroyed 方法会被调用,可以在其中执行清理逻辑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值