springmvc相关配置和用法
?
目錄如下:
一、spring mvc 核心類與接口
二、spring mvc?核心流程圖
三、spring mvc?DispatcherServlet說明
四、spring mvc 父子上下文的說明
五、springMVC-mvc.xml 配置文件片段講解?
六、spring mvc?如何訪問到靜態的文件,如jpg,js,css
七、spring mvc?請求如何映射到具體的Action中的方法
八、 spring mvc?中的攔截器
九、 spring mvc?如何使用攔截器
十、 spring mvc?轉發與重定向 (帶參數重定向)
十一、 spring mvc?處理ajax請求
十二、 spring mvc?關于寫幾個配置文件的說明?
十三、 spring mvc?如何取得Spring管理的bean
十四、 spring mvc?多視圖控制器
十五、 <mvc:annotation-driven /> 到底做了什么工作?
spring mvc 核心類與接口
先來了解一下,幾個重要的接口與類?,F在不知道他們是干什么的沒關系,先混個臉熟,為以后認識他們打個基礎。
DispatcherServlet?? -- 前置控制器
?
HandlerMapping接口 -- 處理請求的映射
HandlerMapping接口的實現類:
SimpleUrlHandlerMapping? 通過配置文件,把一個URL映射到Controller
DefaultAnnotationHandlerMapping? 通過注解,把一個URL映射到Controller類上
?
?
HandlerAdapter接口 -- 處理請求的映射
AnnotationMethodHandlerAdapter類,通過注解,把一個URL映射到Controller類的方法上
Controller接口 -- 控制器
由于我們使用了@Controller注解,添加了@Controller注解注解的類就可以擔任控制器(Action)的職責,
所以我們并沒有用到這個接口。
HandlerInterceptor 接口--攔截器
無圖,我們自己實現這個接口,來完成攔截的器的工作。
?
ViewResolver接口的實現類
UrlBasedViewResolver類 通過配置文件,把一個視圖名交給到一個View來處理
InternalResourceViewResolver類,比上面的類,加入了JSTL的支持
?
View接口
JstlView類
LocalResolver接口
HandlerExceptionResolver接口 --異常處理
SimpleMappingExceptionResolver實現類
ModelAndView類
無圖。
spring mvc?核心流程圖
spring mvc?DispatcherServlet說明
使用Spring MVC,配置DispatcherServlet是第一步。
DispatcherServlet是一個Servlet,所以可以配置多個DispatcherServlet。
DispatcherServlet是前置控制器,配置在web.xml文件中的。攔截匹配的請求,Servlet攔截匹配規則要自已定義,把攔截下來的請求,依據某某規則分發到目標Controller(我們寫的Action)來處理。
“某某規則”:是根據你使用了哪個HandlerMapping接口的實現類的不同而不同。
先來看第一個例子:
| 1 2 3 4 5 6 7 8 9 10 11 | <web-app>? ????<servlet>? ????????<servlet-name>example</servlet-name>? ????????<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>? ????????<load-on-startup>1</load-on-startup>? ????</servlet>? ????<servlet-mapping>? ????????<servlet-name>example</servlet-name>? ????????<url-pattern>*.form</url-pattern>? ????</servlet-mapping>? </web-app> |
?<load-on-startup>1</load-on-startup>是啟動順序,讓這個Servlet隨Servletp容器一起啟動。
?<url-pattern>*.form</url-pattern> 會攔截*.form結尾的請求。
?<servlet-name>example</servlet-name>這個Servlet的名字是example,可以有多個DispatcherServlet,是通過名字來區分的。每一個DispatcherServlet有自己的WebApplicationContext上下文對象。同時保存的ServletContext中和Request對象中,關于key,以后說明。
在DispatcherServlet的初始化過程中,框架會在web應用的 WEB-INF文件夾下尋找名為[servlet-name]-servlet.xml 的配置文件,生成文件中定義的bean。
第二個例子:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | <servlet>? ????<servlet-name>springMVC</servlet-name>? ????<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>? ????<init-param>? ????????<param-name>contextConfigLocation</param-name>? ????????<param-value>classpath*:/springMVC.xml</param-value>? ????</init-param>? ????<load-on-startup>1</load-on-startup>? </servlet>? <servlet-mapping>? ????<servlet-name>springMVC</servlet-name>? ????<url-pattern>/</url-pattern>? </servlet-mapping> |
指明了配置文件的文件名,不使用默認配置文件名,而使用springMVC.xml配置文件。
其中<param-value>**.xml</param-value> 這里可以使用多種寫法
1、不寫,使用默認值:/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、多個值用逗號分隔
Servlet攔截匹配規則可以自已定義,攔截哪種URL合適??
當映射為@RequestMapping("/user/add")時,為例:
1、攔截*.do、*.htm, 例如:/user/add.do
這是最傳統的方式,最簡單也最實用。不會導致靜態文件(jpg,js,css)被攔截。
2、攔截/,例如:/user/add
可以實現現在很流行的REST風格。很多互聯網類型的應用很喜歡這種風格的URL。
弊端:會導致靜態文件(jpg,js,css)被攔截后不能正常顯示。想實現REST風格,事情就是麻煩一些。后面有解決辦法還算簡單。
3、攔截/*,這是一個錯誤的方式,請求可以走到Action中,但轉到jsp時再次被攔截,不能訪問到jsp。
spring mvc 父子上下文的說明
如果你使用了listener監聽器來加載配置,一般在Struts+Spring+Hibernate的項目中都是使用listener監聽器的。如下
| 1 2 3 | <listener>??? ??<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>??? </listener> |
Spring會創建一個WebApplicationContext上下文,稱為父上下文(父容器)?,保存在 ServletContext中,key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。
可以使用Spring提供的工具類取出上下文對象:WebApplicationContextUtils.getWebApplicationContext(ServletContext);
DispatcherServlet是一個Servlet,可以同時配置多個,每個 DispatcherServlet有一個自己的上下文對象(WebApplicationContext),稱為子上下文(子容器),子上下文可以訪問父上下文中的內容,但父上下文不能訪問子上下文中的內容。 它也保存在 ServletContext中,key是"org.springframework.web.servlet.FrameworkServlet.CONTEXT"+Servlet名稱。當一個Request對象產生時,會把這個子上下文對象(WebApplicationContext)保存在Request對象中,key是DispatcherServlet.class.getName() + ".CONTEXT"。
可以使用工具類取出上下文對象:RequestContextUtils.getWebApplicationContext(request);
說明 :Spring 并沒有限制我們,必須使用父子上下文。我們可以自己決定如何使用,一般建議這樣使用。
方案一,傳統型:
父上下文容器中保存數據源、服務層、DAO層、事務的Bean。
子上下文容器中保存Mvc相關的Action的Bean.
事務控制在服務層。
由于父上下文容器不能訪問子上下文容器中內容,事務的Bean在父上下文容器中,無法訪問子上下文容器中內容,就無法對子上下文容器中Action進行AOP(事務)。
當然,做為“傳統型”方案,也沒有必要這要做。
方案二,激進型:(不推薦)
Java世界的“面向接口編程”的思想是正確的,但在增刪改查為主業務的系統里,Dao層接口,Dao層實現類,Service層接口,Service層實現類,Action父類,Action。再加上眾多的O(vo\po\bo)和jsp頁面。寫一個小功能 7、8個類就寫出來了。 開發者說我就是想接點私活兒,和PHP,ASP搶搶飯碗,但我又是Java程序員。最好的結果是大項目能做好,小項目能做快。所以“激進型”方案就出現了-----沒有接口、沒有Service層、還可以沒有眾多的O(vo\po\bo)。那沒有Service層事務控制在哪一層?只好上升的Action層。
本文不想說這是不是正確的思想,我想說的是Spring不會限制你這樣做。
由于有了父子上下文,你將無法實現這一目標。解決方案是只使用子上下文容器,不要父上下文容器?。所以數據源、服務層、DAO層、事務的Bean、Action的Bean都放在子上下文容器中。就可以實現了,事務(注解事務)就正常工作了。這樣才夠激進。
總結:不使用listener監聽器來加載spring的配置文件,只使用DispatcherServlet來加載spring的配置,不要父子上下文,只使用一個DispatcherServlet,事情就簡單了,什么麻煩事兒也沒有了。
Java--大項目能做好--按傳統方式做,規規矩矩的做,好擴展,好維護。
Java--小項目能做快--按激進方式做,一周時間就可以出一個版本,先上線接受市場(用戶)的反饋,再改進,再反饋,時間就是生命(成本)。
springMVC-mvc.xml 配置文件片段講解?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <?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:tx="http://www.springframework.org/schema/tx"? ????xmlns:context="http://www.springframework.org/schema/context"??? ????xmlns:mvc="http://www.springframework.org/schema/mvc"??? ????xsi:schemaLocation="http://www.springframework.org/schema/beans?? ????http://www.springframework.org/schema/beans/spring-beans-3.0.xsd?? ????http://www.springframework.org/schema/tx?? ????http://www.springframework.org/schema/tx/spring-tx-3.0.xsd? ????http://www.springframework.org/schema/context? ????http://www.springframework.org/schema/context/spring-context-3.0.xsd? ????http://www.springframework.org/schema/mvc? ????http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">? ??? ??? ????<!-- 自動掃描的包名 -->? ????<context:component-scan base-package="com.app,com.core,JUnit4"?></context:component-scan>? ??????? ????<!-- 默認的注解映射的支持 -->? ????<mvc:annotation-driven />? ??????? ????<!-- 視圖解釋類 -->? ????<bean?class="org.springframework.web.servlet.view.InternalResourceViewResolver">? ????????<property name="prefix"?value="/WEB-INF/jsp/"/>? ????????<property name="suffix"?value=".jsp"/><!--可為空,方便實現自已的依據擴展名來選擇視圖解釋類的邏輯? -->? ????????<property name="viewClass"?value="org.springframework.web.servlet.view.JstlView"?/>? ????</bean>? ??????? ????<!-- 攔截器 -->? ????<mvc:interceptors>? ????????<bean?class="com.core.mvc.MyInteceptor"?/>? ????</mvc:interceptors>?????? ??????? ????<!-- 對靜態資源文件的訪問? 方案一 (二選一) -->? ????<mvc:default-servlet-handler/>? ??????? ????<!-- 對靜態資源文件的訪問? 方案二 (二選一)-->? ????<mvc:resources mapping="/images/**"?location="/images/"?cache-period="31556926"/>? ????<mvc:resources mapping="/js/**"?location="/js/"?cache-period="31556926"/>? ????<mvc:resources mapping="/css/**"?location="/css/"?cache-period="31556926"/>? ??? </beans> |
<context:component-scan/> 掃描指定的包中的類上的注解,常用的注解有:
@Controller 聲明Action組件
@Service??? 聲明Service組件??? @Service("myMovieLister")?
@Repository 聲明Dao組件
@Component?? 泛指組件, 當不好歸類時.?
@RequestMapping("/menu")? 請求映射
@Resource? 用于注入,( j2ee提供的 ) 默認按名稱裝配,@Resource(name="beanName")?
@Autowired 用于注入,(srping提供的) 默認按類型裝配?
@Transactional( rollbackFor={Exception.class}) 事務管理
@ResponseBody
@Scope("prototype")?? 設定bean的作用域
<mvc:annotation-driven /> 是一種簡寫形式,完全可以手動配置替代這種簡寫形式,簡寫形式可以讓初學都快速應用默認配置方案。<mvc:annotation-driven />?會自動注冊DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter?兩個bean,是spring MVC為@Controllers分發請求所必須的。
并提供了:數據綁定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,讀寫XML的支持(JAXB),讀寫JSON的支持(Jackson)。
后面,我們處理響應ajax請求時,就使用到了對json的支持。
后面,對action寫JUnit單元測試時,要從spring IOC容器中取DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter 兩個bean,來完成測試,取的時候要知道是<mvc:annotation-driven />這一句注冊的這兩個bean。
如何替換?<mvc:annotation-driven />?他到底做了什么工作,請看,最后面的章節 “<mvc:annotation-driven />?到底做了什么工作”。
<mvc:interceptors/>?是一種簡寫形式。通過看前面的大圖,知道,我們可以配置多個HandlerMapping。<mvc:interceptors/>會為每一個HandlerMapping,注入一個攔截器。其實我們也可以手動配置為每個HandlerMapping注入一個攔截器。
<mvc:default-servlet-handler/>?使用默認的Servlet來響應靜態文件。
<mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/> 匹配URL? /images/**? 的URL被當做靜態資源,由Spring讀出到內存中再響應http。
spring mvc?如何訪問到靜態的文件,如jpg,js,css
如果你的DispatcherServlet攔截"*.do"這樣的有后綴的URL,就不存在訪問不到靜態資源的問題。
如果你的DispatcherServlet攔截"/",為了實現REST風格,攔截了所有的請求,那么同時對*.js,*.jpg等靜態文件的訪問也就被攔截了。
我們要解決這個問題。
目的:可以正常訪問靜態文件,不可以找不到靜態文件報404。
方案一:激活Tomcat的defaultServlet來處理靜態文件
| 1 2 3 4 5 6 7 8 9 10 11 12 | <servlet-mapping>??? ????<servlet-name>default</servlet-name>? ????<url-pattern>*.jpg</url-pattern>????? </servlet-mapping>???? <servlet-mapping>??????? ????<servlet-name>default</servlet-name>???? ????<url-pattern>*.js</url-pattern>???? </servlet-mapping>???? <servlet-mapping>???????? ????<servlet-name>default</servlet-name>??????? ????<url-pattern>*.css</url-pattern>?????? </servlet-mapping> |
要配置多個,每種文件配置一個 ??
要寫在DispatcherServlet的前面, 讓?defaultServlet先攔截請求,這樣請求就不會進入Spring了,我想性能是最好的吧。
Tomcat, Jetty, JBoss, and GlassFish 自帶的默認Servlet的名字 -- "default"
Google App Engine?自帶的?默認Servlet的名字 -- "_ah_default"
Resin?自帶的?默認Servlet的名字 -- "resin-file"
WebLogic?自帶的?默認Servlet的名字? -- "FileServlet"
WebSphere??自帶的?默認Servlet的名字 -- "SimpleFileServlet"?
方案二: 在spring3.0.4以后版本提供了mvc:resources , ?使用方法:
| 1 2 | <!-- 對靜態資源文件的訪問 -->???? <mvc:resources mapping="/images/**"?location="/images/"?/> |
/images/**映射到ResourceHttpRequestHandler進行處理,location指定靜態資源的位置.可以是web application根目錄下、jar包里面,這樣可以把靜態資源壓縮到jar包中。cache-period 可以使得靜態資源進行web cache?
如果出現下面的錯誤,可能是沒有配置<mvc:annotation-driven />的原因。?
報錯WARNING: No mapping found for HTTP request with URI [/mvc/user/findUser/lisi/770] in DispatcherServlet with name 'springMVC'
使用<mvc:resources/>元素,把mapping的URI注冊到SimpleUrlHandlerMapping的urlMap中,
key為mapping的URI pattern值,而value為ResourceHttpRequestHandler,
這樣就巧妙的把對靜態資源的訪問由HandlerMapping轉到ResourceHttpRequestHandler處理并返回,所以就支持classpath目錄,jar包內靜態資源的訪問.
另外需要注意的一點是,不要對SimpleUrlHandlerMapping設置defaultHandler.因為對static uri的defaultHandler就是ResourceHttpRequestHandler,
否則無法處理static resources request.
方案三 ,使用<mvc:default-servlet-handler/>
| 1 | <mvc:default-servlet-handler/> |
會把"/**" url,注冊到SimpleUrlHandlerMapping的urlMap中,把對靜態資源的訪問由HandlerMapping轉到org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler處理并返回.
DefaultServletHttpRequestHandler使用就是各個Servlet容器自己的默認Servlet.
補充說明:
多個HandlerMapping的執行順序問題:
DefaultAnnotationHandlerMapping的order屬性值是:0
<mvc:resources/?>自動注冊的?SimpleUrlHandlerMapping的order屬性值是:?2147483646
<mvc:default-servlet-handler/>自動注冊?的SimpleUrlHandlerMapping?的order屬性值是:?2147483647
spring會先執行order值比較小的。當訪問一個a.jpg圖片文件時,先通過 DefaultAnnotationHandlerMapping 來找處理器,一定是找不到的,因為我們沒有叫a.jpg的Action。然后再按order值升序找,由于最后一個 SimpleUrlHandlerMapping 是匹配 "/**"的,所以一定會匹配上,就可以響應圖片。
訪問一個圖片,還要走層層匹配。不知性能如何?
最后再說明一下,方案二、方案三 在訪問靜態資源時,如果有匹配的(近似)總攔截器,就會走攔截器。如果你在攔截中實現權限檢查,要注意過濾這些對靜態文件的請求。
如何你的DispatcherServlet攔截 *.do這樣的URL后綴,就不存上述問題了。還是有后綴方便。
spring mvc?請求如何映射到具體的Action中的方法
八、 spring mvc?中的攔截器
九、 spring mvc?如何使用攔截器
十、 spring mvc?轉發與重定向 (帶參數重定向)
十一、 spring mvc?處理ajax請求
十二、 spring mvc?關于寫幾個配置文件的說明?
十三、 spring mvc?如何取得Spring管理的bean
十四、 spring mvc?多視圖控制器
十五、 <mvc:annotation-driven /> 到底做了什么工作?
轉載于:https://www.cnblogs.com/chunhui521/p/9104071.html
總結
以上是生活随笔為你收集整理的springmvc相关配置和用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 20172332 2017-2018-2
- 下一篇: mock 测试 MVC