posts - 495,comments - 227,trackbacks - 0

          資源下載:

          Spring_MVC_教程_快速入門_深入分析V1.1.pdf

          SpringMVC核心配置文件示例.rar

           

           

          作者:趙磊

          博客:http://elf8848.iteye.com

           

          目錄

          一、前言
          二、spring mvc 核心類與接口
          三、spring mvc 核心流程圖

          四、spring mvc DispatcherServlet說明

          五、spring mvc 父子上下文的說明

          六、springMVC-mvc.xml 配置文件片段講解
          七、spring mvc 如何訪問到靜態(tài)的文件,如jpg,js,css

          八、spring mvc 請(qǐng)求如何映射到具體的Action中的方法

          九、 spring mvc 中的攔截器:
          十、
          spring mvc 如何使用攔截器

          十一、 spring mvc 如何實(shí)現(xiàn)全局的異常處理

          十二、 spring mvc 如何把全局異常記錄到日志中

          十三、 如何給spring3 MVC中的Action做JUnit單元測(cè)試

          十四、 spring mvc 轉(zhuǎn)發(fā)與重定向 (帶參數(shù)重定向)

          十五、 spring mvc 處理ajax請(qǐng)求

          十六、 spring mvc 關(guān)于寫幾個(gè)配置文件的說明 

          十七、 spring mvc 如何取得Spring管理的bean

          十八、 spring mvc 多視圖控制器

          十九、 <mvc:annotation-driven /> 到底做了什么工作
          二十、 本文中springMVC.xml配置文件是核心,這里給一個(gè)下載地址

           

           

           

          說明:本作者是文章的原創(chuàng)作者,轉(zhuǎn)載請(qǐng)注明出處:本文地址:http://elf8848.iteye.com/blog/875830

           

           

           

          一、前言:

          為開發(fā)團(tuán)隊(duì)選擇一款優(yōu)秀的MVC框架是件難事兒,在眾多可行的方案中決擇需要很高的經(jīng)驗(yàn)和水平。你的一個(gè)決定會(huì)影響團(tuán)隊(duì)未來的幾年。要考慮方面太多:

          1、簡(jiǎn)單易用,以提高開發(fā)效率。使小部分的精力在框架上,大部分的精力放在業(yè)務(wù)上。

          2、性能優(yōu)秀,這是一個(gè)最能吸引眼球的話題。

          3、盡量使用大眾的框架(避免使用小眾的、私有的框架),新招聘來的開發(fā)人員有一些這方面技術(shù)積累,減低人員流動(dòng)再適應(yīng)的影響。

           

          如果你還在為這件事件發(fā)愁,本文最適合你了。選擇Spring MVC吧。

           

          Spring MVC是當(dāng)前最優(yōu)秀的MVC框架,自從Spring 2.5版本發(fā)布后,由于支持注解配置,易用性有了大幅度的提高。Spring 3.0更加完善,實(shí)現(xiàn)了對(duì)Struts 2的超越。現(xiàn)在越來越多的開發(fā)團(tuán)隊(duì)選擇了Spring MVC。

           

          Struts2也是非常優(yōu)秀的MVC構(gòu)架,優(yōu)點(diǎn)非常多比如良好的結(jié)構(gòu),攔截器的思想,豐富的功能。但這里想說的是缺點(diǎn),Struts2由于采用了值 棧、OGNL表達(dá)式、struts2標(biāo)簽庫等,會(huì)導(dǎo)致應(yīng)用的性能下降,應(yīng)避免使用這些功能。而Struts2的多層攔截器、多實(shí)例action性能都很 好。可以參考我寫的一篇關(guān)于Spring MVC與Struts2與Servlet比較的文章《Struts2、SpringMVC、Servlet(Jsp)性能對(duì)比 測(cè)試》

           

          Spring3 MVC的優(yōu)點(diǎn):

          1、Spring3 MVC使用簡(jiǎn)單,學(xué)習(xí)成本低。學(xué)習(xí)難度小于Struts2,Struts2用不上的多余功能太多。呵呵,當(dāng)然這不是決定因素。

          2、Spring3 MVC很容易就可以寫出性能優(yōu)秀的程序,Struts2要處處小心才可以寫出性能優(yōu)秀的程序(指MVC部分)

          3、Spring3 MVC的靈活是你無法想像的,Spring框架的擴(kuò)展性有口皆碑,Spring3 MVC當(dāng)然也不會(huì)落后,不會(huì)因使用了MVC框架而感到有任何的限制。

           

          Struts2的眾多優(yōu)點(diǎn):

          1、老牌的知名框架,從Struts1起積累了大量用戶群體。技術(shù)文檔豐富。

          2、其它方面略...   (呵呵,是不是不公平?)

           

          Spring的官方下載網(wǎng)址是:http://www.springsource.org/download    (本文使用是的Spring 3.0.5版本)

          轉(zhuǎn)載請(qǐng)注明出處:原文地址:http://elf8848.iteye.com/blog/875830

           

          二、核心類與接口:

           

          先來了解一下,幾個(gè)重要的接口與類。現(xiàn)在不知道他們是干什么的沒關(guān)系,先混個(gè)臉熟,為以后認(rèn)識(shí)他們打個(gè)基礎(chǔ)。

           

          DispatcherServlet   -- 前置控制器

           

          HandlerMapping接口 -- 處理請(qǐng)求的映射

          HandlerMapping接口的實(shí)現(xiàn)類:

          SimpleUrlHandlerMapping  通過配置文件,把一個(gè)URL映射到Controller

          DefaultAnnotationHandlerMapping  通過注解,把一個(gè)URL映射到Controller類上

           

          HandlerAdapter接口 -- 處理請(qǐng)求的映射

          AnnotationMethodHandlerAdapter類,通過注解,把一個(gè)URL映射到Controller類的方法上

           

          Controller接口 -- 控制器

          由于我們使用了@Controller注解,添加了@Controller注解注解的類就可以擔(dān)任控制器(Action)的職責(zé),

          所以我們并沒有用到這個(gè)接口。

           

           

           

          HandlerInterceptor 接口--攔截器

          無圖,我們自己實(shí)現(xiàn)這個(gè)接口,來完成攔截的器的工作。

           

           

          ViewResolver接口的實(shí)現(xiàn)類

          UrlBasedViewResolver類 通過配置文件,把一個(gè)視圖名交給到一個(gè)View來處理

          InternalResourceViewResolver類,比上面的類,加入了JSTL的支持

           

          View接口

          JstlView類

           

          LocalResolver接口

           

          HandlerExceptionResolver接口 --異常處理

          SimpleMappingExceptionResolver實(shí)現(xiàn)類

           

           

          ModelAndView類

          無圖。

           

           

           

           

           

          三、核心流程圖

           

          本圖是我個(gè)人畫的,有不嚴(yán)謹(jǐn)?shù)牡胤剑蠹覍?duì)付看吧。總比沒的看強(qiáng)。

          轉(zhuǎn)載請(qǐng)注明出處:本文地址:http://elf8848.iteye.com/blog/875830

           

           


          四、DispatcherServlet說明

           

          使用Spring MVC,配置DispatcherServlet是第一步。

          DispatcherServlet是一個(gè)Servlet,所以可以配置多個(gè)DispatcherServlet。

          DispatcherServlet是前置控制器,配置在web.xml文件中的。攔截匹配的請(qǐng)求,Servlet攔截匹配規(guī)則要自已定義,把攔截下來的請(qǐng)求,依據(jù)某某規(guī)則分發(fā)到目標(biāo)Controller(我們寫的Action)來處理。

           

          “某某規(guī)則”:是根據(jù)你使用了哪個(gè)HandlerMapping接口的實(shí)現(xiàn)類的不同而不同。

           

          先來看第一個(gè)例子:

          Xml代碼  收藏代碼
          1. <web-app>  
          2.     <servlet>  
          3.         <servlet-name>example</servlet-name>  
          4.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
          5.         <load-on-startup>1</load-on-startup>  
          6.     </servlet>  
          7.     <servlet-mapping>  
          8.         <servlet-name>example</servlet-name>  
          9.         <url-pattern>*.form</url-pattern>  
          10.     </servlet-mapping>  
          11. </web-app>  

           <load-on-startup>1</load-on-startup>是啟動(dòng)順序,讓這個(gè)Servlet隨Servletp容器一起啟動(dòng)。

           <url-pattern>*.form</url-pattern> 會(huì)攔截*.form結(jié)尾的請(qǐng)求。

           

           <servlet-name>example</servlet-name>這個(gè)Servlet的名字是 example,可以有多個(gè)DispatcherServlet,是通過名字來區(qū)分的。每一個(gè)DispatcherServlet有自己的 WebApplicationContext上下文對(duì)象。同時(shí)保存的ServletContext中和Request對(duì)象中,關(guān)于key,以后說明。

           

          在DispatcherServlet的初始化過程中,框架會(huì)在web應(yīng)用的 WEB-INF文件夾下尋找名為[servlet-name]-servlet.xml 的配置文件,生成文件中定義的bean。

           

           

          第二個(gè)例子:

          Xml代碼  收藏代碼
          1. <servlet>  
          2.     <servlet-name>springMVC</servlet-name>  
          3.     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
          4.     <init-param>  
          5.         <param-name>contextConfigLocation</param-name>  
          6.         <param-value>classpath*:/springMVC.xml</param-value>  
          7.     </init-param>  
          8.     <load-on-startup>1</load-on-startup>  
          9. </servlet>  
          10. <servlet-mapping>  
          11.     <servlet-name>springMVC</servlet-name>  
          12.     <url-pattern>/</url-pattern>  
          13. </servlet-mapping>  

          指明了配置文件的文件名,不使用默認(rèn)配置文件名,而使用springMVC.xml配置文件。

          其中<param-value>**.xml</param-value> 這里可以使用多種寫法
          1、不寫,使用默認(rèn)值:/WEB-INF/<servlet-name>-servlet.xml
          2、<param-value>/WEB-INF/classes/springMVC.xml</param-value>
          3、<param-value>classpath*:springMVC-mvc.xml</param-value>
          4、多個(gè)值用逗號(hào)分隔

           


          Servlet攔截匹配規(guī)則可以自已定義,攔截哪種URL合適?
          當(dāng)映射為@RequestMapping("/user/add")時(shí),為例:


          1、攔截*.do、*.htm, 例如:/user/add.do

          這是最傳統(tǒng)的方式,最簡(jiǎn)單也最實(shí)用。不會(huì)導(dǎo)致靜態(tài)文件(jpg,js,css)被攔截。

           

          2、攔截/,例如:/user/add

          可以實(shí)現(xiàn)現(xiàn)在很流行的REST風(fēng)格。很多互聯(lián)網(wǎng)類型的應(yīng)用很喜歡這種風(fēng)格的URL。

          弊端:會(huì)導(dǎo)致靜態(tài)文件(jpg,js,css)被攔截后不能正常顯示。想實(shí)現(xiàn)REST風(fēng)格,事情就是麻煩一些。后面有解決辦法還算簡(jiǎn)單。

           

          3、攔截/*,這是一個(gè)錯(cuò)誤的方式,請(qǐng)求可以走到Action中,但轉(zhuǎn)到j(luò)sp時(shí)再次被攔截,不能訪問到j(luò)sp。

           

          轉(zhuǎn)載請(qǐng)注明出處:本文地址:http://elf8848.iteye.com/blog/875830

           

          五、父子上下文(WebApplicationContext)

           

          如果你使用了listener監(jiān)聽器來加載配置,一般在Struts+Spring+Hibernate的項(xiàng)目中都是使用listener監(jiān)聽器的。如下

          Java代碼  收藏代碼
          1. <listener>   
          2.   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>   
          3. </listener>   

           

           

          Spring會(huì)創(chuàng)建一個(gè)WebApplicationContext上下文,稱為父上下文(父容器) ,保存在 ServletContext中,key是 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。

          可以使用Spring提供的工具類取出上下文對(duì)象:WebApplicationContextUtils.getWebApplicationContext(ServletContext);

           

          DispatcherServlet是一個(gè)Servlet,可以同時(shí)配置多個(gè),每個(gè) DispatcherServlet有一個(gè)自己的上下文對(duì)象(WebApplicationContext),稱為子上下文(子容器),子上下文可以訪問 父上下文中的內(nèi)容,但父上下文不能訪問子上下文中的內(nèi)容。 它也保存在 ServletContext中,key 是"org.springframework.web.servlet.FrameworkServlet.CONTEXT"+Servlet名稱。當(dāng)一 個(gè)Request對(duì)象產(chǎn)生時(shí),會(huì)把這個(gè)子上下文對(duì)象(WebApplicationContext)保存在Request對(duì)象中,key是 DispatcherServlet.class.getName() + ".CONTEXT"。

          可以使用工具類取出上下文對(duì)象:RequestContextUtils.getWebApplicationContext(request);

           

           

          說明 :Spring 并沒有限制我們,必須使用父子上下文。我們可以自己決定如何使用。

           

          方案一,傳統(tǒng)型:

          父上下文容器中保存數(shù)據(jù)源、服務(wù)層、DAO層、事務(wù)的Bean。

          子上下文容器中保存Mvc相關(guān)的Action的Bean.

          事務(wù)控制在服務(wù)層。

          由于父上下文容器不能訪問子上下文容器中內(nèi)容,事務(wù)的Bean在父上下文容器中,無法訪問子上下文容器中內(nèi)容,就無法對(duì)子上下文容器中Action進(jìn)行AOP(事務(wù))。

          當(dāng)然,做為“傳統(tǒng)型”方案,也沒有必要這要做。

           

          方案二,激進(jìn)型:

          Java世界的“面向接口編程”的思想是正確的,但在增刪改查為主業(yè)務(wù)的系統(tǒng)里,Dao層接口,Dao層實(shí)現(xiàn)類,Service層接 口,Service層實(shí)現(xiàn)類,Action父類,Action。再加上眾多的O(vo\po\bo)和jsp頁面。寫一個(gè)小功能 7、8個(gè)類就寫出來了。 開發(fā)者說我就是想接點(diǎn)私活兒,和PHP,ASP搶搶飯碗,但我又是Java程序員。最好的結(jié)果是大項(xiàng)目能做好,小項(xiàng)目能做快。所以“激進(jìn)型”方案就出現(xiàn)了 -----沒有接口、沒有Service層、還可以沒有眾多的O(vo\po\bo)。那沒有Service層事務(wù)控制在哪一層?只好上升的Action 層。

          本文不想說這是不是正確的思想,我想說的是Spring不會(huì)限制你這樣做。

          由于有了父子上下文,你將無法實(shí)現(xiàn)這一目標(biāo)。解決方案是只使用子上下文容器,不要父上下文容器 。所以數(shù)據(jù)源、服務(wù)層、DAO層、事務(wù)的Bean、Action的Bean都放在子上下文容器中。就可以實(shí)現(xiàn)了,事務(wù)(注解事務(wù))就正常工作了。這樣才夠激進(jìn)。

          總結(jié):不使用listener監(jiān)聽器來加載spring的配置文件,只使用DispatcherServlet來加載spring的配置,不要父子上下文,只使用一個(gè)DispatcherServlet,事情就簡(jiǎn)單了,什么麻煩事兒也沒有了。

           

           

           

          Java--大項(xiàng)目能做好--按傳統(tǒng)方式做,規(guī)規(guī)矩矩的做,好擴(kuò)展,好維護(hù)。

          Java--小項(xiàng)目能做快--按激進(jìn)方式做,一周時(shí)間就可以出一個(gè)版本,先上線接受市場(chǎng)(用戶)的反饋,再改進(jìn),再反饋,時(shí)間就是生命(成本)。

           

          轉(zhuǎn)載請(qǐng)注明出處:原文地址:http://elf8848.iteye.com/blog/875830

           

          六、springMVC-mvc.xml 配置文件片段講解 (未使用默認(rèn)配置文件名)

           

          Xml代碼  收藏代碼
          1. <?xml version="1.0" encoding="UTF-8"?>  
          2. <beans  
          3.     xmlns="http://www.springframework.org/schema/beans"  
          4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
          5.     xmlns:tx="http://www.springframework.org/schema/tx"  
          6.     xmlns:context="http://www.springframework.org/schema/context"    
          7.     xmlns:mvc="http://www.springframework.org/schema/mvc"    
          8.     xsi:schemaLocation="http://www.springframework.org/schema/beans   
          9.     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
          10.     http://www.springframework.org/schema/tx   
          11.     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
          12.     http://www.springframework.org/schema/context  
          13.     http://www.springframework.org/schema/context/spring-context-3.0.xsd  
          14.     http://www.springframework.org/schema/mvc  
          15.     http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
          16.   
          17.   
          18.     <!-- 自動(dòng)掃描的包名 -->  
          19.     <context:component-scan base-package="com.app,com.core,JUnit4" ></context:component-scan>  
          20.       
          21.     <!-- 默認(rèn)的注解映射的支持 -->  
          22.     <mvc:annotation-driven />  
          23.       
          24.     <!-- 視圖解釋類 -->  
          25.     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
          26.         <property name="prefix" value="/WEB-INF/jsp/"/>  
          27.         <property name="suffix" value=".jsp"/><!--可為空,方便實(shí)現(xiàn)自已的依據(jù)擴(kuò)展名來選擇視圖解釋類的邏輯  -->  
          28.         <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />  
          29.     </bean>  
          30.       
          31.     <!-- 攔截器 -->  
          32.     <mvc:interceptors>  
          33.         <bean class="com.core.mvc.MyInteceptor" />  
          34.     </mvc:interceptors>       
          35.       
          36.     <!-- 對(duì)靜態(tài)資源文件的訪問  方案一 (二選一) -->  
          37.     <mvc:default-servlet-handler/>  
          38.       
          39.     <!-- 對(duì)靜態(tài)資源文件的訪問  方案二 (二選一)-->  
          40.     <mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/>  
          41.     <mvc:resources mapping="/js/**" location="/js/" cache-period="31556926"/>  
          42.     <mvc:resources mapping="/css/**" location="/css/" cache-period="31556926"/>  
          43.   
          44. </beans>   

           

          <context:component-scan/> 掃描指定的包中的類上的注解,常用的注解有:

          @Controller 聲明Action組件
          @Service    聲明Service組件    @Service("myMovieLister")
          @Repository 聲明Dao組件
          @Component   泛指組件, 當(dāng)不好歸類時(shí).
          @RequestMapping("/menu")  請(qǐng)求映射
          @Resource  用于注入,( j2ee提供的 ) 默認(rèn)按名稱裝配,@Resource(name="beanName")
          @Autowired 用于注入,(srping提供的) 默認(rèn)按類型裝配
          @Transactional( rollbackFor={Exception.class}) 事務(wù)管理
          @ResponseBody
          @Scope("prototype")   設(shè)定bean的作用域

           

          <mvc:annotation-driven /> 是一種簡(jiǎn)寫形式,完全可以手動(dòng)配置替代這種簡(jiǎn)寫形式,簡(jiǎn)寫形式可以讓初學(xué)都快速應(yīng)用默認(rèn)配置方案。<mvc:annotation-driven /> 會(huì)自動(dòng)注冊(cè)DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter 兩個(gè)bean,是spring MVC為@Controllers分發(fā)請(qǐng)求所必須的。
          并提供了:數(shù)據(jù)綁定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,讀寫XML的支持(JAXB),讀寫JSON的支持(Jackson)。
          后面,我們處理響應(yīng)ajax請(qǐng)求時(shí),就使用到了對(duì)json的支持。
          后面,對(duì)action寫JUnit單元測(cè)試時(shí),要從spring IOC容器中取DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter 兩個(gè)bean,來完成測(cè)試,取的時(shí)候要知道是<mvc:annotation-driven />這一句注冊(cè)的這兩個(gè)bean。

          如何替換 <mvc:annotation-driven />?他到底做了什么工作,請(qǐng)看,最后面的 十九節(jié) <mvc:annotation-driven /> 到底做了什么工作。

           

          <mvc:interceptors/> 是一種簡(jiǎn)寫形式。通過看前面的大圖,知道,我們可以配置多個(gè)HandlerMapping。<mvc:interceptors/>會(huì)為每一 個(gè)HandlerMapping,注入一個(gè)攔截器。其實(shí)我們也可以手動(dòng)配置為每個(gè)HandlerMapping注入一個(gè)攔截器。

           

          <mvc:default-servlet-handler/> 使用默認(rèn)的Servlet來響應(yīng)靜態(tài)文件。

           

          <mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/> 匹配URL  /images/**  的URL被當(dāng)做靜態(tài)資源,由Spring讀出到內(nèi)存中再響應(yīng)http。

          轉(zhuǎn)載請(qǐng)注明出處:本文地址:http://elf8848.iteye.com/blog/875830

           
          七、如何訪問到靜態(tài)的文件,如jpg,js,css?

           

           

          如何你的DispatcherServlet攔截"*.do"這樣的有后綴的URL,就不存在訪問不到靜態(tài)資源的問題。

          如果你的DispatcherServlet攔截"/",為了實(shí)現(xiàn)REST風(fēng)格,攔截了所有的請(qǐng)求,那么同時(shí)對(duì)*.js,*.jpg等靜態(tài)文件的訪問也就被攔截了。

          我們要解決這個(gè)問題。

           

          目的:可以正常訪問靜態(tài)文件,不可以找不到靜態(tài)文件報(bào)404。

           
          方案一:激活Tomcat的defaultServlet來處理靜態(tài)文件

          Xml代碼  收藏代碼
          1. <servlet-mapping>   
          2.     <servlet-name>default</servlet-name>  
          3.     <url-pattern>*.jpg</url-pattern>     
          4. </servlet-mapping>    
          5. <servlet-mapping>       
          6.     <servlet-name>default</servlet-name>    
          7.     <url-pattern>*.js</url-pattern>    
          8. </servlet-mapping>    
          9. <servlet-mapping>        
          10.     <servlet-name>default</servlet-name>       
          11.     <url-pattern>*.css</url-pattern>      
          12. </servlet-mapping>    
          13. 要配置多個(gè),每種文件配置一個(gè)   

          要寫在DispatcherServlet的前面, 讓 defaultServlet先攔截請(qǐng)求,這樣請(qǐng)求就不會(huì)進(jìn)入Spring了,我想性能是最好的吧。


          Tomcat, Jetty, JBoss, and GlassFish 自帶的默認(rèn)Servlet的名字 -- "default"
          Google App Engine
          自帶的 默認(rèn)Servlet的名字 -- "_ah_default"
          Resin
          自帶的 默認(rèn)Servlet的名字 -- "resin-file"
          WebLogic
          自帶的 默認(rèn)Servlet的名字  -- "FileServlet"
          WebSphere 
          自帶的 默認(rèn)Servlet的名字 -- "SimpleFileServlet" 

           

           


          方案二: 在spring3.0.4以后版本提供了mvc:resources ,  使用方法:

          Xml代碼  收藏代碼
          1. <!-- 對(duì)靜態(tài)資源文件的訪問 -->    
          2. <mvc:resources mapping="/images/**" location="/images/" />  

            
          /images/**映射到 ResourceHttpRequestHandler進(jìn)行處理,location指定靜態(tài)資源的位置.可以是web application根目錄下、jar包里面,這樣可以把靜態(tài)資源壓縮到j(luò)ar包中。cache-period 可以使得靜態(tài)資源進(jìn)行web cache 
           
          如果出現(xiàn)下面的錯(cuò)誤,可能是沒有配置<mvc:annotation-driven />的原因。
          報(bào)錯(cuò)WARNING: No mapping found for HTTP request with URI [/mvc/user/findUser/lisi/770] in DispatcherServlet with name 'springMVC'

           

          使用<mvc:resources/>元素,把mapping的URI注冊(cè)到SimpleUrlHandlerMapping的urlMap中,
          key為mapping的URI pattern值,而value為ResourceHttpRequestHandler,
          這樣就巧妙的把對(duì)靜態(tài)資源的訪問由HandlerMapping轉(zhuǎn)到ResourceHttpRequestHandler處理并返回,所以就支持classpath目錄,jar包內(nèi)靜態(tài)資源的訪問.
          另外需要注意的一點(diǎn)是,不要對(duì)SimpleUrlHandlerMapping設(shè)置defaultHandler.因?yàn)閷?duì)static uri的defaultHandler就是ResourceHttpRequestHandler,
          否則無法處理static resources request.

           

           

          方案三 ,使用<mvc:default-servlet-handler/>

          Xml代碼  收藏代碼
          1. <mvc:default-servlet-handler/>  

          會(huì)把"/**" url,注冊(cè)到SimpleUrlHandlerMapping的urlMap中,把對(duì)靜態(tài)資源的訪問由HandlerMapping轉(zhuǎn)到 org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler 處理并返回.
          DefaultServletHttpRequestHandler使用就是各個(gè)Servlet容器自己的默認(rèn)Servlet.

           

           

          補(bǔ)充說明:多個(gè)HandlerMapping的執(zhí)行順序問題:

          DefaultAnnotationHandlerMapping的order屬性值是:0

          <mvc:resources/ >自動(dòng)注冊(cè)的 SimpleUrlHandlerMapping的order屬性值是: 2147483646

           

          <mvc:default-servlet-handler/>自動(dòng)注冊(cè) 的SimpleUrlHandlerMapping 的order屬性值是: 2147483647

           

           

          spring會(huì)先執(zhí)行order值比較小的。當(dāng)訪問一個(gè)a.jpg圖片文件時(shí),先通過 DefaultAnnotationHandlerMapping 來找處理器,一定是找不到的,因?yàn)槲覀儧]有叫a.jpg的Action。然后再按order值升序找,由于最后一個(gè) SimpleUrlHandlerMapping 是匹配 "/**"的,所以一定會(huì)匹配上,就可以響應(yīng)圖片。

           

          訪問一個(gè)圖片,還要走層層匹配。不知性能如何?

          最后再說明一下,方案二、方案三 在訪問靜態(tài)資源時(shí),如果有匹配的(近似)總攔截器,就會(huì)走攔截器。如果你在攔截中實(shí)現(xiàn)權(quán)限檢查,要注意過濾這些對(duì)靜態(tài)文件的請(qǐng)求。

          如何你的DispatcherServlet攔截 *.do這樣的URL后綴,就不存上述問題了。還是有后綴方便。

           

          轉(zhuǎn)載請(qǐng)注明出處:原文地址:http://elf8848.iteye.com/blog/875830

           


          八、請(qǐng)求如何映射到具體的Action中的方法?
          方案一:基于xml配置映射,可以利用SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping進(jìn)行Url映射和攔截請(qǐng)求。
          配置方法略。
           
          方案二:基于注解映射,可以使用DefaultAnnotationHandlerMapping。

          Xml代碼  收藏代碼
          1. <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">  </bean>   

           

          但前面我們配置了<mvc:annotation-driven />,他會(huì)自動(dòng)注冊(cè)這個(gè)bean,就不須要我們顯示的注冊(cè)這個(gè)bean了。  

          如何替換 <mvc:annotation-driven />?他到底做了什么工作,請(qǐng)看,最后面的 十九節(jié) <mvc:annotation-driven /> 到底做了什么工作。


           
          以上都可以注入interceptors,實(shí)現(xiàn)權(quán)限控制等前置工作。
          我們使用第2種,基于注解來使用spring MVC

           

           

           并在action類上使用:
          @Controller
          @RequestMapping("/user")

          轉(zhuǎn)載請(qǐng)注明出處:原文地址:http://elf8848.iteye.com/blog/875830
           
           
          九、Spring中的攔截器:
          Spring為我們提供了:
          org.springframework.web.servlet.HandlerInterceptor接口,

          org.springframework.web.servlet.handler.HandlerInterceptorAdapter適配器,
          實(shí)現(xiàn)這個(gè)接口或繼承此類,可以非常方便的實(shí)現(xiàn)自己的攔截器。
           
          有以下三個(gè)方法:
           
          Action之前執(zhí)行:
           public boolean preHandle(HttpServletRequest request,
             HttpServletResponse response, Object handler);
           
          生成視圖之前執(zhí)行
           public void postHandle(HttpServletRequest request,
             HttpServletResponse response, Object handler,
             ModelAndView modelAndView);
           
          最后執(zhí)行,可用于釋放資源
           public void afterCompletion(HttpServletRequest request,
             HttpServletResponse response, Object handler, Exception ex)
           
           
          分別實(shí)現(xiàn)預(yù)處理、后處理(調(diào)用了Service并返回ModelAndView,但未進(jìn)行頁面渲染)、返回處理(已經(jīng)渲染了頁面)
          在preHandle中,可以進(jìn)行編碼、安全控制等處理;
          在postHandle中,有機(jī)會(huì)修改ModelAndView;
          在afterCompletion中,可以根據(jù)ex是否為null判斷是否發(fā)生了異常,進(jìn)行日志記錄。
          參數(shù)中的Object handler是下一個(gè)攔截器。
          轉(zhuǎn)載請(qǐng)注明出處:原文地址:http://elf8848.iteye.com/blog/875830


          十、如何使用攔截器?
          自定義一個(gè)攔截器,要實(shí)現(xiàn)HandlerInterceptor接口:

          Java代碼  收藏代碼
          1. public class MyInteceptor implements HandlerInterceptor {     
          2.     略。。。  
          3. }    

           

          Spring MVC并沒有總的攔截器,不能對(duì)所有的請(qǐng)求進(jìn)行前后攔截。
          Spring MVC的攔截器,是屬于HandlerMapping級(jí)別的,可以有多個(gè)HandlerMapping ,每個(gè)HandlerMapping可以有自己的攔截器。
          當(dāng)一個(gè)請(qǐng)求按Order值從小到大,順序執(zhí)行HandlerMapping接口的實(shí)現(xiàn)類時(shí),哪一個(gè)先有返回,那就可以結(jié)束了,后面的HandlerMapping就不走了,本道工序就完成了。就轉(zhuǎn)到下一道工序了。
          攔截器會(huì)在什么時(shí)候執(zhí)行呢? 一個(gè)請(qǐng)求交給一個(gè)HandlerMapping時(shí),這個(gè)HandlerMapping先找有沒有處理器來處理這個(gè)請(qǐng)求,如何找到了,就執(zhí)行攔截器,執(zhí)行完攔截后,交給目標(biāo)處理器。
          如果沒有找到處理器,那么這個(gè)攔截器就不會(huì)被執(zhí)行。

           


          在spring MVC的配置文件中配置有三種方法:


          方案一,(近似)總攔截器,攔截所有url

          Java代碼  收藏代碼
          1.    <mvc:interceptors>  
          2.     <bean class="com.app.mvc.MyInteceptor" />  
          3. </mvc:interceptors>  

          為什么叫“近似”,前面說了,Spring沒有總的攔截器。

          <mvc:interceptors/>會(huì)為每一個(gè)HandlerMapping,注入一個(gè)攔截器。總有一個(gè)HandlerMapping是可以找到處理器的,最多也只找到一個(gè)處理器,所以這個(gè)攔截器總會(huì)被執(zhí)行的。起到了總攔截器的作用。

          如果是REST風(fēng)格的URL,靜態(tài)資源也會(huì)被攔截。

           

           
          方案二, (近似) 總攔截器, 攔截匹配的URL。

          Xml代碼  收藏代碼
          1. <mvc:interceptors >    
          2.   <mvc:interceptor>    
          3.         <mvc:mapping path="/user/*" /> <!-- /user/*  -->    
          4.         <bean class="com.mvc.MyInteceptor"></bean>    
          5.     </mvc:interceptor>    
          6. </mvc:interceptors>    

          就是比 方案一多了一個(gè)URL匹配。

          如果是REST風(fēng)格的URL,靜態(tài)資源也會(huì)被攔截。

           

           

           

          方案三,HandlerMappint上的攔截器。

          如果是REST風(fēng)格的URL,靜態(tài)資源就不會(huì)被攔截。因?yàn)槲覀兙珳?zhǔn)的注入了攔截器。

          Xml代碼  收藏代碼
          1. <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">       
          2.  <property name="interceptors">       
          3.      <list>       
          4.          <bean class="com.mvc.MyInteceptor"></bean>      
          5.      </list>       
          6.  </property>       
          7. </bean>   

            如果使用了<mvc:annotation-driven />, 它會(huì)自動(dòng)注冊(cè)DefaultAnnotationHandlerMapping 與AnnotationMethodHandlerAdapter 這兩個(gè)bean,所以就沒有機(jī)會(huì)再給它注入interceptors屬性,就無法指定攔截器。

          當(dāng)然我們可以通過人工配置上面的兩個(gè)Bean,不使用 <mvc:annotation-driven />,就可以 給interceptors屬性 注入攔截器了。

           

          其實(shí)我也不建議使用 <mvc:annotation-driven />,而建議手動(dòng)寫詳細(xì)的配置文件,來替代 <mvc:annotation-driven />,這就控制力就強(qiáng)了。

          如何替換 <mvc:annotation-driven />?他到底做了什么工作,請(qǐng)看,最后面的 十九節(jié) <mvc:annotation-driven /> 到底做了什么工作。

          轉(zhuǎn)載請(qǐng)注明出處:原文地址:http://elf8848.iteye.com/blog/875830

           

           

           

          十一、如何實(shí)現(xiàn)全局的異常處理?

          在spring MVC的配置文件中:

          Xml代碼  收藏代碼
          1. <!-- 總錯(cuò)誤處理-->  
          2. <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  
          3.     <property name="defaultErrorView">    
          4.         <value>/error/error</value>  
          5.     </property>  
          6.     <property name="defaultStatusCode">    
          7.         <value>500</value>  
          8.     </property>     
          9. <property name="warnLogCategory">    
          10.         <value>org.springframework.web.servlet.handler.SimpleMappingExceptionResolver</value>  
          11.     </property>     
          12. </bean>   

           

          這里主要的類是SimpleMappingExceptionResolver類,和他的父類AbstractHandlerExceptionResolver類。

          具體可以配置哪些屬性,我是通過查看源碼知道的。

          你也可以實(shí)現(xiàn)HandlerExceptionResolver接口,寫一個(gè)自己的異常處理程序。spring的擴(kuò)展性是很好的。

           

           

          通過SimpleMappingExceptionResolver我們可以將不同的異常映射到不同的jsp頁面(通過exceptionMappings屬性的配置)。

           

          同時(shí)我們也可以為所有的異常指定一個(gè)默認(rèn)的異常提示頁面(通過defaultErrorView屬性的配置),如果所拋出的異常在exceptionMappings中沒有對(duì)應(yīng)的映射,則Spring將用此默認(rèn)配置顯示異常信息。

          注意這里配置的異常顯示界面均僅包括主文件名,至于文件路徑和后綴已經(jīng)在viewResolver中指定。如/error/error表示/error/error.jsp

           

           

          顯示錯(cuò)誤的jsp頁面:

          Html代碼  收藏代碼
          1. <%@ page language="java" contentType="text/html; charset=GBK"  
          2.     pageEncoding="GBK"%>  
          3. <%@ page import="java.lang.Exception"%>  
          4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
          5. <html>  
          6. <head>  
          7. <meta http-equiv="Content-Type" content="text/html; charset=GBK">  
          8. <title>錯(cuò)誤頁面</title>  
          9. </head>  
          10. <body>  
          11. <h1>出錯(cuò)了</h1>  
          12. <%  
          13. Exception e = (Exception)request.getAttribute("exception");  
          14. out.print(e.getMessage());  
          15. %>  
          16. </body>  
          17. </html>  

          其中一句:request.getAttribute("exception"),key是exception,也是在SimpleMappingExceptionResolver類默認(rèn)指定的,是可能通過配置文件修改這個(gè)值的,大家可以去看源碼。

           

           

           

          十二、如何把全局異常記錄到日志中?

          在前的配置中,其中有一個(gè)屬性warnLogCategory,值是 “SimpleMappingExceptionResolver類的全限定名”。我是在SimpleMappingExceptionResolver 類父類AbstractHandlerExceptionResolver類中找到這個(gè)屬性的。查看源碼后得知:如果warnLogCategory不為 空,spring就會(huì)使用apache的org.apache.commons.logging.Log日志工具,記錄這個(gè)異常,級(jí)別是warn。

          值:“org.springframework.web.servlet.handler.SimpleMappingExceptionResolver”,是“SimpleMappingExceptionResolver類的全限定名”。這個(gè)值不是隨便寫的。  因?yàn)槲以趌og4j的配置文件中還要加入 log4j.logger.org.springframework.web.servlet.handler.SimpleMappingExceptionResolver=WARN, 保證這個(gè)級(jí)別是warn的日志一定會(huì)被記錄,即使log4j的根日志級(jí)別是ERROR。

          轉(zhuǎn)載請(qǐng)注明出處:原文地址:http://elf8848.iteye.com/blog/875830

           

           

           

           十三、如何給spring3 MVC中的Action做JUnit單元測(cè)試?

           使用了spring3 MVC后,給action做單元測(cè)試變得很方便,我以前從來不給action寫單元測(cè)試的,現(xiàn)在可以根據(jù)情況寫一些了。

           不用給每個(gè)Action都寫單元測(cè)試吧,自己把握吧。

           

           JUnitActionBase類是所有JUnit的測(cè)試類的父類

          Java代碼  收藏代碼
          1. package test;  
          2. import javax.servlet.http.HttpServletRequest;  
          3. import javax.servlet.http.HttpServletResponse;  
          4. import org.junit.BeforeClass;  
          5. import org.springframework.mock.web.MockServletContext;  
          6. import org.springframework.web.context.WebApplicationContext;  
          7. import org.springframework.web.context.support.XmlWebApplicationContext;  
          8. import org.springframework.web.servlet.HandlerAdapter;  
          9. import org.springframework.web.servlet.HandlerExecutionChain;  
          10. import org.springframework.web.servlet.HandlerMapping;  
          11. import org.springframework.web.servlet.ModelAndView;  
          12. import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;  
          13. import org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping;  
          14. /**  
          15. * 說明: JUnit測(cè)試action時(shí)使用的基類 
          16. *  
          17. * @author  趙磊 
          18. * @version 創(chuàng)建時(shí)間:2011-2-2 下午10:27:03   
          19. */   
          20. public class JUnitActionBase {  
          21.     private static HandlerMapping handlerMapping;  
          22.     private static HandlerAdapter handlerAdapter;  
          23.     /** 
          24.      * 讀取spring3 MVC配置文件 
          25.      */  
          26.     @BeforeClass  
          27.  public static void setUp() {  
          28.         if (handlerMapping == null) {  
          29.             String[] configs = { "file:src/springConfig/springMVC.xml" };  
          30.             XmlWebApplicationContext context = new XmlWebApplicationContext();  
          31.             context.setConfigLocations(configs);  
          32.             MockServletContext msc = new MockServletContext();  
          33.             context.setServletContext(msc);         context.refresh();  
          34.             msc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);  
          35.             handlerMapping = (HandlerMapping) context  
          36.                     .getBean(DefaultAnnotationHandlerMapping.class);  
          37.             handlerAdapter = (HandlerAdapter) context.getBean(context.getBeanNamesForType(AnnotationMethodHandlerAdapter.class)[0]);     
          38.         }  
          39.     }  
          40.   
          41.     /** 
          42.      * 執(zhí)行request對(duì)象請(qǐng)求的action 
          43.      *  
          44.      * @param request 
          45.      * @param response 
          46.      * @return 
          47.      * @throws Exception 
          48.      */  
          49.     public ModelAndView excuteAction(HttpServletRequest request, HttpServletResponse response)  
          50.  throws Exception {  
          51.         HandlerExecutionChain chain = handlerMapping.getHandler(request);  
          52.         final ModelAndView model = handlerAdapter.handle(request, response,  
          53.                 chain.getHandler());  
          54.         return model;  
          55.     }  
          56. }  

           

           

          這是個(gè)JUnit測(cè)試類,我們可以new Request對(duì)象,來參與測(cè)試,太方便了。給request指定訪問的URL,就可以請(qǐng)求目標(biāo)Action了。

           

          Java代碼  收藏代碼
          1. package test.com.app.user;  
          2. import org.junit.Assert;  
          3. import org.junit.Test;  
          4. import org.springframework.mock.web.MockHttpServletRequest;  
          5. import org.springframework.mock.web.MockHttpServletResponse;  
          6. import org.springframework.web.servlet.ModelAndView;  
          7.   
          8. import test.JUnitActionBase;  
          9.   
          10. /**  
          11. * 說明: 測(cè)試OrderAction的例子 
          12. *  
          13. * @author  趙磊  
          14. * @version 創(chuàng)建時(shí)間:2011-2-2 下午10:26:55   
          15. */   
          16.   
          17. public class TestOrderAction extends JUnitActionBase {  
          18.     @Test  
          19.     public void testAdd() throws Exception {  
          20.     MockHttpServletRequest request = new MockHttpServletRequest();  
          21.         MockHttpServletResponse response = new MockHttpServletResponse();  
          22.         request.setServletPath("/order/add");  
          23.         request.addParameter("id", "1002");  
          24.         request.addParameter("date", "2010-12-30");  
          25.         request.setMethod("POST");  
          26.         // 執(zhí)行URI對(duì)應(yīng)的action  
          27.         final ModelAndView mav = this.excuteAction(request, response);  
          28.         // Assert logic  
          29.         Assert.assertEquals("order/add", mav.getViewName());  
          30.         String msg=(String)request.getAttribute("msg");  
          31.         System.out.println(msg);  
          32.     }  
          33. }  

           需要說明一下 :由于當(dāng)前最想版本的Spring(Test) 3.0.5還不支持@ContextConfiguration的注解式context file注入,所以還需要寫個(gè)setUp處理下,否則類似于Tiles的加載過程會(huì)有錯(cuò)誤,因?yàn)闆]有ServletContext。3.1的版本應(yīng)該有更 好的解決方案,

          參見: https://jira.springsource.org/browse/SPR-5243

          參考 :http://www.iteye.com/topic/828513

           

           

           

           

           十四、轉(zhuǎn)發(fā)與重定向

          可以通過redirect/forward:url方式轉(zhuǎn)到另一個(gè)Action進(jìn)行連續(xù)的處理。

          可以通過redirect:url 防止表單重復(fù)提交

          寫法如下:

          return "forward:/order/add";

          return "redirect:/index.jsp";

          轉(zhuǎn)載請(qǐng)注明出處:原文地址:http://elf8848.iteye.com/blog/875830

           

           

          帶參數(shù)重定向--RedirectAttributes

          用戶保存或修改后,為了防止用戶刷新瀏覽器(F5)導(dǎo)致表單重復(fù)提交,一般在保存或修改操作之后會(huì)redirect到一個(gè)結(jié)果頁面(不是 forward),同時(shí)攜帶參數(shù),如操作成功的提示信息。因?yàn)槭荝edirect,Request里的attribute不會(huì)傳遞過去。Spring在 3.1才提供了這個(gè)能力--RedirectAttributes。 反復(fù)按F5,操作成功的提示信息也不會(huì)再次出來(總共只出現(xiàn)一次),效果很理想。

           

          Java代碼  收藏代碼
          1. public String save(@ModelAttribute("group") Group group, RedirectAttributes redirectAttributes) {  
          2.     accountManager.saveGroup(group);  
          3.     redirectAttributes.addFlashAttribute("message", "操作成功");  
          4.     return "redirect:/account/group/";  
          5. }  
           

           

           

           十五、處理ajax請(qǐng)求

           

          1、引入下面兩個(gè)jar包,我用的是1.7.2,好像1.4.2版本以上都可以,下載地址: http://wiki.fasterxml.com/JacksonDownload

          jackson-core-asl-1.7.2.jar 

          jackson-mapper-asl-1.7.2.jar

           

          2、spring的配置文件中要有這一行,才能使用到spring內(nèi)置支持的json轉(zhuǎn)換。如果你手工把POJO轉(zhuǎn)成json就可以不須要使用spring內(nèi)置支持的json轉(zhuǎn)換。

          <mvc:annotation-driven />

           

          3、使用@ResponseBody注解

          Java代碼  收藏代碼
          1. /** 
          2.  * ajax測(cè)試 
          3. * http://127.0.0.1/mvc/order/ajax 
          4.  */  
          5.   
          6. @RequestMapping("/ajax")  
          7. @ResponseBody  
          8. public Object ajax(HttpServletRequest request){  
          9.     List<String> list=new ArrayList<String>();  
          10.     list.add("電視");  
          11. nbsp;       list.add("洗衣機(jī)");  
          12.     list.add("冰箱");  
          13.     list.add("電腦");  
          14.     list.add("汽車");  
          15.     list.add("空調(diào)");  
          16.     list.add("自行車");  
          17.     list.add("飲水機(jī)");  
          18.     list.add("熱水器");  
          19.     return list;  
          20. }  

           

          轉(zhuǎn)載請(qǐng)注明出處:原文地址:http://elf8848.iteye.com/blog/875830

           

           

           

          十六、關(guān)于寫幾個(gè)配置文件的說明

          我看到有的人把配置文件寫兩份:
          一個(gè)是原有的applicationContext.xml,這個(gè)文件從spring2.0-2.5時(shí)一直在使用。
          別一個(gè)是新加的spring MVC的配置文件。
          其實(shí)這兩個(gè)文件是可以寫成一個(gè)文件的,springMVC相關(guān)的配置,數(shù)據(jù)源,事務(wù)相關(guān)配置可以都寫再一個(gè)配置文件中。
          本例子中只使用了一個(gè)spring配置文件叫“springMVC.xml”。
          就不要再多配置一個(gè)applicationContext.xml文件了。
          web.xml文件中也不要再配置org.springframework.web.context.ContextLoaderListener的listener了。
          寫兩個(gè)配置文件一般就會(huì)導(dǎo)致掃描兩次,一定要精確控制掃描的包名,做到不重復(fù)掃描。

          寫兩個(gè)配置文件還出現(xiàn)事務(wù)不好使的現(xiàn)象,是當(dāng)把@Transactional寫有Action層時(shí)出現(xiàn)的。

          是因?yàn)楦缸由舷挛牡脑颍?qǐng)參看前的 第五節(jié) 父子上下文,里面有說明 。原因是父上下文不能訪問子上下文。

           

           

           

          十七、如何取得Spring管理的bean (請(qǐng)用第3種方法)
          1、servlet方式加載時(shí),
          【web.xml】

          Xml代碼  收藏代碼
          1. <servlet>  
          2. <servlet-name>springMVC</servlet-name>  
          3. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
          4. <init-param>  
          5. <param-name>contextConfigLocation</param-name>  
          6. <param-value>classpath*:/springMVC.xml</param-value>  
          7. </init-param>  
          8. <load-on-startup>1</load-on-startup>  
          9. </servlet>  

           spring容器放在ServletContext中的key是org.springframework.web.servlet.FrameworkServlet.CONTEXT.springMVC
          注意后面的springMVC,是你的servlet-name配置的值,注意適時(shí)修改。

          Java代碼  收藏代碼
          1. ServletContext sc=略  
          2. WebApplicationContext attr = (WebApplicationContext)sc.getAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.springMVC");  
           

          2、listener方式加載時(shí):
          【web.xml】

          Xml代碼  收藏代碼
          1. <context-param>  
          2.   <param-name>contextConfigLocation</param-name>  
          3.   <param-value>/WEB-INF/applicationContext</param-value>  
          4. </context-param>  
          5.   
          6. <listener>  
          7.   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
          8. </listener>  

           【jsp/servlet】可以這樣取得

          Java代碼  收藏代碼
          1. ServletContext context = getServletContext();  
          2. WebApplicationContext applicationContext  = WebApplicationContextUtils .getWebApplicationContext(context);   
           

          3、通用的方法來了,神器啊,前的  1、2兩種方法并不通用,可以拋棄了。
          在配置文件中加入:

          Xml代碼  收藏代碼
          1. <!-- 用于持有ApplicationContext,可以使用SpringContextHolder.getBean('xxxx')的靜態(tài)方法得到spring bean對(duì)象 -->  
          2. <bean class="com.xxxxx.SpringContextHolder" lazy-init="false" />  
           
          Java代碼  收藏代碼
          1. import org.springframework.context.ApplicationContext;  
          2. import org.springframework.context.ApplicationContextAware;  
          3. /** 
          4.  * 以靜態(tài)變量保存Spring ApplicationContext, 可在任何代碼任何地方任何時(shí)候中取出ApplicaitonContext. 
          5.  *  
          6.  */  
          7. public class SpringContextHolder implements ApplicationContextAware {  
          8. private static ApplicationContext applicationContext;  
          9.   
          10. /** 
          11. * 實(shí)現(xiàn)ApplicationContextAware接口的context注入函數(shù), 將其存入靜態(tài)變量. 
          12. */  
          13. public void setApplicationContext(ApplicationContext applicationContext) {  
          14. SpringContextHolder.applicationContext = applicationContext; // NOSONAR  
          15. }  
          16.   
          17. /** 
          18. * 取得存儲(chǔ)在靜態(tài)變量中的ApplicationContext. 
          19. */  
          20. public static ApplicationContext getApplicationContext() {  
          21. checkApplicationContext();  
          22. return applicationContext;  
          23. }  
          24.   
          25. /** 
          26. * 從靜態(tài)變量ApplicationContext中取得Bean, 自動(dòng)轉(zhuǎn)型為所賦值對(duì)象的類型. 
          27. */  
          28. @SuppressWarnings("unchecked")  
          29. public static <T> T getBean(String name) {  
          30. checkApplicationContext();  
          31. return (T) applicationContext.getBean(name);  
          32. }  
          33.   
          34. /** 
          35. * 從靜態(tài)變量ApplicationContext中取得Bean, 自動(dòng)轉(zhuǎn)型為所賦值對(duì)象的類型. 
          36. */  
          37. @SuppressWarnings("unchecked")  
          38. public static <T> T getBean(Class<T> clazz) {  
          39. checkApplicationContext();  
          40. return (T) applicationContext.getBeansOfType(clazz);  
          41. }  
          42.   
          43. /** 
          44. * 清除applicationContext靜態(tài)變量. 
          45. */  
          46. public static void cleanApplicationContext() {  
          47. applicationContext = null;  
          48. }  
          49.   
          50. private static void checkApplicationContext() {  
          51. if (applicationContext == null) {  
          52. throw new IllegalStateException("applicaitonContext未注入,請(qǐng)?jiān)赼pplicationContext.xml中定義SpringContextHolder");  
          53. }  
          54. }  
          55. }  

            轉(zhuǎn)載請(qǐng)注明出處:原文地址:http://elf8848.iteye.com/blog/875830

           

           

          十八、多視圖控制器

           

          當(dāng)有jsp,flt (模板)等多種頁面生成展示方式時(shí),spring默認(rèn)使用的是“視圖解析器鏈”。 真是一個(gè)鏈,所以性能不好,spring會(huì)在“視圖解析器鏈”中順序的查找,直到找到對(duì)應(yīng)的 “視圖解析器” 。jsp視圖解析器一定要寫在最后面,因?yàn)橐坏┱{(diào)用jsp,就向?yàn)g覽器發(fā)出數(shù)據(jù)了,Spring就沒有機(jī)會(huì)再嘗試下一個(gè)了。

          所以自己寫一個(gè)"多視圖解析器",依靠擴(kuò)展名來區(qū)分,可一次準(zhǔn)確的選中一個(gè) 視圖解析器,提高性能(會(huì)有多少提高呢?沒測(cè)試過).

           

          下面的例子支持jsp,flt (模板)兩種頁面生成展示方式,你中以自己添加,支持更多。

           

          Xml代碼  收藏代碼
          1.    <!-- 多視圖處理器 -->  
          2.    <bean class="com.xxx.core.web.MixedViewResolver">  
          3.     <property name="resolvers">  
          4.         <map>  
          5.             <entry key="jsp">  
          6.                 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
          7.                     <property name="prefix" value="/WEB-INF/jsp/"/>  
          8.                     <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>  
          9.                 </bean>  
          10.             </entry>  
          11.             <entry key="ftl">  
          12.                 <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">  
          13.                     <property name="cache" value="true"/>  
          14.                     <property name="contentType" value="text/html;charset=UTF-8"></property>  
          15.                     <!-- 宏命令的支持  -->    
          16.                     <property name="exposeSpringMacroHelpers" value="true"/>  
          17.                     <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/>  
          18.                     <property name="requestContextAttribute" value="rc"></property>  
          19.                 </bean>  
          20.             </entry>  
          21.         </map>  
          22.     </property>  
          23. </bean>  
          24.   
          25. <!-- freemarker config -->  
          26.    <bean id="freeMarkerConfigurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">   
          27.        <property name="templateLoaderPath" value="/WEB-INF/ftl/" />   
          28.        <property name="freemarkerSettings">   
          29.            <props>   
          30.                <prop key="template_update_delay">5</prop>   
          31.                <prop key="default_encoding">UTF-8</prop>   
          32.                <prop key="locale">zh_CN</prop>   
          33.            </props>   
          34.        </property>   
          35.    </bean>   
            

           

          Java代碼  收藏代碼
          1. import java.util.Locale;  
          2. import java.util.Map;  
          3. import org.springframework.web.servlet.View;  
          4. import org.springframework.web.servlet.ViewResolver;  
          5.   
          6. /**  
          7. * 說明: 多視圖處理器 
          8. *  
          9. * @author  趙磊  
          10. * @version 創(chuàng)建時(shí)間:2011-8-19 上午09:41:09   
          11. */   
          12. public class MixedViewResolver implements ViewResolver{  
          13.     private Map<String,ViewResolver> resolvers;  
          14.   
          15.     public void setResolvers(Map<String, ViewResolver> resolvers) {  
          16.         this.resolvers = resolvers;  
          17.     }  
          18.       
          19.     public View resolveViewName(String viewName,Locale locale) throws Exception{  
          20.         int n=viewName.lastIndexOf(".");  
          21.         if(n!=-1){  
          22.             //取出擴(kuò)展名  
          23.             String suffix=viewName.substring(n+1);  
          24.             //取出對(duì)應(yīng)的ViewResolver  
          25.             ViewResolver resolver=resolvers.get(suffix);  
          26.             if(resolver==null){  
          27.                 throw new RuntimeException("No ViewResolver for "+suffix);  
          28.             }  
          29.             return  resolver.resolveViewName(viewName, locale);  
          30.         }else{  
          31.             ViewResolver resolver=resolvers.get("jsp");  
          32.             return  resolver.resolveViewName(viewName, locale);  
          33.         }  
          34.     }  
          35. }  

            轉(zhuǎn)載請(qǐng)注明出處:原文地址:http://elf8848.iteye.com/blog/875830

           

           

          十九、 <mvc:annotation-driven /> 到底做了什么工作

           

           

          一句 <mvc:annotation-driven />實(shí)際做了以下工作:(不包括添加自己定義的攔截器)

          我們了解這些之后,對(duì)Spring3 MVC的控制力就更強(qiáng)大了,想改哪就改哪里。

          Xml代碼  收藏代碼
          1.    <!-- 注解請(qǐng)求映射  -->  
          2.    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">          
          3.     <property name="interceptors">  
          4.         <list>    
          5.             <ref bean="logNDCInteceptor"/>   <!-- 日志攔截器,這是你自定義的攔截器 -->  
          6.             <ref bean="myRequestHelperInteceptor"/>   <!-- RequestHelper攔截器,這是你自定義的攔截器-->   
          7.             <ref bean="myPermissionsInteceptor"/>  <!-- 權(quán)限攔截器,這是你自定義的攔截器-->   
          8.             <ref bean="myUserInfoInteceptor"/>  <!-- 用戶信息攔截器,這是你自定義的攔截器-->   
          9.         </list>          
          10.     </property>          
          11. </bean>     
          12. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">  
          13.     <property name="messageConverters">    
          14.         <list>    
          15.             <ref bean="byteArray_hmc" />    
          16.             <ref bean="string_hmc" />    
          17.             <ref bean="resource_hmc" />    
          18.             <ref bean="source_hmc" />    
          19.             <ref bean="xmlAwareForm_hmc" />    
          20.             <ref bean="jaxb2RootElement_hmc" />    
          21.             <ref bean="jackson_hmc" />    
          22.         </list>    
          23.     </property>    
          24. </bean>    
          25. <bean id="byteArray_hmc" class="org.springframework.http.converter.ByteArrayHttpMessageConverter" /><!-- 處理.. -->  
          26. <bean id="string_hmc" class="org.springframework.http.converter.StringHttpMessageConverter" /><!-- 處理.. -->  
          27. <bean id="resource_hmc" class="org.springframework.http.converter.ResourceHttpMessageConverter" /><!-- 處理.. -->  
          28. <bean id="source_hmc" class="org.springframework.http.converter.xml.SourceHttpMessageConverter" /><!-- 處理.. -->  
          29. <bean id="xmlAwareForm_hmc" class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter" /><!-- 處理.. -->  
          30. <bean id="jaxb2RootElement_hmc" class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" /><!-- 處理.. -->  
          31. <bean id="jackson_hmc" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" /><!-- 處理json-->  

            轉(zhuǎn)載請(qǐng)注明出處:原文地址:http://elf8848.iteye.com/blog/875830

           

           

           

          二十、 本文中springMVC.xml配置文件是核心,這里給一個(gè)下載地址

           

          要在http://www.iteye.com/網(wǎng)站有注冊(cè)帳號(hào)才能下載(這不能怪我)

           

          Spring_MVC_教程_快速入門_深入分析V1.1.pdf

           

          SpringMVC核心配置文件示例.rar

           

           

           

           

           

           

           

           

           

           

          posted on 2014-10-31 10:33 SIMONE 閱讀(435) 評(píng)論(0)  編輯  收藏 所屬分類: JSP
          主站蜘蛛池模板: 东至县| 会昌县| 东明县| 高平市| 吉林市| 聊城市| 莱西市| 栾城县| 天全县| 武邑县| 登封市| 东安县| 黄石市| 武鸣县| 红安县| 遂溪县| 宁明县| 云梦县| 卓资县| 盘锦市| 孙吴县| 新绛县| 乡城县| 平湖市| 永和县| 普宁市| 木兰县| 嘉峪关市| 读书| 保康县| 中卫市| 宝丰县| 镇远县| 平乡县| 泰和县| 昌乐县| 县级市| 砀山县| 苏州市| 青岛市| 桑植县|