Spring与web环境集成

1. 为什么Spring要与web环境集成?

在之前讲解的案例中,我们将 Dao 层和 Service 层的类通过 IOC 容器实例化,在 web 层通过 ApplicationContext接口实例化创建 Bean 调用具体业务。但是在实际开发中, 在 web 层不止一个类,所以每次从容器中获取 Bean 时都要实例化接口,这样弊端是配置文件加载多次,应用上下文对象创建多次。所以为了简化此过程,我们可以将 Spring 和 web 环境集成。

2. 集成的底层实现

在Web项目中,可以使用ServletContextListener监听Web应用的启动,我们可以在Web应用启动时,就加载Spring的配置文件,创建应用上下文对象ApplicationContext,在将其存储到最大的域servletContext域中,这样就可以在任意位置从域中获得应用上下文ApplicationContext对象了。具体代码如下:

//监听器类
public class ContextLoaderListener implements ServletContextListener
{

    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //ServletContext域实例化
        ServletContext servletContext = servletContextEvent.getServletContext();
        //读取web.xml中的全局参数
        String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
        //实例化 IOC容器
        ApplicationContext app = new ClassPathXmlApplicationContext(contextConfigLocation);
        //将Spring的应用上下文对象存储到ServletContext域中
        servletContext.setAttribute("app",app);
    }

    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}
//web中的web.xml 配置文件中添加
<!--全局初始化参数-->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>

<!--配置监听器-->
<listener>
    <listener-class>com.ContextLoaderListener</listener-class>
</listener>
//在 web 层中获取 Spring 应用上下文对象
public class UserServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //ServletContext域实例化
        ServletContext servletContext = this.getServletContext();
        //取出 ServletContext域中的 Spring的应用上下文对象
        ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
    }
}

上述案例手动的完成了 Spring与web环境集成,但是在 web 层获取出 Spring的应用上下文对象时需要提供存入的名称,所以需要进一步提取参数,修改如下:

//添加一个工具类
public class WebApplicationContextUtils {
  
    //定义一个静态方法
    //用于返回 ServletContext域中的 Spring的应用上下文对象
    public static ApplicationContext getWebApplicationContext(ServletContext servletContext){
        return (ApplicationContext) servletContext.getAttribute("app");
    }

}
//修改 web 层的代码
public class UserServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //ServletContext域实例化
        ServletContext servletContext = this.getServletContext();
        //取出 ServletContext域中的 Spring的应用上下文对象
        //只修改了这一行代码
        ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        //获取 Bean 
        UserService userService = app.getBean(UserService.class);
    }
}

上述就是使用手动完成 Spring与web环境的集成。上面讲了一大串代码,但是不需要记忆,有一个大概的了解,知道 Spring与web环境集成的底层是如何实现的。

3. Spring实现集成

其实在集成不用手动实现,Spring提供了一个监听器 ContextLoaderListener就是对上述功能的封装,该监听器内部加载 Spring 配置文件,创建应用上下文对象,并存储到 ServletContext 域中,提供了一个客户端工具WebApplicationContextUtils类供使用者获得应用上下文对象。

那么具体使用流程:

  1. 导入Spring集成web的包:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.3.8</version>
    </dependency>   
    
  2. 在web.xml 配置文件中添加添加配置文件:

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    
    <!--配置监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
  3. 在web 层调用:

    public class UserServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          //ServletContext域实例化
          ServletContext servletContext = this.getServletContext();
          //取出 ServletContext域中的 Spring的应用上下文对象
          //只修改了这一行代码
          ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
       }
    }  
    

对比两种方式,其实只是少了两个类的创建,Spring 已经将两个类的创建进行了封装,所以在使用过程中没有区别。


当然有一点需要提醒的,在两种方式中我们都使用到了ContextLoaderListener类和WebApplicationContextUtils类,在这两种方法中这两个类是有区别的。第一种方式中的两个类的类名是自定义的,也可以换成其他类名;第二种方式中的两个类的类名是已经固定了,无法改变。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值