Spring集成web环境-ContextLoaderListener监听器的分析
Posted bfhonor
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring集成web环境-ContextLoaderListener监听器的分析相关的知识,希望对你有一定的参考价值。
一、Spring与Web环境集成
1. ApplicationContext应用上下文获取方式
- 通过上次Spring集成web环境-基本三层架构环境搭建文章,我们可以了解到应用上下文对象是通过new ClasspathXmlApplicationContext(spring配置文件)方式获取的,但是每次从容器中获得Bean时都要编写new ClasspathXmlApplicationContext(spring配置文件),这样的弊端是配置文件加载多次,应用上下文对象创建多次。
- 在Web项目中,可以使用ServletContextListener监听Web应用的启动,我们可以在Web应用启动时,就加载Spring的配置文件,创建应用上下文对象ApplicationContext,在将其存储到最大的域servletContext域中,这样就可以在任意位置从域中获得应用上下文ApplicationContext对象了。
2. 自定义ContextLoaderLister
- 通过上次Spring集成web环境-基本三层架构环境搭建文章,创建并搭建好项目。
- 在
src\\main\\java
里面创建com.itheima.listener
包,在此包下创建ContextLoaderListener文件
package com.itheima.listener;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ContextLoaderListener implements ServletContextListener
//contextInitialized上下文初始化的方法
//服务器一启动,只要监听到就会执行此方法
@Override
public void contextInitialized(ServletContextEvent servletContextEvent)
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
//将Spring的应用上下文对象存储到ServletContext域中
ServletContext servletContext = servletContextEvent.getServletContext();
servletContext.setAttribute("app",app);
System.out.println("spring容器创建完毕...");
//contextDestroyed上下文销毁的方法
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent)
- 在
src\\main\\webapp\\WEB-INF
里面配置web.xml
,添加listener监听器
<!--配置监听器-->
<listener>
<listener-class>com.itheima.listener.ContextLoaderListener</listener-class>
</listener>
- 此时倘若我们运行tomcat服务器,我们可以通过控制台看出一下结果,表示此时服务器启动,但是我们没有访问也会将spring容器创建成功,如果去访问服务器的时候,就不会再次创建了,直接从服务器里面拿就可以。
3. 自定义ContextLoaderLister代码优化①
- ❌❌❌由于在上述的文件中,我们可以看到
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
是写死的,并且applicationContext.xml文件是随机命名的,命名成其他形式也是可以的;只不过在这里我们约定俗成的把它命名为applicationContext.xml,万一后期我们不适用这个名字,使用其他的名字;那就无法使用了❌❌❌ - 所以我们需要将
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
提取到配置文件里面 - 在
web.xml
文件里面添加如下配置
<!--全局齿初始化参数-->
<context-param>
<param-name>contextConfigLocation</param-name><!--命名什么类型都可以-->
<param-value>applicationContext.xml</param-value><!--填写配置文件的名称-->
</context-param>
- 然后修改
src\\main\\java
里面com.itheima.listener
包下的ContextLoaderListener.java文件
package com.itheima.listener;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ContextLoaderListener implements ServletContextListener
//contextInitialized上下文初始化的方法
//服务器一启动,只要监听到就会执行此方法
@Override
public void contextInitialized(ServletContextEvent servletContextEvent)
ServletContext servletContext = servletContextEvent.getServletContext();//👈先提取到ServletContext
//👇然后读取web.xml中的全局参数
String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
ApplicationContext app = new ClassPathXmlApplicationContext(contextConfigLocation);
//将Spring的应用上下文对象存储到ServletContext域中
servletContext.setAttribute("app",app);
System.out.println("spring容器创建完毕...");
//contextDestroyed上下文销毁的方法
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent)
4. 自定义ContextLoaderLister代码优化②
- 在
src\\main\\java
文件com.itheima.web
包下的UserServlet.java文件
ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
- ❌❌❌其中的“app”也是耦合死的,这导致我们每次都需要记住app,然后再去其他文件里面创建。❌❌❌
- 在
src/main/java
文件com.itheima.listener
包里面创建WebApplicationContextUtils.java工具类
package com.itheima.listener;
import org.springframework.context.ApplicationContext;
import javax.servlet.ServletContext;
public class WebApplicationContextUtils
public static ApplicationContext getWebApplicationContext(ServletContext servletContext)
return (ApplicationContext) servletContext.getAttribute("app");
- 在
src/main/java
文件com.itheima.web
包里面修改UserServlet.java文件
package com.itheima.web;
import com.itheima.listener.WebApplicationContextUtils;
import com.itheima.service.UserService;
import org.springframework.context.ApplicationContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class UserServlet extends HttpServlet
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
ServletContext servletContext = this.getServletContext();
//ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
//👇此时已经替代了具体的字符串“app”,已经解耦合❗❗❗
ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
UserService userService = app.getBean(UserService.class);
userService.save();
- 以上是我们对于Spring提供获取上下文工具底层封装的逐步了解和实现,方便我们理解和掌握。
- 下面我们可以直接使用Spring自动提供的获取应用上下文工具
5. Spring提供获取应用上下文的工具
-
上面的分析不用手动实现,Spring提供了一个监听器ContextLoaderListener就是对上述功能的封装,该监听器内部加载Spring配置文件,创建应用上下文对象,并存储到ServletContext域中,提供了一个客户端工具WebApplicationContextUtils供使用者获得应用上下文对象。
-
所以我们需要做的只有两件事:
①在web.xml中配置ContextLoaderListener监听器(导入spring-web坐标)
②使用WebApplicationContextUtils获得应用上下文对象ApplicationContext
(1)导入Spring集成web的坐标
- 在pom.xml文件中导入坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
(2)配置ContextLoaderListener监听器
- 在web.xml文件中配置监听器
<!--全局参数-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--Spring的监听器-->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
(3)通过工具获得应用上下文对象
- 在web层代码,
src\\mian\\java
文件里面com.itheima.web
包里面的UserServlet.java文件
ApplicationContext applicationContext =
WebApplicationContextUtils.getWebApplicationContext(servletContext);
Object obj = applicationContext.getBean("id");
package com.itheima.web;
import com.itheima.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class UserServlet extends HttpServlet
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
ServletContext servletContext = this.getServletContext();
//调用org.springframework.web.context.support包下的WebApplicationContextUtils工具类,Spring已经为我们封装好
ApplicationContext app = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
UserService userService = app.getBean(UserService.class);
userService.save();
以上是关于Spring集成web环境-ContextLoaderListener监听器的分析的主要内容,如果未能解决你的问题,请参考以下文章
Spring - Spring集成web环境 -基本三层架构搭建案例
Spring集成web环境-ContextLoaderListener监听器的分析
Spring集成web环境-ContextLoaderListener监听器的分析