zoukankan      html  css  js  c++  java
  • 记录搭建SSM框架中常用到的功能:(监听器)、过滤器和拦截器 以及相关的拓展内容的学习记录

    写在前面:

      其实现在更多的人在使用springboot框架来搭建项目,好处是简单方便拓展,但是想要学习以上说明的三个功能,我个人感觉还是从SSM框架进行切入,能够方便理解。另外,这篇博客更多的是记录如何使用,涉及原理的部分需要更多得学习。

    SSM框架和监听器、过滤器、拦截器 —— 监听器

    能帮助开发者监听web中的特定事件,比如ServletContext,HttpSession,ServletRequest的创建和销毁;变量的创建、销毁和修改等。可以在某些动作前后增加处理,实现监控。

    1.1 初识监听器,了解web.xml加载过程

    我们应该都知道,对于ssm搭建的javaWeb项目,一般都是使用Tomcat或Jboss等服务器容器来启动的,java项目启动配置弄好之后,启动容器,就可以将项目启动。一般 tomcat 或者 Jboss 都是先访问加载web项目的web.xml配置文件。

    容器一般是先加载该配置文件中的节点<context-param> 和 <listener>:

      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-context.xml</param-value>
      </context-param>
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>

    紧接着容器会创建ServletContext,这是属于该web项目的上下文环境,所谓上下文环境其实也可以理解为一个容器,里面装着web的应用信息。注意一个web项目也只有一个ServletContext,其生命周期是

    • 创建:容器启动(将web应用加载到容器中)
    • 销毁:容器关闭,服务器shut down

    那这个ServletContext对象的作用是什么呢?

    • 获得web应用全局初始化参数,之后项目中便可以调用这些参数。
    • 可以通过这个context获得web项目中任何资源的绝对路径:

        string path= context.getrealpath(“相对于该web应用的相对路径”);注意:src下的文件被服务器内部加载会被放到WEB-INF/classes文件夹中。

          例:string path_c =context.getrealpath(“WEB-INF/classes/c.txt”)     

        也可以使用类加载器,专门加载classes文件夹下的文件。xxxservlet.class.getClassloader().getresource(“c.txt”).getpath();其中c.txt 是相对于classes的相对路径。

    • 它是一个域对象,域对象:存储数据的区域就是域对象。

      ServletContext域对象的作用范围是整个web应用(所有web应用中的自资源都可以向ServletContext对象中存储数据,而且数据可以共享)。

    首先容器以<context-param>中的<param-name>为键,<param-value>为值,将数据转换为键值对,存入ServletContext中;

    接着容器会创建<lisrtener>中的类实例,根据配置的class的类路径<listener-class>,来创建监听对象ContextLoaderListener,该对象中的 contextInitialized 是初始化方法,启动web时,调用该方法,得到ServletContextEventevent.getServletContext();

    public void contextInitialized(ServletContextEvent event){         
        this.initWebApplicationContext(event.getServletContext());
    }

    接着容器会读取<filter>节点,根据指定类路径来实例化过滤器;


    以上是在web项目还没有完全启动起来的时候,已经完成了工作。如果系统中有Servlet,则servlet是在第一次调用的时候被实例化的,且一般不会被容器销毁,他可以服务多个用户的请求。所以Servlet会被上面的元素初始化的要迟;

    总的来说,web.xml的加载顺序是:
    <context-param> —> <listener> —> <filter> —> <servlet>,如果web.xml中出现了相同的元素,则按照元素出现的先后顺序加载。

    1.2 要怎么编辑自定义监听器呢?

    从上述可以知道,想要SSM项目启动需要在web.xml中配置上监听器ContextLoaderListener,而该监听器的作用是 可以初始化<context-param>中的参数到ServletContext中。

    那么我们如果想要自定义监听器的话就可以参考ContextLoaderListener。我们先看一下该类中的源码是怎么实现的:

    package org.springframework.web.context;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
        public ContextLoaderListener() {
        }
    
        public ContextLoaderListener(WebApplicationContext context) {
            super(context);
        }
    
        public void contextInitialized(ServletContextEvent event) {
            this.initWebApplicationContext(event.getServletContext());
        }
    
        public void contextDestroyed(ServletContextEvent event) {
            this.closeWebApplicationContext(event.getServletContext());
            ContextCleanupListener.cleanupAttributes(event.getServletContext());
        }
    }

    可以看到该监听器继承了接口 ServletContextListener  ,接口中有两个需要实现的方法 contextInitialized 和 contextDestroyed:

    package javax.servlet;
    
    import java.util.EventListener;
    
    public interface ServletContextListener extends EventListener {
        void contextInitialized(ServletContextEvent var1);
    
        void contextDestroyed(ServletContextEvent var1);
    }

    很明显是初始化方法和销毁方法。据查询,该接口的实现类的对应的方法,将会在Tomcat 或者 Jboss 容器启动过程中进行回调。

    1.2.1 ServletContextListener 接口

    因此,如果我们想要在项目启动的时候 自定义加载初始化信息(如:配置数据库信息、设置计时器去定时执行任务等操作)监听器的话,

    可以参考在自定义的 Listener 类中去实现 ServletContextListener 接口,如:

    package com.shine.platform.listener;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @Author: Shine EtherealWind
     * @Description:
     * @Date: create in 17:07 2021/7/29
     */
    public class TestMyListener implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            System.out.println("* 应用启动的时候 TestMyListener init... *");
            Map<String, String> sysRoles = new HashMap<>();
            sysRoles.put("ADMIN","管理员");
            sysRoles.put("NEWMAN", "小白用户");
            sysRoles.put("BIZUSER", "业务用户");
            servletContextEvent.getServletContext().setAttribute("SYS_ROLES", sysRoles);
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
        }
    }

    然后别忘记在web.xml中配置监听

    <listener>
        <listener-class>com.shine.platform.listener.TestMyListener</listener-class>
    </listener>

    就是在启动应用的时候加载TestMyListener 的初始化方法,可以将信息放到ServletContext中。

    那在应用层怎么调用呢?

    方法一:

    WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
    ServletContext servletContext = webApplicationContext.getServletContext();
    Map<String, String> sysRoles = (Map<String, String>)servletContext.getAttribute("SYS_ROLES");
    System.out.println("初始化监听器中设置的角色:" + sysRoles.get("ADMIN"));

    方法二:

    @RequestMapping(value = "/login")
        @ResponseBody
        public String login(User user, HttpServletRequest request){
            List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
    
            Map<String, String> sysRoles2 = (Map<String, String>)request.getServletContext().getAttribute("SYS_ROLES");
            System.out.println("初始化监听器中设置的角色:" + sysRoles2.get("BIZUSER"));
         return null; }

     而执行的结果中是能够得到期望结果的

     1.2.2 HttpSessionListener接口

    对于javaweb项目,当浏览器第一次访问服务器的时候,服务器就会创建一个session。如果我们想要监听当前网站的访问人数,实现对httpsession的监控又要怎么去做呢?

    java提供有HttpSessionListener来监听Httpsession。因此我们来实现该接口就可以做到监听session了

    package com.shine.platform.listener;
    
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    /**
     * @Author: Shine EtherealWind
     * @Description:
     * @Date: create in 9:54 2021/8/5
     */
    public class TestHttpSessionListener implements HttpSessionListener {
    
        private static int visitNum = 0;
    
        @Override
        public void sessionCreated(HttpSessionEvent httpSessionEvent) {
            System.out.println("会话创建的时候调用该方法 TestHttpSessionListener . sessionCreated");
            visitNum ++ ;
            System.out.println("当前系统访问用户数:"+visitNum);
        }
    
        @Override
        public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
            System.out.println("...destroy...");
            visitNum -- ;
            System.out.println("当前系统访问用户数:"+visitNum);
        }
    }

    注意:不要忘记web.xml里面的配置

      <listener>
        <listener-class>com.shine.platform.listener.TestHttpSessionListener</listener-class>
      </listener>

    在有浏览器第一次访问服务器的时候监听触发sessionCreated方法,而sessionDestroyed方法是在调用session.invalidate()方法时或者超过session有效期被触发

    其中session的有效期可以再web.xml中被配置,需要注意单位是分钟:

     1.2.3 ServletRequestListener接口

    该接口监听的是 ServletRequest 对象,

    当客户端向服务器发送一次请求,服务器就会调用初始化方法,

    当服务器对这个请求作出响应之后,就会调用销毁方法。

    用途:可以用来记录系统被访问的次数。

  • 相关阅读:
    Study Plan The Twelfth Day
    Study Plan The Fifteenth Day
    Study Plan The Seventeenth Day
    Study Plan The Tenth Day
    Study Plan The Eighth Day
    Study Plan The Eleventh Day
    Study Plan The Sixteenth Day
    Study Plan The Thirteenth Day
    Study Plan The Fourteenth Day
    Study Plan The Ninth Day
  • 原文地址:https://www.cnblogs.com/EtherealWind/p/15097242.html
Copyright © 2011-2022 走看看