• 过滤器和监听器


    过滤器

    Filter译为过滤器。 由于 Servlet 规范是开放的,借助于公众与开源社区的力量, Servlet 规范越来越科学,功能也越来越强大。

    运行原理:

    当客户端向服务器端发送一个请求时,如果有对应的过滤器进行拦截,过滤器可以改变请求的内容、或者重新设置请求协议的相关信息等,然后再将请求发送给服务器端的Servlet进行处理。当Servlet对客户端做出响应时,过滤器同样可以进行拦截,将响应内容进行修改或者重新设置后,再响应给客户端浏览器。在上述过程中,客户端与服务器端并不需要知道过滤器的存在 在一个Web应用程序中,可以部署多个过滤器进行拦截,这些过滤器组成了一个过滤器链。过滤器链中的每个过滤器负责特定的操作和任务,客户端的请求在这些过滤器之间传递,直到服务器端的Servlet。具体执行流程如下:

    快速入门

    1.编写一个类实现Filter过滤接口

    2.重写接口中的方法

     

    1. package com.bhf.filter;
    2. import javax.servlet.*;
    3. import javax.servlet.annotation.WebFilter;
    4. import java.io.IOException;
    5. /**
    6. * 过滤器的生命周期
    7. * 创建对象 LoginFilter() 服务器启动时 调用一次
    8. * 初始化 init 对象创建完成后 调用一次
    9. * 执行过滤的方法 doFilter 一次请求执行一次
    10. * 销毁方法 destroy 服务器关闭时 被调用 调用一次
    11. */
    12. // "/*"表示拦截所有请求,进入doFilter,
    13. // 执行filterChain.doFilter(servletRequest,servletResponse);放行请求
    14. @WebFilter("/*")
    15. public class TestFilter implements Filter {
    16. @Override
    17. public void init(FilterConfig filterConfig) throws ServletException {
    18. }
    19. @Override
    20. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    21. //放行
    22. filterChain.doFilter(servletRequest,servletResponse);
    23. }
    24. @Override
    25. public void destroy() {
    26. }
    27. }

    应用的实例

    1.解决请求参数的乱码问题

    2.非法访问的拦截(当用户未登录时,拦截请求到登录页面)

    拦截所有资源: /*

    需要被放行的资源: 不需要登录即可访问的资源

    1、放行指定页面:不需要登录可以访问的页面(例如:登录页面、注册页面等)

    2、放行静态资源: (例如: css. js. image等资源)

    3、放行指定操作:不需要登录即可执行的操作(例如:登录操作、注册操作等)

    4、登录状态放行(如果存在指定session对象。则为登录状态)

    1. package com.bhf.filter;
    2. import com.bhf.pojo.User;
    3. import javax.servlet.*;
    4. import javax.servlet.annotation.WebFilter;
    5. import javax.servlet.http.HttpServletRequest;
    6. import javax.servlet.http.HttpServletResponse;
    7. import java.io.IOException;
    8. @WebFilter("/*")
    9. public class LoginFilter implements Filter {
    10. @Override
    11. public void init(FilterConfig filterConfig) throws ServletException {
    12. }
    13. @Override
    14. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    15. HttpServletRequest req = (HttpServletRequest) servletRequest;
    16. HttpServletResponse resp = (HttpServletResponse) servletResponse;
    17. //处理中文乱码
    18. req.setCharacterEncoding("utf-8");
    19. //放行特定页面
    20. String servletPath = req.getServletPath();
    21. System.out.println("servletPath"+servletPath);
    22. if("/login.jsp".equals(servletPath)||"/register.jsp".equals(servletPath)){
    23. filterChain.doFilter(req,resp);
    24. return;
    25. }
    26. //放行特定的请求 /user method=getCode
    27. String method = req.getParameter("method");
    28. if("getCode".equals(method)||"login".equals(method)||"register".equals(method)||"checkUserName".equals(method)){
    29. filterChain.doFilter(req,resp);
    30. return;
    31. }
    32. //放行特定静态资源 .css .js .img
    33. if(servletPath.startsWith("/static")) {
    34. filterChain.doFilter(req,resp);
    35. return;
    36. }
    37. //1.判断session中是否有user对象
    38. User user = (User) req.getSession().getAttribute("user");
    39. //2.判断user是否为null
    40. if(user==null){
    41. //没有登录跳转
    42. req.setAttribute("login_msg","您未登录");
    43. req.getRequestDispatcher("/login.jsp").forward(req,resp);
    44. }
    45. filterChain.doFilter(req,resp);
    46. }
    47. @Override
    48. public void destroy() {
    49. }
    50. }

    监听器

    web监听器由servlet规范提供的,它可以监听客户端的请求,服务端的操作,监听的对象包括:

    三个域对象(内置对象),分别对应aplication,session,request

     

    Web监听器概念 Servlet规范中定义的一种特殊类,用于监听ServletContext,HttpSession和ServletRequest等域对象的创建与销毁事件,用于监听域对象的属性发生增、删、改的事件,可以在事件发生前,发生后做一些必要的处理

    监听三个对象的创建和销毁

    1.application域对象的监听器

    1. package com.aiit.listener;
    2. import javax.servlet.ServletContextEvent;
    3. import javax.servlet.ServletContextListener;
    4. import javax.servlet.annotation.WebListener;
    5. /**
    6. * application域对象的监听器
    7. * 1.监听域对象的创建和销毁
    8. * ServletContextListener
    9. */
    10. @WebListener
    11. public class ApplicationListener implements ServletContextListener {
    12. // 一旦有application对象被创建 则该方法会被自动调用
    13. @Override
    14. public void contextInitialized(ServletContextEvent sce) {
    15. System.out.println("application对象被创建");
    16. }
    17. // 一旦有application对象被销毁 则该方法会被自动调用
    18. @Override
    19. public void contextDestroyed(ServletContextEvent sce) {
    20. System.out.println("application对象被销毁");
    21. }
    22. }

    2.session对象的监听器 

    1. package com.aiit.listener;
    2. import javax.servlet.annotation.WebListener;
    3. import javax.servlet.http.HttpSessionEvent;
    4. import javax.servlet.http.HttpSessionListener;
    5. /**
    6. * session对象的创建和销毁的监听
    7. *
    8. * session 对象 什么时候被创建
    9. * 浏览器向服服务器成功发送一次请求 则会话对象被创建 同一次会话只会创建一个会话对象 Cookie
    10. * session 对象 什么时候被销毁
    11. * 1. 手动销毁
    12. * 2. 默认销毁 浏览器在30分钟之内没有向服务器发送请求 则会话对象自动销毁
    13. */
    14. @WebListener
    15. public class SessionListener implements HttpSessionListener {
    16. //会话对象被创建
    17. @Override
    18. public void sessionCreated(HttpSessionEvent se) {
    19. System.out.println("sessionCreated");
    20. }
    21. //会话对象被销毁
    22. @Override
    23. public void sessionDestroyed(HttpSessionEvent se) {
    24. System.out.println("sessionDestroyed");
    25. }
    26. }

    3.request对象的监听器

    1. package com.aiit.listener;
    2. import javax.servlet.ServletRequestEvent;
    3. import javax.servlet.ServletRequestListener;
    4. import javax.servlet.annotation.WebListener;
    5. @WebListener
    6. public class RequestListener implements ServletRequestListener {
    7. //会话对象被创建
    8. @Override
    9. public void requestDestroyed(ServletRequestEvent sre) {
    10. System.out.println("requestDestroyed");
    11. }
    12. //会话对象被销毁
    13. @Override
    14. public void requestInitialized(ServletRequestEvent sre) {
    15. System.out.println("requestInitialized");
    16. }
    17. }

    监听三个对象中值的变化

    1.监听域对象中值的改变,实现ServletContextAttributeListener接口

    1. package com.aiit.listener;
    2. import javax.servlet.ServletContextAttributeEvent;
    3. import javax.servlet.ServletContextAttributeListener;
    4. import javax.servlet.annotation.WebListener;
    5. /**
    6. * application域对象的监听器
    7. *2.监听域对象中值的改变
    8. * ServletContextAttributeListener
    9. *
    10. */
    11. @WebListener
    12. public class ApplicationAttributeListener implements ServletContextAttributeListener {
    13. //application中有值被添加
    14. @Override
    15. public void attributeAdded(ServletContextAttributeEvent event) {
    16. String name = event.getName();
    17. System.out.println("name = " + name);
    18. Object value = event.getValue();
    19. System.out.println("value = " + value);
    20. System.out.println("application attributeAdded");
    21. }
    22. //application中有值被删除
    23. @Override
    24. public void attributeRemoved(ServletContextAttributeEvent event) {
    25. System.out.println("application attributeRemoved");
    26. }
    27. //application中有值被替换
    28. @Override
    29. public void attributeReplaced(ServletContextAttributeEvent event) {
    30. System.out.println("application attributeReplaced");
    31. }
    32. }

    2.监听域对象中值的改变,实现HttpSessionAttributeListener接口

    与1相同省略

    3.监听域对象中值的改变,实现ServletRequestAttributeListener接口

    与1相同省略

    使用监听器防止一个账号多段登录

    单点登录思路分析
    1.用户登录成功后会向session域中添加一个key --> user
    2.向session对象中添加值时会被HttpSessionAttributeListener attributeAdded 获取到
    3.判断改登录的用户是否已经登录过一次了 -->Map tom  session  ;jack session
    4.用户已经登录则根据用户名在map集合中取出对应的session并销毁 第一次登录的用户就会被剔除 再次请求后台接口是就会被拦截到登录页面
    5.将第二次登录的用户相关信息存入map集合 user session
    1. @WebListener
    2. public class LoginListener implements HttpSessionAttributeListener {
    3. private Map sessions = new HashMap();
    4. public void attributeReplaced(HttpSessionBindingEvent arg0) {
    5. }
    6. public void attributeAdded(HttpSessionBindingEvent event) {
    7. System.out.println("session值被添加");
    8. //获取添加session的名字
    9. String name = event.getName();
    10. System.out.println(name);
    11. if("username".equals(name)) {//该用户的session 已存在 在map中移出
    12. String username =(String)event.getValue();
    13. if(sessions.containsKey(username)) {
    14. HttpSession httpSession = sessions.get(username);
    15. //设置session失效
    16. httpSession.invalidate();
    17. System.out.println("session被移出");
    18. }
    19. //将刚生成的session放入 集合
    20. sessions.put(username, event.getSession());
    21. }
    22. }
    23. public void attributeRemoved(HttpSessionBindingEvent event) { }
    24. public void attributeReplaced(HttpSessionBindingEvent event) { }
    25. }

    Web监听器的常用用途

    • 统计在线人数

    • 系统启动时加载初始化信息

    实例1

    1. /**
    2. * 使用session监听器实现统计在线人数
    3. * @author USER
    4. * date 2021年7月13日
    5. * @version 1.0
    6. */
    7. @WebListener
    8. public class SessionListener implements HttpSessionListener {
    9. public void sessionCreated(HttpSessionEvent arg0) {
    10. System.out.println("session监听器初始化完毕");
    11. CountUtil.add();
    12. arg0.getSession().getServletContext().setAttribute("online", CountUtil.getCount());
    13. }
    14. public void sessionDestroyed(HttpSessionEvent arg0) {
    15. System.out.println("session监听器销毁完毕");
    16. CountUtil.sub();
    17. arg0.getSession().getServletContext().setAttribute("online", CountUtil.getCount());
    18. }
    19. }

    实例2

    1. /**
    2. * Application域生命周期的监听 设置全局的路径
    3. * @author USER
    4. * date 2021年7月12日
    5. * @version 1.0
    6. */
    7. @WebListener
    8. public class ApplicationListener implements ServletContextListener {
    9. public void contextDestroyed(ServletContextEvent arg0) {
    10. System.out.println("上下文销毁化完毕");
    11. }
    12. public void contextInitialized(ServletContextEvent arg0) {
    13. System.out.println("上下文初始化完毕");
    14. arg0.getServletContext().setAttribute("bp", arg0.getServletContext().getContextPath());
    15. }
    16. }
  • 相关阅读:
    (附源码)计算机毕业设计Java大学生学科竞赛报名管理系统
    leetcode 518. 零钱兑换 II、377. 组合总和 Ⅳ
    [{data:{data:[{}]},{data:{data:[{}]}] JS解构赋值拿到内层的data数据
    day15-Linux对文件系统的支持
    9.18 QT作业
    【高阶数据结构】跳表
    供应商关系管理的重要性
    【附源码】计算机毕业设计JAVA校园讲座管理
    竟然还有人不会配置idea鼠标调节字体?
    muduo库的高性能日志库(五)——AsyncLogging文件
  • 原文地址:https://blog.csdn.net/lmdbhf/article/details/127727277