十二、springMVC整合spring
一、概述:
需要進行spring 整合 springmvc 嗎?或者說還是否需要加入Spring 的IOC容器? 是否需要在web.xml檔案中配置啟動啟動Spring IOC容器的ContextLoaderListener?
- 需要整合:通常情況下,類似於資料來源 事務 整合其他框架都是放在spring的配置檔案中,而不是放在Springmvc的配置檔案中 實際放入Spring配置檔案對應的IOC容器中的還有Service 和Dao;
- 不需要整合:都放在Springmvc 的配置檔案中,也可以分多個Spring的配置檔案,然後使用import節點匯入其他配置檔案;
整合spring、springMVC中的問題:
若spring的IOC 容器和springMVC的IOC容器掃描的包有重合的部分,就會導致bean會被建立兩次。即tomcat啟動時,構造器分別被建立了2次;
例項驗證:
目錄結構如下圖
配置:
web.xml只配置了DispatcherServlet+配置啟動spring ioc容器的Listener ,Listener 配置如下:
1 <context-param> 2 <param-name>contextConfigLocation</param-name> 3 <param-value>classpath:beans.xml</param-value> 4 </context-param> 5 <listener> 6 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 7 </listener>
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"View Code3 xmlns="http://xmlns.jcp.org/xml/ns/javaee" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 5 id="WebApp_ID" version="3.1"> 6 <context-param> 7 <param-name>contextConfigLocation</param-name> 8 <param-value>classpath:beans.xml</param-value> 9 </context-param> 10 <listener> 11 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 12 </listener> 13 <servlet> 14 <servlet-name>springDispatcherServlet</servlet-name> 15 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 16 <!-- 配置DispatcherServletd 一個初始化引數:配置springmvc配置檔案的位置和名稱 --> 17 <!-- 實際上也可以不通過 contextConfigLocation 來配置Springmvc的配置檔案,而是用預設的 即預設的配置檔案為 18 /WEB-INF/<servlet-name>-servlet.xml 本專案預設位置配置檔案即為: /WEB-INF/springDispatcherServlet-servlet.xml --> 19 <init-param> 20 <param-name>contextConfigLocation</param-name> 21 <param-value>classpath:spring.xml</param-value> 22 </init-param> 23 <!-- 表示springDispatcherServlet在載入的時候被建立 --> 24 <load-on-startup>1</load-on-startup> 25 </servlet> 26 27 <!-- Map all requests to the DispatcherServlet for handling --> 28 <servlet-mapping> 29 <servlet-name>springDispatcherServlet</servlet-name> 30 <url-pattern>/</url-pattern> 31 </servlet-mapping> 32 </web-app>
spring.xml基礎配置(包掃描的配置、檢視解析器配置、<mvc:annotation-driven></mvc:annotation-driven>)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:mvc="http://www.springframework.org/schema/mvc" 5 xmlns:context="http://www.springframework.org/schema/context" 6 xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 7 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 9 10 <!-- 配置需要掃描的包 --> 11 <context:component-scan base-package="springandspringmvc"> 12 </context:component-scan> 13 <!-- 配置檢視解析器 如何把handler 方法返回值解析為實際的物理檢視 --> 14 <bean 15 class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 16 <property name="prefix" value="/WEB-INF/views/"></property> 17 <property name="suffix" value=".jsp"></property> 18 </bean> 19 20 <mvc:annotation-driven></mvc:annotation-driven> 21 </beans>View Code
bean.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 6 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 7 8 <context:component-scan base-package="springandspringmvc"></context:component-scan> 9 </beans>View Code
mvc程式碼:
HelloController:
1 package springandspringmvc; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.stereotype.Controller; 5 import org.springframework.web.bind.annotation.RequestMapping; 6 7 @Controller 8 @RequestMapping("/helloworld") 9 public class HelloController { 10 @Autowired 11 private HelloService helloService; 12 13 @RequestMapping("list") 14 public String hello() { 15 helloService.hello(); 16 System.out.println("success"); 17 return "success"; 18 } 19 20 public HelloController() { 21 System.out.println("controller constructor"); 22 } 23 24 }View Code
HelloService.java
1 package springandspringmvc; 2 3 public interface HelloService { 4 5 String hello(); 6 7 }View Code
HelloServiceImpl.java
1 package springandspringmvc; 2 3 import org.springframework.stereotype.Service; 4 5 @Service("helloService") 6 public class HelloServiceImpl implements HelloService { 7 8 @Override 9 public String hello() { 10 System.out.println("hello HelloServiceImpl"); 11 return null; 12 } 13 14 public HelloServiceImpl() { 15 System.out.println("HelloServiceImpl constructor"); 16 // TODO Auto-generated constructor stub 17 } 18 19 }View Code
success.jsp:
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html> 4 <html> 5 <head> 6 <meta charset="UTF-8"> 7 <title>Insert title here</title> 8 </head> 9 <body> 10 success 11 </body> 12 </html>View Code
執行結果:
當專案啟動時,控制列印了兩遍:
controller constructor
HelloServiceImpl constructor
解決辦法:
- 解決方法1:使spring的IOC 容器和springMVC的IOC容器掃描的包有重合的部分
- 解決方法2:使用exclue-filter和include-filter 子節點來規定只能掃描的註解
採用exclue-filter和include-filter 子節點來規定只能掃描的註解;即spring.xml 掃描包該為只掃描Controller和service;bean.xml除了Controller和service不掃描,其他都掃描;
spring.xml:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:mvc="http://www.springframework.org/schema/mvc" 5 xmlns:context="http://www.springframework.org/schema/context" 6 xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 7 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 9 10 <!-- 配置需要掃描的包 --> 11 <context:component-scan base-package="restful" 12 use-default-filters="false"> 13 <context:include-filter type="annotation" 14 expression="org.springframework.stereotype.Controller" /> 15 <context:include-filter type="annotation" 16 expression="org.springframework.stereotype.Service" /> 17 </context:component-scan> 18 <!-- 配置檢視解析器 如何把handler 方法返回值解析為實際的物理檢視 --> 19 <bean 20 class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 21 <property name="prefix" value="/WEB-INF/views/"></property> 22 <property name="suffix" value=".jsp"></property> 23 </bean> 24 25 <mvc:annotation-driven></mvc:annotation-driven> 26 </beans>View Code
bean.xml:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 6 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 7 8 <context:component-scan 9 base-package="restful.restful.springandspringmvc" 10 use-default-filters="false"> 11 <context:exclude-filter type="annotation" 12 expression="org.springframework.stereotype.Controller" /> 13 <context:exclude-filter type="annotation" 14 expression="org.springframework.stereotype.Service" /> 15 </context:component-scan> 16 </beans>View Code
此時:springMVC的IOC容器掃描的包就沒有重合的部分。且springmvc 的IOC容器中的bean可以引用spring ioc中的bean,而反過來不行,也就是說service不能通過@Autowired來獲取Controller;
即:spring ioc容器中的bean不能引用springMVC IOC容器中的bean。即完成了整合;若配置IOC,資料來源,就可以配置到bean.xml中了;
參考:
context:component-scan的一些說明的參考連結:https://www.cnblogs.com/lixiuming521125/p/15401339.html#_label3_1