记录搭建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 对象,

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

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

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

posted @ 2021-08-05 17:17  EtherealWind  阅读(314)  评论(0编辑  收藏  举报