Spring和SpringMVC整合及关系

SpringMVC扼要的讲,就是控制请求和处理。有必要将Spring和SpringMVC整合,否则仅配置SpringMVC并完成Spring的功能,会造成业务逻辑混乱。

简要总结:①原理:采用监听器,可以在ServlertContext加载时,通过监听器加载Spring的配置文件,创建Spring容器。②Spring提供的监听器ContextLoaderListener (可以不用自己创建监听器)。下面为详细分析:

1、整合分析(模拟原理,SpringMVC可以通过在web.xml中直接配置监听器):

  ①在配置文件中加入Spring的配置文件。但需要考虑,web容器启动以后,Spring的配置文件不会自动加载。加载需要ApplicationContext调用其实现类ClassPathXmlApplicationContext的构造方法,实现Spring配置文件的加载。

  ②Spring配置文件什么时候加载?怎么加载?

Spring配置文件的一定需要在web项目启动时加载,而且必须在Servlet配置前加载(为控制层的自动装载做准备,SpringMVC所管理的控制层依赖于Spring管理的service业务逻辑层)。采用监听器Listener(监听在web程序执行中的一些事件,比如ServletContext的生命周期,或者某一属性是否变化,监听的是一个动作)。ServlertContext,在web项目启动时就会创建。因此,可以创建一个监听器,来监听ServletContext的生命周期,一旦ServletContext创建,就去加载Spring的配置文件

注意的问题:

  1)SpringMVC和Spring配置文件,如果都配置包的扫描,可能会导致有的bean被创建2次。解决办法,在Spring配置文件扫描中去除控制层的扫描:

    <context:component-scan base-package="com.atguigu">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

  2)在监听器加载Spring配置文件时,在ServletContext中绑定ApplicationContext对象,从而能够在控制层中使用Spring管理的bean。

复制代码
package com.atguigu.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Application Lifecycle Listener implementation class SpringListener
 *
 */
public class SpringListener implements ServletContextListener {

    /**
     * Default constructor. 
     */
    public SpringListener() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see ServletContextListener#contextDestroyed(ServletContextEvent)
     */
    public void contextDestroyed(ServletContextEvent arg0)  { 
         // TODO Auto-generated method stub
    }

    /**
     * @see ServletContextListener#contextInitialized(ServletContextEvent)
     */
    public void contextInitialized(ServletContextEvent sce)  { 
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
        ServletContext servletContext = sce.getServletContext();
        servletContext.setAttribute("ac", ac);
    }
    
}
复制代码
复制代码
package com.atguigu.controller;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;

import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.atguigu.bean.Teacher;

@Controller
public class TestController {

    @RequestMapping("/testListener")         //返回void,回去寻找与请求名一致的视图,即testListener。但实际中不会有void的情况
    public void testListener(HttpSession session) {
        //获取spring所管理的teacher对象
        ServletContext servletContext = session.getServletContext();
        ApplicationContext ac = (ApplicationContext)servletContext.getAttribute("ac");
        Teacher teacher = ac.getBean("teacher", Teacher.class);
        System.out.println(teacher);
    }
        
}
复制代码

Spring.xml

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- <bean id="user" class="com.atguigu.bean.User"></bean> -->
    <context:component-scan base-package="com.atguigu">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    
    <bean id="teacher" class="com.atguigu.bean.Teacher"></bean>

</beans>
复制代码

 

2、SpringMVC配置:(建议使用)

  1)、包扫描(排除控制层)

  2)、配置监听器 ContextLoaderListener


 

复制代码
  <!-- needed for ContextLoaderListener ,该配置表示Spring的配置spring.xml文件在类路径下,context-param标签表示项目启动时加载-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring.xml</param-value>
    </context-param>

    <!-- Bootstraps the root web application context before servlet initialization -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
复制代码

注意:Spring的配置文件有默认的名字和位置,在WEB-INF文件下,名为applicationContext.xml

错误:BeanFactory not initialized or already closed,出现的三种情况:

  ①Spring的配置文件找不到(路径或名称不对)

  ②Spring的配置文件没有创建

  ③Spring文件中出现了语法错误

 

Spring和SpringMVC关系

  Spring为父容器,SpringMVC为子容器。

  规定:子容器能够调用访问父容器中的bean,而父容器不能调用访问子容器中的bean.

SpringMVC      |     Spring

Controller         |     service   dao

 

posted @   kkzhang  阅读(1648)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示