第一節:Spring 與 SpringMVC 整合


一、Spring 與 SpringMVC 是否需要整合?

  1、需要進行 Spring 整合 SpringMVC 嗎?
  2、還是否需要再加入 Spring 的 IOC 容器?
  3、是否需要再 web.xml 文件中配置啟動的 Spring IOC 容器的 ContextLoaderListener?

  不需要整合:

    都放在 SpringMVC 的配置文件中,也可以分多個 Spring 的配置文件,然后使用 import 節點導入其他的配置文件

    示例:在 springmvc.xml 中導入 spring.xml 文件

    <import resource="spring.xml"/>

     不整合造成的問題:需要將 spring 管理的內容都交給 springMVC 管理,這樣會造成業務邏輯混亂

  需要整合:

    通常情況下,類似於數據源、事務,整合其他框架都是放在 Spring 的配置文件中(而不是放在 SpringMVC 的配置文件中),實際上放入 Spring 配置文件對應的 IOC 容器中的還有 Service 和 Dao。

    整合的目的:分工明確

      SpringMVC的配置文件就來配置網站轉發邏輯以及網站功能有關的(視圖解析器、文件上傳解析器、支持ajax)

      Spring的配置文件來配置和業務有關的(事務控制,數據源,xxx)

    

    整合:Spring 的配置文件在什么時候加載?怎么加載?

    注意:Spring 的配置文件必須在項目啟動時加載,且要在 Servlet 加載前加載。

    解決方法:使用監聽器(首先執行),可以在ServletContext 加載時,通過監聽器加載 Spring 的配置文件,創建 Spring 容器,也可以使用 Spring 提供的監聽器。

 

二、准備工作

  1、創建一個動態 Web 工程

  2、導入 jar 包依賴

   <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-version>4.1.0.RELEASE</spring-version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${spring-version}</version>
        </dependency>

        <!-- AOP -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring-version}</version>
        </dependency>

        <!-- Web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring-version}</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>


        <dependency>
            <groupId>org.apache.taglibs</groupId>
            <artifactId>taglibs-standard-impl</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.taglibs</groupId>
            <artifactId>taglibs-standard-spec</artifactId>
            <version>1.2.1</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.4.Final</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>


    </dependencies>

 

  3、創建 Spring 的配置文件 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.xsd">


    <!--掃描組件,排除 controller 和 ControllerAdvice-->
    <context:component-scan base-package="com.njf" use-default-filters="true">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
    </context:component-scan>

<!-- 配置數據源,整合其他框架,事務等等 -->
</beans>

 

 

  4、配置 springMVC的配置文件 springmvc.xml(只掃描控制器和異常處理,和web相關的組件)

<?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" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd 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">
    <!-- 掃描組件,將加上@Controller注解的類作為springMVC的控制層和異常控制器 -->
    <context:component-scan base-package="com.njf" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
    </context:component-scan>
     
     <!-- 配置一個視圖解析器 :能幫我們拼接頁面地址-->
     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
         <property name="prefix" value="/WEB-INF/view/"></property>
         <property name="suffix" value=".jsp"></property>
     </bean>
     
     <!-- 處理靜態資源,交給 Tomcat 處理 -->
     <mvc:default-servlet-handler/>
     
     <!-- 開啟 SpringMVC 的高級功能 -->
     <mvc:annotation-driven />
     
     <!-- 處理文件,將客戶端上傳的File文件,處理為MultipartFile 注意:文件解析器的bean中id必須設置為multipartResolver -->
     <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
         <!-- 設置文件解析的編碼,注意:一定要和頁面的pageEncoding保持一致 -->
         <property name="defaultEncoding" value="UTF-8"></property>
         <!-- 設置最大上傳文件大小 -->
         <property name="maxUploadSize" value="88888888"></property>
     </bean>
     
     <!-- 配置異常處理器 -->
     <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
         <property name="exceptionMappings">
              <props>
                  <prop key="java.lang.NullPointerException">error</prop>
              </props>
         </property>
     </bean>

     <!-- <mvc:interceptors> 默認攔截所有請求 <bean class="com.spring.interceptor.FirstInterceptor"></bean> <bean class="com.spring.interceptor.SecondInterceptor"></bean> 此方式要求攔截器類上必須加注解@Component <ref bean="firstInterceptor"/> 設置自定義攔截方式 <mvc:interceptor> <bean></bean> <mvc:mapping path=""/> <mvc:exclude-mapping path=""/> </mvc:interceptor> </mvc:interceptors> -->
</beans>

 

 

  5、存在的問題

    若 Spring 的 IOC 容器和 SpringMVC 的 IOC 容器掃描的包有重合的部分,就會導致有的 bean 會被創建兩次。
    如果某個包下面的 bean 會被掃描多次,就會出現多個 bean 的問題。

 

  6、解決方案

    使用 Spring 的 IOC 容器掃描的包和 SpringMVC 的 IOC 容器掃描的包沒有重合的部分,可以使用 exclude-filter 和 include-filter 子節點來規定只能掃描的注解:

    由於 SpringMVC 是對 Servlet 的封裝,我們可以只用來掃描控制層;

    spring 的配置文件掃描除了控制層之外的 bean,還可以用於配置數據源,整合其他框架,事務等;

    具體配置如上。

三、自定義監聽器整合Spring與SpringMVC

  1、自定義監聽器

public class SpringListener implements ServletContextListener { public SpringListener() { } @Override public void contextInitialized(ServletContextEvent sce) { //獲取 application 對象
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); ServletContext servletContext = sce.getServletContext(); // 把spring IOC 容器放到 application 域中
        servletContext.setAttribute("ac", ac); } @Override public void contextDestroyed(ServletContextEvent sce) { } }

 

  2、web.xml 中的配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
    </welcome-file-list>

    <!-- 配置自定義的監聽器 -->
 <listener> <listener-class>com.njf.listener.SpringListener</listener-class> </listener>

    <!-- 前端控制器(核心控制器) -->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置DispatcherServlet的初始化參數:設置文件的路徑和文件名稱 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!-- servlet 啟動加載,servlet 原本是第一次訪問創建對象 load-on-startup:服務器啟動的時候就創建對象,值越小優先級越高,越先創建對象 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- /* 和 / 都是攔截所有請求,/:會攔截所有請求,但是不會攔截 *.jsp,能保證 jsp訪問正常; /* 的范圍更大,還會攔截 *.jsp 這些請求,一旦攔截 jsp 頁面就不能顯示了 -->
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>     <!-- / 這樣寫,只有請求才處理,頁面會過濾掉 -->
    </servlet-mapping>


    <!-- 字符編碼過濾器 -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 設置字符編碼 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!-- 強制設置響應進行編碼 -->
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>  <!-- 對所有的請求都攔截,處理所有響應-->
    </filter-mapping>

    <!-- REST 風格過濾器-->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

 

  3、控制器方法

    @RequestMapping(value = "/hello2") public String hello2(HttpSession session) { //獲取spring IOC 所管理的 bean 組件
        ServletContext servletContext = session.getServletContext(); ApplicationContext ac = (ApplicationContext)servletContext.getAttribute("ac"); System.out.println(ac); BookService bookService = ac.getBean("bookService", BookService.class); System.out.println("bookService = " + bookService); return "success"; }

    可以在控制器方法中通過 ServletContext 對象來獲取 application 對象,從而進行操作。

 

 

四、使用Spring監聽器進行整合

  1、使用 Spring 監聽器

    在 web.xml 中進配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
    </welcome-file-list>

     <!-- 配置啟動 Spring IOC容器的 Listener-->
 <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>

    <!-- 前端控制器(核心控制器) -->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置DispatcherServlet的初始化參數:設置文件的路徑和文件名稱 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!-- servlet 啟動加載,servlet 原本是第一次訪問創建對象 load-on-startup:服務器啟動的時候就創建對象,值越小優先級越高,越先創建對象 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- /* 和 / 都是攔截所有請求,/:會攔截所有請求,但是不會攔截 *.jsp,能保證 jsp訪問正常; /* 的范圍更大,還會攔截 *.jsp 這些請求,一旦攔截 jsp 頁面就不能顯示了 -->
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>     <!-- / 這樣寫,只有請求才處理,頁面會過濾掉 -->
    </servlet-mapping>


    <!-- 字符編碼過濾器 -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 設置字符編碼 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!-- 強制設置響應進行編碼 -->
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>  <!-- 對所有的請求都攔截,處理所有響應-->
    </filter-mapping>

    <!-- REST 風格過濾器-->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

 

    但是這是會在控制台報錯:

java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext

    這是因為沒有找到 spring 的配置文件(可能是文件名錯誤或路徑錯誤)

    還需要在 web.xml中 配置 <context-param> 標簽,指定 spring.xml 的位置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
    </welcome-file-list>

    <!-- 配置 spring 容器,指定 spring 的配置文件 spring.xml-->
 <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </context-param>

     <!-- 配置啟動 Spring IOC容器的 Listener-->
     <listener>
         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
     </listener>

    <!-- 前端控制器(核心控制器) -->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置DispatcherServlet的初始化參數:設置文件的路徑和文件名稱 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!-- servlet 啟動加載,servlet 原本是第一次訪問創建對象 load-on-startup:服務器啟動的時候就創建對象,值越小優先級越高,越先創建對象 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- /* 和 / 都是攔截所有請求,/:會攔截所有請求,但是不會攔截 *.jsp,能保證 jsp訪問正常; /* 的范圍更大,還會攔截 *.jsp 這些請求,一旦攔截 jsp 頁面就不能顯示了 -->
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>     <!-- / 這樣寫,只有請求才處理,頁面會過濾掉 -->
    </servlet-mapping>


    <!-- 字符編碼過濾器 -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 設置字符編碼 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!-- 強制設置響應進行編碼 -->
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>  <!-- 對所有的請求都攔截,處理所有響應-->
    </filter-mapping>

    <!-- REST 風格過濾器-->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

 

    如果沒有配置此標簽,監聽器默認會去 web-content 下找 application.xml的配置文件,找不到,就會報上面的錯誤,如果使用了該標簽,就可以指定配置文件的路徑和名稱了。

 

    擴展:web.xml中的執行順序
    1、首先加載的是 <context-parm> ,里面存放的當前 web 應用的參數和配置
    2、運行監聽器
    3、運行過濾器
    4、運行 Servlet

  

  2、ContextLoaderListener 部分源碼

public class ContextLoaderListener extends  ContextLoader implements ServletContextListener { public ContextLoaderListener() { } public ContextLoaderListener(WebApplicationContext context) { super(context); } @Override public void contextInitialized(ServletContextEvent event) { initWebApplicationContext(event.getServletContext()); } @Override public void contextDestroyed(ServletContextEvent event) { closeWebApplicationContext(event.getServletContext()); ContextCleanupListener.cleanupAttributes(event.getServletContext()); } } initWebApplicationContext 方法源碼: public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { throw new IllegalStateException( "Cannot initialize context because there is already a root application context present - " +
                    "check whether you have multiple ContextLoader* definitions in your web.xml!"); } Log logger = LogFactory.getLog(ContextLoader.class); servletContext.log("Initializing Spring root WebApplicationContext"); if (logger.isInfoEnabled()) { logger.info("Root WebApplicationContext: initialization started"); } long startTime = System.currentTimeMillis(); try { // Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown.
            if (this.context == null) { this.context = createWebApplicationContext(servletContext); } if (this.context instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc
                    if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> // determine parent for root web application context, if any.
                        ApplicationContext parent = loadParentContext(servletContext); cwac.setParent(parent); } configureAndRefreshWebApplicationContext(cwac, servletContext); } } servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); ClassLoader ccl = Thread.currentThread().getContextClassLoader(); if (ccl == ContextLoader.class.getClassLoader()) { currentContext = this.context; } else if (ccl != null) { currentContextPerThread.put(ccl, this.context); } if (logger.isDebugEnabled()) { logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"); } if (logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms"); } return this.context; } catch (RuntimeException ex) { logger.error("Context initialization failed", ex); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex); throw ex; } catch (Error err) { logger.error("Context initialization failed", err); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err); throw err; } }

 

 

五、父子容器

  Spring Ioc 容器 與 SpringMVC Ioc 容器的關系
  SpringMVC 的 Ioc 容器中的 bean 可以來應用 Spring Ioc 容器中的 bean, 返回來卻不行!Spring Ioc 容器中的 bean 卻不能引用 SpringMVC Ioc 容器中的 bean。
  spring 是父容器,springMVC 是子容器
 
  規定:子容器能夠調用訪問父容器中的 bean,而父容器不能夠調用訪問子容器中的 bean
 
  1、在 SpringMVC 配置文件中引用業務層的 Bean;
  2、多個 Spring IOC容器之間設置為父子關系,以實現良好的解耦;
  3、SpringMVC WEB 層容器可作為 “業務層”,Spring 容器的子容器:即 WEB 層容器可以引用業務層容器的 Bean,而業務層容器卻訪問不到 WEB 層容器的 Bean;
  

 

  Spring 管理業務邏輯組件
  SpringMVC 管理控制器組件

 

六、SpringMVC 對比 Struts2

    1、SpringMVC 的入口是 Servlet,而 Struts2 是Filter;
    2、SpringMVC 會稍微比 Struts2 快些,SpringMVC 是基於方法設計,而 Struts2 是基於類,每次發送一次請求都會實例一個 Action;
    3、SpringMVC 使用更加簡潔,開發效率 SpringMVC確實比 struts2 高,支持 JSR303,處理 AJAX 的請求更方便;
    4、 Struts2 的 OGNL 表達式使頁面的開發效率相比 Spring MVC 更高些;
 
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM