解析mediaTypes+viewResolvers+viewResolvers
spring在解析視圖的時候有兩個重要的接口:ViewResolver?和?View
ViewResolver 中只有一個方法 resolveViewName ,提供 view name 和 實際 view的映射;
View 中兩個方法 getContentType 和 render ,解析請求中的參數并把這個請求處理成某一種 View.
說白了,就是ViewResolver 負責怎么去解析, 而View只代表一種 視圖層的技術。
對于一個請求,應該返回什么樣的視圖是 ViewResolver 來決定的,spring3.0提供的 ViewResolver 包括 AbstractCachingViewResolver,
XmlViewResolver,ResourceBundleViewResolver,UrlBasedViewResolver,InternalResourceViewResolver,VelocityViewResolver/FreeMarkerViewResolver,
ContentNegotiatingViewResolver等。從字面意思我們大致就可以猜出起用途。
我們平時使用ResourceBundleViewResolver或者InternalResourceViewResolver來返回JSP頁面,他們就是其中的兩個 ViewResolver?
下面我主要說說ContentNegotiatingViewResolver?
根據官方文檔:The ContentNegotiatingViewResolver does not resolve views itself but rather delegates to other view resolvers,就是說ContentNegotiatingViewResolver 本身并不自己去解析,他只是分配給其他的ViewResolver 去解析。并選擇一個看起來像是客戶端請求需要返回的一種? View? 返回。
下面來看看我們想要返回的JSON格式的數據,spring3.0中提供了一種View 來支持 JSON,MappingJacksonJsonView ?,在這個View中我們可以封裝數據,
屬性等等,但是怎么讓spring返回這個view呢,還是要通過 ViewResolver 來處理。
我們來看官方文檔里的一份關于ContentNegotiatingViewResolver??的典型配置:
Java代碼??
<bean?class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">??
?<property name="ignoreAcceptHeader" value="true"/>
<!--?在沒有擴展名時即:?"http://www.sxrczx.com/rest"?時的默認展現形式?-->
?<property name="defaultContentType" value="text/html"/>
<!--?擴展名至mimeType的映射,即?http://www.sxrczx.com/rest.json?映射為?application/json?-->
??<property?name="mediaTypes">??
????<map>??
??????<entry?key="atom"?value="application/atom+xml"/>??
??????<entry?key="html"?value="text/html"/>??
??????<entry?key="json"?value="application/json"/>??
????</map>??
??</property>
??<property?name="viewResolvers">??
????<list>??
??????<bean?class="org.springframework.web.servlet.view.BeanNameViewResolver"/>??
??????<bean?class="org.springframework.web.servlet.view.InternalResourceViewResolver">??
<!--
? ? ? ??<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
-->
????????<property?name="prefix"?value="/WEB-INF/jsp/"/>??
????????<property?name="suffix"?value=".jsp"/>??
??????</bean>??
????</list>??
??</property>??
??<property?name="defaultViews">??
????<list>??
? ? ??<!-- for application/json -->
??????<bean?class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"?/> ?
????</list>??
??</property>??
</bean>??
??
<bean?id="content"?class="com.springsource.samples.rest.SampleContentAtomView"/>??
關于 mediaTypes 這個屬性我稍后分析,先看viewResolvers和defaultViews這兩個屬性,viewResolvers中定義了兩個 ViewResolver ,defaultViews定義了一個默認的返回視圖。
但是ContentNegotiatingViewResolver? 是怎么決定使用哪個ViewResolver 以及 返回什么樣的 View呢? 通過跟蹤源碼和查看API文檔可以很容易發現。
?
API中寫道:
This view resolver uses the requested media type to select a suitable View for a request. This media type is determined by using the following criteria:
1. If the requested path has a file extension and if the setFavorPathExtension(boolean) property is true, the mediaTypes property is inspected for a matching media type.
2. If the request contains a parameter defining the extension and if the setFavorParameter(boolean) property is true, the mediaTypes property is inspected for a matching media type.?
The default name of the parameter is format and it can be configured using the parameterName property.
3. If there is no match in the mediaTypes property and if the Java Activation Framework (JAF) is both enabled and present on the class path, FileTypeMap.getContentType(String) is used instead.
4. If the previous steps did not result in a media type, and ignoreAcceptHeader is false, the request Accept header is used.
Once the requested media type has been determined, this resolver queries each delegate view resolver for a View and determines if the requested media type is compatible with the view's content type). The most compatible view is returned.
?
1. spring檢查setFavorPathExtension(boolean)?,如果這個屬性為true(默認為true),它檢查請求的后綴名,來返回一種 mediaType ,
而后綴名和mediaType是通過ContentNegotiatingViewResolver??配置中的mediaTypes指定的,這個我開始也不確定,后來跟蹤源碼發現確實是這樣映射的。
?
2.spring檢查?setFavorParameter(boolean)?這個屬性是否為true(默認為false),而如果你打開這個屬性,那么默認的參數名應為 format ,
spring通過你傳過去的參數決定返回哪種mediaType。
?
3.如果前兩步沒有找到合適的mediaType,則啟動**機制去找,這個看不懂,也不用管了。
?
4.如果前三步都沒有找到合適的mediaType,并且?ignoreAcceptHeader?這個屬性為false(默認為false),spring則根據 ?你請求頭里面設置的 ?ContentType 來找適合的 mediaType。
?
那么現在我們明白了?ContentNegotiatingViewResolver???resolves a view based on the request file name or?Accept?header. ?
?就是ContentNegotiatingViewResolver??根據文件名和請求頭類型來決定返回什么樣的View。而mediaTypes這個屬性存儲了 你請求后綴名 或者 參數 所對應 的mediaType。
?
所以要想返回JSON數據所代表的MappingJacksonJsonView ??,我們要么在請求頭中設置contentType為application/json,要么使用 **.json ? 或者 ?**?format=json?
(這是我的猜測,我猜spring接收到format中的參數后也會去那個map中找)這種請求,其中json這個名字你可以任意換,只要在配置文件中統一就可以了。
?
下面是我項目中具體的使用:
?
XML中的配置:
Xml文件代碼??
<bean?class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">????
????<property?name="mediaTypes">????
??????<map>????
????????<entry?key="html"?value="text/html"/>????
????????<entry?key="spring"?value="text/html"/>??
????????<entry?key="json"?value="application/json"/>????
??????</map>????
????</property>??
????<property?name="viewResolvers">????
??????<list>??
????????<bean?class="org.springframework.web.servlet.view.InternalResourceViewResolver">????
??????????<property?name="prefix"?value="/"/>??
??????????<property?name="suffix"?value=".jsp"/>??
????????</bean>??
??????</list>??
????</property>??
????<property?name="defaultViews">??
????????<list>??
????????????<bean?class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>??
????????</list>??
????</property>??
</bean>??
?
?
前臺調用:
Js代碼??
<script?type="text/javascript">??
$(function()?{??
????jQuery.ajax({??
????????url?:?'index.json',??
????????contentType?:?"application/json",//application/xml??
????????processData?:?true,//contentType為xml時,些值為false??
????????dataType?:?"json",//json--返回json數據類型;xml--返回xml??
????????data?:?{??
????????????tag?:?'tag123'??
????????},??
????????success?:?function(data)?{??
????????????document.write(data.applyList.length);??
????????},??
????????error?:?function(e)?{??
????????????document.write('error');??
????????}??
????});??
});??
</script>??
?
后臺Controller:
?
Java代碼??
@RequestMapping(value?=?"/index.json")??
public?ModelAndView?queryAppliesForJson()?{??
???????ModelAndView?mav?=?new?ModelAndView("query_list_paginition");??
????List<ChangeApply>?applyList?=?changeApplyService.findAllApplies();??
????mav.addObject("applyList",?applyList);??
???????return?mav;??
}??
?
這么前臺JavaScript會接收到JSON字符串。 而且這樣設計也符合spring提倡的 RESTful 風格。我們在任何地方只要發出對應的請求,服務器就會給我們返回需要的數據。
?
....陸續增加中,下次我可能會寫從源碼角度去分析。
轉載于:https://my.oschina.net/liangzhenghui/blog/408358
總結
以上是生活随笔為你收集整理的解析mediaTypes+viewResolvers+viewResolvers的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java时间比较大小_Go、Java 和
- 下一篇: springmvc传递数组参数