Filter过滤器(重点)

基本概念

  • Filter本意为”过滤“的含义,是JavaWeb的三大组件之一,三大组件为:Servlet、Filter、Listener。
  • 过滤器是向 Web 应用程序的请求和响应处理添加功能的 Web 服务组件。
  • 过滤器相当于浏览器与Web资源之间的一道过滤网,在访问资源之前通过一系列的过滤器对请求进行修改、判断以及拦截等,也可以对响应进行修改、判断以及拦截等。

    工作方式

    第五章 Filter Listener核心技术 - 图1

    使用方式

  • 自定义类实现Filter接口并重写doFilter方法。

    1. public class LoginFilter implements Filter {
    2. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,ServletException {
    3. //TODO 处理逻辑,必须调用下面的方法
    4. chain.doFilter(request,response);
    5. }
    6. }

    在web.xml文件中配置过滤器。 ```javascript

    LoginFilter com.lagou.LoginFilter

LoginFilter /*

  1. LoginServlet.java
  2. ```javascript
  3. package com.lagou.demo01;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.annotation.WebServlet;
  6. import javax.servlet.http.HttpServlet;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import java.io.IOException;
  10. @WebServlet(name = "LoginServlet",urlPatterns = "/login")
  11. public class LoginServlet extends HttpServlet {
  12. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  13. // 1.接收前端页面输入的用户名和密码信息并打印
  14. String userName = request.getParameter("userName");
  15. System.out.println("接收到的用户名为:" + userName);
  16. String password = request.getParameter("password");
  17. System.out.println("接收到的密码为:" + password);
  18. // 2.使用固定的用户名和密码信息来进行登录的校验
  19. if ("admin".equalsIgnoreCase(userName)&&"123456".equalsIgnoreCase(password)){
  20. System.out.println("登录成功,欢迎使用!");
  21. // 存储用户信息
  22. request.getSession().setAttribute("userName",userName);
  23. // 重定向 跳转
  24. response.sendRedirect("main.jsp");
  25. }else {
  26. System.out.println("用户名或密码错误,请重新输入!");
  27. //登录失败,转发
  28. request.getRequestDispatcher("login.jsp").forward(request,response);
  29. }
  30. }
  31. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  32. this.doPost(request, response);
  33. }
  34. }

LoginFilter.java

  1. package com.lagou.demo01;
  2. import javax.servlet.*;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpSession;
  5. import java.io.IOException;
  6. public class LoginFilter implements Filter {
  7. @Override
  8. public void init(FilterConfig filterConfig) throws ServletException {
  9. }
  10. @Override
  11. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  12. // 1.实现对用户访问主页面的过滤操作,也就是只有用户登录后才能访问主页面,否则一律拦截
  13. // 判断session中是否已有用户名信息,若没有则进行拦拦截,否则放行
  14. HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
  15. HttpSession session = httpServletRequest.getSession();
  16. Object userName = session.getAttribute("userName");
  17. // 获取Servlet的请求路径
  18. String servletPath = httpServletRequest.getServletPath();
  19. // 若没有登录,则回到登录页面
  20. if (null == userName && !servletPath.contains("login")){
  21. servletRequest.getRequestDispatcher("login.jsp").forward(servletRequest,servletResponse);
  22. }else {
  23. // 若已经登录,则放行
  24. filterChain.doFilter(servletRequest,servletResponse);
  25. }
  26. }
  27. @Override
  28. public void destroy() {
  29. }
  30. }

login.jsp main.jsp web.xml
image.png
image.png

Filter接口

基本概念

  • javax.servlet.Filter接口主要用于描述过滤器对象,可以对资源的请求和资源的响应操作进行筛选操作。

    常用的方法

    | 方法声明 | 功能介绍 | | —- | —- | | void init(FilterConfig filterConfig) | 实现过滤器的初始化操作 | | void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | 执行过滤操作的功能 | | void destroy() | 实现过滤器的销毁操作 |

FilterConfig接口

基本概念

javax.servlet.FilterConfig接口主要用于描述过滤器的配置信息。

常用方法

方法声明 功能介绍
String getFilterName() 获取过滤器的名字
String getInitParameter(String name) 获取指定的初始化参数信息
Enumeration getInitParameterNames() 获取所有的初始化操作名称
ServletContext getServletContext() 获取ServletContext对象

LifeFilter.java

  1. package com.lagou.demo02;
  2. import javax.servlet.*;
  3. import java.io.IOException;
  4. import java.util.Enumeration;
  5. public class LifeFilter implements Filter {
  6. @Override
  7. public void init(FilterConfig filterConfig) throws ServletException {
  8. System.out.println("初始化操作正在火热进行中...");
  9. System.out.println("获取到的过滤器名称为:" + filterConfig.getFilterName());
  10. String userName = filterConfig.getInitParameter("userName");
  11. System.out.println("获取到指定初始化参数的数值为:" + userName); // admin
  12. Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
  13. while (initParameterNames.hasMoreElements()){
  14. // userName password
  15. System.out.println("获取到的初始化参数名为:" + initParameterNames.nextElement());
  16. }
  17. ServletContext servletContext = filterConfig.getServletContext();
  18. System.out.println("获取到的上下文对象是:" + servletContext);
  19. }
  20. @Override
  21. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  22. System.out.println("阻拦一切不合理的访问哦!");
  23. filterChain.doFilter(servletRequest,servletResponse);
  24. }
  25. @Override
  26. public void destroy() {
  27. System.out.println("销毁操作执行完毕了!");
  28. }
  29. }

web.xml
image.png

多个过滤器的使用

  • 如果有多个过滤器都满足过滤的条件,则容器依据映射的先后顺序来调用各个过滤器。

第五章 Filter Listener核心技术 - 图5

过滤器优点

  • 实现代码的“可插拔性”,即增加或减少某个功能模块,不会影响程序的正常执行。
  • 可以将多个相同处理逻辑的模块集中写在过滤器里面,可实现重复利用、也方便代码的维护。

image.png

Listener监听器(重点)

基本概念

  • Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理。

    容器产生的事件分类如下:
    生命周期相关的事件。
    属性状态相关的事件。
    存值状态相关的事件。

  • 底层原理是采用接口回调的方式实现。

    基本分类

    | 监听器类型 | 功能介绍 | | —- | —- | | javax.servlet.ServletRequestListener | 监听request作用域的创建和销毁 | | javax.servlet.ServletRequestAttributeListener | 监听request作用域的属性状态变化 | | javax.servlet.http.HttpSessionListener | 监听session作用域的创建和销毁 | | javax.servlet.http.HttpSessionAttributeListener | 监听session作用域的属性状态变化 | | javax.servlet.ServletContextListener | 监听application作用域的创建和销毁 | | javax.servlet.ServletContextAttributeListener | 监听application作用域的属性状态变化 | | javax.servlet.http.HttpSessionBindingListener | 监听对象与session的绑定和解除 | | javax.servlet.http.HttpSessionActivationListener | 监听session数值的钝化和活化 |

监听器详解

ServletRequestListener监听器

  • 在ServletRequest创建和关闭时都会通知ServletRequestListener监听器。
  • 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void requestInitialized(ServletRequestEvent sre) | 实现ServletRequest对象的初始化 | | void requestDestroyed(ServletRequestEvent sre) | 实现ServletRequest对象的销毁 |

image.png

ServletRequestAttributeListener监听器

  • 向ServletRequest添加、删除或者替换一个属性的时候,将会通知ServletRequestAttributeListener监听器。
  • 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void attributeAdded(ServletRequestAttributeEvent srae) | 增加属性时触发 | | void attributeReplaced(ServletRequestAttributeEvent srae) | 修改属性时触发 | | void attributeRemoved(ServletRequestAttributeEvent srae) | 删除属性时触发 |

image.png

HttpSessionListener监听器

  • 当一个HttpSession刚被创建或者失效(invalidate)的时候,将会通知HttpSessionListener监听器。
  • 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void sessionCreated(HttpSessionEvent se) | 当一个HttpSession对象被创建时会调用这个方法 | | void sessionDestroyed(HttpSessionEvent se) | 当一个HttpSession超时或者调用HttpSession的
    invalidate()方法让它销毁时,将会调用这个方法 |

image.png

HttpSessionAttributeListener监听器

  • HttpSession中添加、删除或者替换一个属性的时候,将会通知HttpSessionAttributeListener监听器。
  • 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void attributeAdded(HttpSessionBindingEvent se) | 当往会话中加入一个属性的时候会调用这个方法 | | void attributeRemoved(HttpSessionBindingEvent se) | 当从会话中删除一个属性的时候会调用这个方法 | | void attributeReplaced(HttpSessionBindingEvent se) | 当改变会话中的属性的时候会调用这个方法 |

image.png

ServletContextListener监听器

  • 在ServletContext创建和关闭时都会通知ServletContextListener监听器。
  • 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void contextInitialized(ServletContextEvent sce) | 当ServletContext创建的时候,将会调用这个方法 | | void contextDestroyed(ServletContextEvent sce) | 当ServletContext销毁的时候(例如关闭应用服务器或者重新加载应用),将会调用这个方法 |

image.png

ServletContextAttributeListener监听器

  • 向ServletContext添加、删除或者替换一个属性的时候,将会通知ServletContextAttributesListener监听器
  • 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void attributeAdded(ServletContextAttributeEvent scae) | 往ServletContext中加入一个属性的时候触发 | | void attributeRemoved(ServletContextAttributeEvent scae) | 从ServletContext中删除一个属性的时候触发 | | void attributeReplaced(ServletContextAttributeEvent scae) | 改变ServletContext中属性的时候触发 |

image.png

HttpSessionBindingListener监听器

  • HttpSession中绑定和解除绑定时,将会通知HttpSessionListener监听器。
  • 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void valueBound(HttpSessionBindingEvent event) | 有对象绑定时调用该方法 | | void valueUnbound(HttpSessionBindingEvent event) | 有对象解除绑定时调用该方法 |

image.png

HttpSessionActivationListener监听器

  • 当有session数值的钝化和活化操作时,将会通知HttpSessionActivationListener监听器。
  • 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void sessionWillPassivate(HttpSessionEvent se) | 有钝化操作时调用该方法 | | void sessionDidActivate(HttpSessionEvent se) | 有活化操作时调用该方法 |

image.png
活化操作需要进行如下配置

  • 配置context.xml文件的方式如下:
  1. <Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true">
  2. <!-- 配置文件存放的路径信息,可以自由指定 -->
  3. <Store className="org.apache.catalina.session.FileStore" directory="C:\session"/>
  4. </Manager>xml

实战案例

  • 自定义类实现监听器接口并重写相关的方法。

OnlineUser.java

  1. package com.lagou.demo04;
  2. import javax.servlet.ServletContext;
  3. import javax.servlet.ServletContextEvent;
  4. import javax.servlet.ServletContextListener;
  5. import javax.servlet.http.HttpSessionEvent;
  6. import javax.servlet.http.HttpSessionListener;
  7. public class OnlineUser implements HttpSessionListener, ServletContextListener {
  8. // 声明一个ServletContex类型的引用负责作为全局对象来记录当前在线用户的数量,通过属性记录
  9. private ServletContext servletContext = null;
  10. @Override
  11. public void contextInitialized(ServletContextEvent servletContextEvent) {
  12. servletContext = servletContextEvent.getServletContext();
  13. }
  14. @Override
  15. public void contextDestroyed(ServletContextEvent servletContextEvent) {
  16. servletContext = null;
  17. }
  18. @Override
  19. public void sessionCreated(HttpSessionEvent httpSessionEvent) {
  20. System.out.println("有新用户上线了...");
  21. Object count = servletContext.getAttribute("count");
  22. // 若当前用户为第一个用户,则将全局对象中的属性值设置为1即可
  23. if (null == count) {
  24. servletContext.setAttribute("count", 1);
  25. }
  26. // 若当前用户不是第一个用户,则将全局对象中原有的数据取出来加1后再设置进去
  27. else {
  28. Integer integer = (Integer)count;
  29. integer++;
  30. servletContext.setAttribute("count", integer);
  31. }
  32. System.out.println("当前在线用户数量为:" + servletContext.getAttribute("count"));
  33. }
  34. @Override
  35. public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
  36. System.out.println("有用户已下线...");
  37. }
  38. }

onlineUser.jsp

  1. <%--
  2. Created by IntelliJ IDEA.
  3. User: pingmao
  4. Date: 2021/5/8
  5. Time: 下午5:21
  6. To change this template use File | Settings | File Templates.
  7. --%>
  8. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  9. <html>
  10. <head>
  11. <title>实现当前在线的用户数量</title>
  12. </head>
  13. <body>
  14. <h1>当前在线用户人数为:${applicationScope.count}</h1>
  15. </body>
  16. </html>
  • 在web.xml中配置监听器


com.lagou.listener.OnlineUser

image.png