目录
3.3、WebApplicationContextUtils
4.2、WebApplicationContextUtils
⭐作者介绍:大二本科网络工程专业在读,持续学习Java,努力输出优质文章
⭐作者主页:@逐梦苍穹
1、简介
Spring与Web的集成是指将Spring框架与Web开发技术相结合,使得Spring能够更好地支持Web应用的开发。Spring提供了许多功能和特性来简化Web应用的开发,包括Web MVC、Web安全、Web服务等。
以下是Spring与Web集成的主要内容:
- Spring Web MVC: Spring提供了一个强大的Web MVC框架,用于构建灵活、可扩展的Web应用程序。通过使用Spring的DispatcherServlet,开发者可以将请求路由到控制器并处理响应。Spring Web MVC支持注解和XML配置两种方式,使得编写控制器和处理请求变得非常简单。
- Spring Web 安全: Spring Security是Spring提供的一套安全框架,用于处理Web应用程序的安全需求,如认证、授权、权限管理等。Spring Security可以轻松地与Spring Web应用集成,并提供强大的安全特性,保护应用程序免受各种安全威胁。
- Spring Web 服务: Spring支持集成Web服务技术,包括SOAP和RESTful服务。通过使用Spring Web服务,开发者可以轻松地创建和发布Web服务,并与外部系统进行通信。
- Spring Web 数据: Spring提供了各种用于处理Web数据的特性,包括数据绑定、表单处理、文件上传等。Spring的数据绑定功能使得处理表单数据非常简单,可以将请求参数绑定到Java对象上。
- Spring Web 视图: Spring支持各种视图技术,包括JSP、Thymeleaf、Freemarker等。通过使用Spring的视图技术,开发者可以轻松地渲染模型数据并生成最终的页面输出。
- Spring Web 测试: Spring提供了一套用于测试Web应用程序的工具和类库,包括MockMvc、TestRestTemplate等。通过使用Spring Web测试工具,开发者可以编写单元测试和集成测试,验证Web应用的行为和功能。
- Spring Boot: Spring Boot是Spring提供的快速构建Web应用的框架。它可以自动配置Spring应用程序,并提供各种现成的依赖库和功能,使得开发者可以更专注于业务逻辑而不用关心繁琐的配置。
综上所述,Spring与Web集成是一套完整的技术解决方案,使得Spring能够更好地支持Web应用的开发,提供了丰富的功能和特性,帮助开发者构建高效、安全、可靠的Web应用程序。
2、监听器
应用上下文对象是通过**new ClasspathXmlApplicationContext("applicationContext.xml");**或 **new AnnotationConfigApplicationContext(SpringConfiguration.class);**方式获取的,但是每次从容器中获得Bean时都要编写这样的代码 ,这样的弊端是配置文件加载多次,应用上下文对象创建多次。
在Web项目中,可以使用ServletContextListener 监听Web应用的启动,我们可以在Web应用启动时,就加 载Spring的配置文件,创建应用上下文对象ApplicationContext ,在将其存储到最大的域 servletContex 中,这样就可以在任意位置从域中获得应用上下文ApplicationContext对象了。
3、Spring提供的listener
Spring提供了一个监听器**ContextLoaderListener,**就是对上述功能的封装。
该监听器内部加载Spring配置文件,创建应用上下文对象,并存储到ServletContext 域中,提供了一个客户端工具WebApplicationContextUtils供使用者获得应用上下文对象。
所以我们需要做的只有两件事:
① 在web.xml 中配置ContextLoaderListener监听器(导入spring-web坐标)
② 使用WebApplicationContextUtils 获得应用上下文对象ApplicationContext
首先是要配置监听器,自己复现的监听器,则配置自己的监听器类或者在监听器类上声明**@WebListener**注解:
然后是配置web应用的初始化参数(就是要加载spring配置):
3.1、xml
3.2、配置类
3.3、WebApplicationContextUtils
3.4、说明
按照上面的步骤,配置监听器、加载配置、使用工具类获取ApplicationContext对象,完成之后,Spring项目启动的时候,自动加载spring的监听器,获取web.xml中的初始化参数,即获取相关配置文件。
在 contextInitialized() 方法中,ContextLoaderListener 创建一个新的 Spring 容器,一般情况下使用的是 XmlWebApplicationContext 或者 AnnotationConfigWebApplicationContext。
完成 Spring 容器的初始化后,ContextLoaderListener 将 Spring 容器存储到 ServletContext 域对象中,以便在整个 Web 应用程序中共享。
此时,Spring 容器已经准备好,可以通过 ServletContext 域对象获取并使用其中的 Bean 实例。
4、自己复现的listener
基本工作思路同Spring提供的一样。先编写监听器类,再编写工具类,然后在web.xml配置初始化参数,便于监听器读取。
目录结构如下:
4.1、ContextLoaderListener
这个部分复现ContextLoaderListener的功能。
先声明监听器,然后实现ServletContextListener,重写两个方法。重点是初始化方法。
在初始化方法中,我们需要的就是把上下文对象存入ServletContext域中,以便整个Web应用共享。
这里提供三种方式,一种是直接加载配置文件contextInitialized_commonlyMethod(servletContextEvent);
,另外两种是用上下文对象加载web.xml文件中配置的初始值,分别是:
加载xml配置文件:contextInitialized_getXmlConfig_From_WebXml(servletContextEvent);
加载Java配置类:contextInitialized_getSpringConfigurationNoTest_ConfigClass_From_WebXml(servletContextEvent);
代码如下:
java
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容器创建成功");
}
}
4.2、WebApplicationContextUtils
当web应用获取的时候,需要:
ServletContext servletContext = req.getServletContext();
ApplicationContext app = (ApplicationContext) servletContext.getAttribute("applicationContext");
可以看到这里存在耦合,每一个web调用的地方,开发者都需要记住当时在监听器中存入的"applicationContext"标识:
所以这里进行解耦合,学spring官方提供一个工具类WebApplicationContextUtils,用于让web层创建ApplicationContext对象:
很明显可以看到,这就是刚刚"每个web层代码需要重复干的事情"。这里直接使用工具类完成然后返回对象,开发者就不需要记住"applicationContext"。