Spring和SpringMVC 父子容器的问题

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: Spring与SpringMVC的容器属于父子容器关系,在配置使用SpringMVC时,若SpringMVC容器在Spring容器之前创建,可能会导致项目在编译运行时出现异常。

SpringMVC的父子容器问题

在使用SpringMVC 的时候,我们需要对前端控制器进行配置,前端控制器(DispatcherServlet)需要有一个 WebApplicationConetxt作为它的环境配置。


而 SpringMVC 作为 Spring 框架的一个子框架 ,自己拥有一个独立的子容器(Servlet WebApplicationContext),这个容器中应该包含 controller、view resolvers(视图适配器)、handlerMapping(处理器映射器)以及其他的一些和 web 相关的类;


但是如果在这个子容器中没有找到需要的组件(Component),那么SpringMVC 会到一个父容器的环境中(Root WebApplicationContext)去获取。而如果这个时候,父容器没有创建,那么就找不到对应的组件,编译器就会抛出异常,因此在配置前端控制器的时候,应该保证子容器当中可以获取到controller等的一些组件,并且父容器也要被创建。

image.pngimage.png

解决方法

在 springmvc.xml 中配置包扫描,扫描 controller 包

<?xmlversion="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.alibaba.com/schema/stat"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.alibaba.com/schema/stathttp://www.alibaba.com/schema/stat.xsd"><!--扫描controller--><context:component-scanbase-package="com.sxt.controller"/><!--配置spring注解的驱动(处理器映射器、处理器适配器)--><mvc:annotation-driven/><!--配置视图适配器--><beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"><propertyname="prefix"value="/view/"/><propertyname="suffix"value=".jsp"/></bean></beans>

情况一:在配置前端控制器的时候,使用通配符( * )来引入两个配置文件(springdao.xml [主容器配置文件]和 springmvc.xml [springMVC配置文件])

这种情况在理论上是可以满足需求的,但是由于使用的是通配符直接加载两个配置文件,不排除在创建的时候父容器之前就已经创建了子容器,这样也会出现错误

<!--配置前端控制器--><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><!--读取springmvc配置文件--><param-value>classpath:spring*.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet>

情况二:在 web.xml 中配置监听器(ContextLoaderListener),这个监听器在 web 启动的时候就会加载对应的 contextConfig 对应的配置文件,来创建父容器

<!--配置监听器--><!--该监听器可以使 web 在启动的时候加载contextConfig配置文件,创建application容器--><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!--配置环境配置文件--><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:springdao.xml</param-value></context-param>

情况三:前端控制器中配置 springdao.xml 作为它的环境配置(ContextConfiguration),并且在 springdao.xml 中通过 <import> 引入 springmvc.xml,这样来保证两个容器的创建顺序。

<!--配置前端控制器--><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><!--读取springmvc配置文件--><param-value>classpath:springdao.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet>

springdao.xml 文件配置:

<?xmlversion="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttps://www.springframework.org/schema/tx/spring-tx.xsd"><!--设置注解配置包的扫描位置--><context:component-scanbase-package="com.sxt"/><!--配置读取db.properties数据库配置文件--><context:property-placeholderlocation="classpath:dbinfo.properties"/><!--配置数据库连接池--><beanid="dataSource"class="com.alibaba.druid.pool.DruidDataSource"><propertyname="driverClassName"value="${mysql.driver}"/><propertyname="url"value="${mysql.url}"/><propertyname="username"value="${mysql.username}"/><propertyname="password"value="${mysql.password}"/></bean><!--配置mybatis框架的 SqlSessionFactory 类,创建 SqlSessionFactory 工厂对象--><beanclass="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"id="sqlSessionFactory"><!--注入数据--><propertyname="dataSource"ref="dataSource"/><!--配置别名使用包扫描--><propertyname="typeAliasesPackage"value="com.sxt.bean"/><!--读取mybatis-config配置文件,实现其他个性配置--><propertyname="configLocation"value="classpath:mybatis-config.xml"/></bean><!--使用包扫描创建 Mapper 代理对象--><beanclass="org.mybatis.spring.mapper.MapperScannerConfigurer"><!--配置需要创建Mapper接口代理对象对应的包--><propertyname="basePackage"value="com.sxt.mapper"/><!--配置SqlSessionFactory的名称,不是引用--><propertyname="sqlSessionFactoryBeanName"value="sqlSessionFactory"/></bean><!--配置事务管理器--><beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--注入数据源--><propertyname="dataSource"ref="dataSource"/></bean><!--spring事务配置--><tx:adviceid="txAdvice"transaction-manager="transactionManager"><tx:attributes><!--DQL:查询操作,配置只读事务--><tx:methodname="get*"read-only="true"isolation="REPEATABLE_READ"propagation="REQUIRED"/><tx:methodname="find*"read-only="true"isolation="REPEATABLE_READ"propagation="REQUIRED"/><tx:methodname="select*"read-only="true"isolation="REPEATABLE_READ"propagation="REQUIRED"/><tx:methodname="query*"read-only="true"isolation="REPEATABLE_READ"propagation="REQUIRED"/><!--其他SQL:非只读事务--><tx:methodname="*"read-only="false"isolation="REPEATABLE_READ"propagation="REQUIRED"/></tx:attributes></tx:advice><!--配置AOP切入事务--><aop:config><!--切入点--><aop:pointcutid="pt"expression="execution(* com.sxt.service..*(..))"/><!--切面--><aop:advisoradvice-ref="txAdvice"pointcut-ref="pt"/></aop:config><importresource="classpath:springmvc.xml"/></beans>
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
17天前
|
SQL Java 数据库连接
对Spring、SpringMVC、MyBatis框架的介绍与解释
Spring 框架提供了全面的基础设施支持,Spring MVC 专注于 Web 层的开发,而 MyBatis 则是一个高效的持久层框架。这三个框架结合使用,可以显著提升 Java 企业级应用的开发效率和质量。通过理解它们的核心特性和使用方法,开发者可以更好地构建和维护复杂的应用程序。
106 29
|
2天前
|
XML Java 数据格式
Spring容器的本质
本文主要讨论Spring容器最核心的机制,用最少的代码讲清楚Spring容器的本质。
|
2月前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
73 6
|
2月前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
50 1
|
3月前
|
前端开发 Java Docker
使用Docker容器化部署Spring Boot应用程序
使用Docker容器化部署Spring Boot应用程序
|
3月前
|
Java Docker 微服务
利用Docker容器化部署Spring Boot应用
利用Docker容器化部署Spring Boot应用
71 0
|
9月前
|
XML Java 数据格式
Spring IoC容器初始化过程(xml形式)
Spring IoC容器初始化过程(xml形式)
102 0
|
9月前
|
XML Java 数据格式
Spring5源码(15)-IoC容器启动过程简析及XmlBeanFactory初始化
Spring5源码(15)-IoC容器启动过程简析及XmlBeanFactory初始化
81 1
|
XML Java 数据格式
Spring源码阅读-IOC容器初始化过程
Spring IOC容器的初始化过程:Resource定位,BeanDefinition载入,向IOC容器注册BeanDefinition。整个过程由refresh()方法触发,三个过程由不同的模块完成,使用户更加灵活的对这三个过程剪裁和扩展。
182 0
|
XML JavaScript Java
Spring IoC容器初始化过程(xml形式)
Resource是Spring中用于封装I/O操作的接口,在创建Spring的容器的时候,会根据xml对应配置的类型,加载不同的数据类型
83 0