目录
1、简介
2、监听器
3、Spring提供的listener
3.1、xml
3.2、配置类
3.3、WebApplicationContextUtils
3.4、说明
4、自己复现的listener
4.1、ContextLoaderListener
4.2、WebApplicationContextUtils
4.3、Web调用
⭐作者介绍:大二本科网络工程专业在读,持续学习Java,努力输出优质文章
⭐作者主页:@逐梦苍穹
⭐所属专栏:JavaEE、Spring
Spring与Web的集成是指将Spring框架与Web开发技术相结合,使得Spring能够更好地支持Web应用的开发。Spring提供了许多功能和特性来简化Web应用的开发,包括Web MVC、Web安全、Web服务等。
以下是Spring与Web集成的主要内容:
综上所述,Spring与Web集成是一套完整的技术解决方案,使得Spring能够更好地支持Web应用的开发,提供了丰富的功能和特性,帮助开发者构建高效、安全、可靠的Web应用程序。
应用上下文对象是通过new ClasspathXmlApplicationContext("applicationContext.xml");
或new AnnotationConfigApplicationContext(SpringConfiguration.class);
方式获取的,但是每次从容器中获得Bean时都要编写这样的代码 ,这样的弊端是配置文件加载多次,应用上下文对象创建多次。
在Web项目中,可以使用ServletContextListener监听Web应用的启动,我们可以在Web应用启动时,就加 载Spring的配置文件,创建应用上下文对象ApplicationContext,在将其存储到最大的域servletContex中,这样就可以在任意位置从域中获得应用上下文ApplicationContext对象了。
Spring提供了一个监听器ContextLoaderListener,就是对上述功能的封装。
该监听器内部加载Spring配置文件,创建应用上下文对象,并存储到ServletContext域中,提供了一个客户端工具WebApplicationContextUtils供使用者获得应用上下文对象。
所以我们需要做的只有两件事:
① 在web.xml中配置ContextLoaderListener监听器(导入spring-web坐标)
② 使用WebApplicationContextUtils获得应用上下文对象ApplicationContext
首先是要配置监听器,自己复现的监听器,则配置自己的监听器类或者在监听器类上声明@WebListener
注解:
然后是配置web应用的初始化参数(就是要加载spring配置):
按照上面的步骤,配置监听器、加载配置、使用工具类获取ApplicationContext对象,完成之后,Spring项目启动的时候,自动加载spring的监听器,获取web.xml中的初始化参数,即获取相关配置文件。
在 contextInitialized() 方法中,ContextLoaderListener 创建一个新的 Spring 容器,一般情况下使用的是 XmlWebApplicationContext
或者 AnnotationConfigWebApplicationContext
。
完成 Spring 容器的初始化后,ContextLoaderListener 将 Spring 容器存储到 ServletContext 域对象中,以便在整个 Web 应用程序中共享。
此时,Spring 容器已经准备好,可以通过 ServletContext 域对象获取并使用其中的 Bean 实例。
基本工作思路同Spring提供的一样。先编写监听器类,再编写工具类,然后在web.xml配置初始化参数,便于监听器读取。
目录结构如下:
这个部分复现ContextLoaderListener的功能。
先声明监听器,然后实现ServletContextListener,重写两个方法。重点是初始化方法。
在初始化方法中,我们需要的就是把上下文对象存入ServletContext域中,以便整个Web应用共享。
这里提供三种方式,一种是直接加载配置文件contextInitialized_commonlyMethod(servletContextEvent);
,另外两种是用上下文对象加载web.xml文件中配置的初始值,分别是:
加载xml配置文件:contextInitialized_getXmlConfig_From_WebXml(servletContextEvent);
加载Java配置类:contextInitialized_getSpringConfigurationNoTest_ConfigClass_From_WebXml(servletContextEvent);
代码如下:
package com.xzl.listener;
import com.xzl.config.SpringConfigurationNoTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* @author 逐梦苍穹
* @date 2023/7/22 17:09
*/
@WebListener
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//直接加载配置文件
// contextInitialized_commonlyMethod(servletContextEvent);
//用上下文对象加载web.xml中的初始值
//加载xml配置文件
// contextInitialized_getXmlConfig_From_WebXml(servletContextEvent);
//加载Java配置类
contextInitialized_getSpringConfigurationNoTest_ConfigClass_From_WebXml(servletContextEvent);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
public void contextInitialized_commonlyMethod(ServletContextEvent servletContextEvent) {
//加载配置类
//AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfigurationNoTest.class);
//加载配置文件applicationContext.xml
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
ServletContext servletContext = servletContextEvent.getServletContext();
servletContext.setAttribute("applicationContext", applicationContext);
System.out.println("监听器spring容器创建成功");
}
public void contextInitialized_getXmlConfig_From_WebXml(ServletContextEvent servletContextEvent) {
ServletContext servletContext = servletContextEvent.getServletContext();
//获取 web.xml 配置文件中设置的初始化参数的值,这里获取到的是配置文件对象(可以是xml也可以是配置Java类)
String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
System.out.println(contextConfigLocation);
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(contextConfigLocation);
//这个地方存入servletContext域对象,当开发人员取对象的时候,也是存在耦合。所以要修改UserServlet.java代码
servletContext.setAttribute("applicationContext", applicationContext);
System.out.println("监听器spring容器创建成功");
}
public void contextInitialized_getSpringConfigurationNoTest_ConfigClass_From_WebXml(ServletContextEvent servletContextEvent) {
ServletContext servletContext = servletContextEvent.getServletContext();
//获取 web.xml 配置文件中设置的初始化参数的值,这里获取到的是配置文件对象(可以是xml也可以是配置Java类)
String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
try {
Class> contextConfigLocation_Class = Class.forName(contextConfigLocation);
System.out.println(contextConfigLocation_Class);
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(contextConfigLocation_Class);
servletContext.setAttribute("applicationContext", applicationContext);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(contextConfigLocation);
System.out.println("监听器spring容器创建成功");
}
}
当web应用获取的时候,需要:
ServletContext servletContext = req.getServletContext();
ApplicationContext app = (ApplicationContext) servletContext.getAttribute("applicationContext");
可以看到这里存在耦合,每一个web调用的地方,开发者都需要记住当时在监听器中存入的"applicationContext"标识:
所以这里进行解耦合,学spring官方提供一个工具类WebApplicationContextUtils
,用于让web层创建ApplicationContext对象:
很明显可以看到,这就是刚刚"每个web层代码需要重复干的事情"。这里直接使用工具类完成然后返回对象,开发者就不需要记住"applicationContext"。