SpringMVC上下文父子容器
2016-05-22 09:34
423 查看
在SpringMVC的启动依赖Spring框架,有时候我们在启动SpringMVC环境的时候,如果配置不当的话会造成一些不可预知的结果。下面主要介绍一下SpringMVC环境启动的时候context的状态。
通常情况下使用SpringMVC需要进行如下配置:
如上配置所示:listener是装载Spring框架本身的bean上下文(如Service和DAO层等);dispatcherServlet是装载Controller的上下文。
上述的配置指定了Spring框架所扫描的注解不包括@Controller,当然其他的配置文件(如:事务配置、AOP配置、定时任务等)可以通过引入进来。
上面配置是指定了DispatcherServlet所创建的上下文只扫描控制层的beans,当然在此配置文件中还可以指定视图解析、JSON转换、上传下载等配置信息。
在上面web.xml的配置中,listener会创建Spring环境的父类上下文。父类上下文创建完成之后,当初始化DispatcherServlet的时候,就会将之前初始化的context设置为parent。
tip:如果将listener启动的上下文和Dispatcher中启动的上下文所扫描的包都是全部包的话,就会造成在子类context和父类context都有全部的自定义beans,如下图所示
在容器启动后获取bean的时候,也是先从子类容器中去获取bean,子类获取不到时,再到父类容器中去寻找。当子类容器中装载了Service和Dao时,控制层就会使用子类容器所装载的bean去执行。但是这里面的service是没有事务等功能的(没有Spring框架的配置),只是普通的bean,因此使用起来会有不可预知的问题。
我们可以在父容器的bean中,轻松获得properties文件中的值,通过如下方式
但也如上面所说,在Controller层中,你是无法读取到的
写在最后
1、做为SpringMVC+Spring项目,是需要有两个注解扫描的
2、两个注解扫描的范围一定是不相同的
3、SpringMVC应该只扫描@Controller,可以采用两种写法
因为一般规范来说,Controller类肯定是在controller下,那么可以采用如下方式
还有一种方案就是可以扫描路劲直接短一点,到con.somnus,但是最终应该只指定扫描@Controller,比如
4、Spring涉及到的扫描面比较广,不合适具体指定某个子包(service、dao、aspect。。。etc)
但是它又不该去扫描@Controller注解,所以应该采取如下配置
当然也有人为了简洁直接写成扫描所有的
等于是把@Controller也扫描进去了,也不能说他错,虽然在父子容器中最终都有注解为@Controller的对象,但最终其实也只会先拿子容器的,父容器的等于是白定义了。
通常情况下使用SpringMVC需要进行如下配置:
1、web.xml中增加监听和dispatcherServlet入口
<context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:/spring-basic.xml </param-value> </context-param> <context-param> <param-name>spring.profiles.default</param-name> <param-value>dev</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
如上配置所示:listener是装载Spring框架本身的bean上下文(如Service和DAO层等);dispatcherServlet是装载Controller的上下文。
2、监听器入口自动扫描配置(spring-basic.xml)
<context:component-scan base-package="com.somnus.smart"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <import resource="classpath:/spring-env.xml" /> <import resource="classpath*:/spring-resource-*.xml" /> <import resource="classpath:/spring-mybatis.xml" /> <import resource="classpath:/security-shiro.xml" /> <import resource="classpath:/msg/spring-message.xml" />
上述的配置指定了Spring框架所扫描的注解不包括@Controller,当然其他的配置文件(如:事务配置、AOP配置、定时任务等)可以通过引入进来。
3、DispatcherServlet配置(spring-mvc.xml)
<context:component-scan base-package="com.somnus.smart.controller"/> <mvc:annotation-driven /> <!-- 视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="contentType" value="text/html"/> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean>
上面配置是指定了DispatcherServlet所创建的上下文只扫描控制层的beans,当然在此配置文件中还可以指定视图解析、JSON转换、上传下载等配置信息。
在上面web.xml的配置中,listener会创建Spring环境的父类上下文。父类上下文创建完成之后,当初始化DispatcherServlet的时候,就会将之前初始化的context设置为parent。
tip:如果将listener启动的上下文和Dispatcher中启动的上下文所扫描的包都是全部包的话,就会造成在子类context和父类context都有全部的自定义beans,如下图所示
在容器启动后获取bean的时候,也是先从子类容器中去获取bean,子类获取不到时,再到父类容器中去寻找。当子类容器中装载了Service和Dao时,控制层就会使用子类容器所装载的bean去执行。但是这里面的service是没有事务等功能的(没有Spring框架的配置),只是普通的bean,因此使用起来会有不可预知的问题。
4、此外当父容器通过如下方式引入的properties文件,子容器是读取不到的,如需用到,需再次配置
<util:properties id="requestinfo" location="classpath:requestinfo.properties" /> <context:property-placeholder location="classpath:/env/configurations-prd.properties" />
我们可以在父容器的bean中,轻松获得properties文件中的值,通过如下方式
@Value("${redis.host}") private String ip; @Value("#{requestinfo['version']}") private String version;
但也如上面所说,在Controller层中,你是无法读取到的
写在最后
1、做为SpringMVC+Spring项目,是需要有两个注解扫描的
2、两个注解扫描的范围一定是不相同的
3、SpringMVC应该只扫描@Controller,可以采用两种写法
因为一般规范来说,Controller类肯定是在controller下,那么可以采用如下方式
<context:component-scan base-package="com.somnus.controller"/>
还有一种方案就是可以扫描路劲直接短一点,到con.somnus,但是最终应该只指定扫描@Controller,比如
<context:component-scan base-package="com.somnus"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan>
4、Spring涉及到的扫描面比较广,不合适具体指定某个子包(service、dao、aspect。。。etc)
但是它又不该去扫描@Controller注解,所以应该采取如下配置
<context:component-scan base-package="com.somnus"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan>
或者
<context:component-scan base-package="com.somnus" use-default-filters="false"> <!-- 扫描符合@Component @Service @Repository的类 --> <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" /> <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" /> <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" /> </context:component-scan>
当然也有人为了简洁直接写成扫描所有的
<context:component-scan base-package="com.somnus" />
等于是把@Controller也扫描进去了,也不能说他错,虽然在父子容器中最终都有注解为@Controller的对象,但最终其实也只会先拿子容器的,父容器的等于是白定义了。
相关文章推荐
- java各种数据类型的转换问题
- Struts2的核心和工作原理
- Myeclipse生成项目toString
- Windows 安装JDK
- java ArrayList自动排序算法的实现
- Java注解二 自定义注解
- Timer 定时任务
- Java基础笔记(截止到面向对象思想)
- java学习笔记5.22多维数组以及对象和类
- java基础---->java中国际化的实现
- JDK环境变量配置
- java省市级联下拉菜单实例代码
- java异步方式实现登录
- 蚁群算法实现TSP(旅行商)问题(java)
- java中++的理解
- maven的安装配置以及在MyEclipse6.0中集成
- Struts2请求参数扩展名的配置
- 【GOF23设计模式】_原型模式JAVA233-234
- Mybatis:maven-spring实现
- Java链接sql:垃圾回收的陷阱