restful服務中一個重要的特性就是一種資源可以有多種表現形式,在springmvc中可以使用ContentNegotiatingViewResolver這個視圖解析器來實現這種方式。
描述資源的三種形式
一、使用擴展名
http://localhost:8080/test/user.xml 以xml格式呈現
http://localhost:8080/test/user.json 以json格式呈現
http://localhost:8080/test/user 以默認視圖呈現,如jsp
二、使用http request header的Accept
GET /user HTTP/1.1
Accept:application/xml 請求時設置返回形式是xml,如使用ajax請求,則需要設置contentType:application/xml
GET /user HTTP/1.1
Accept:application/json 請求時設置返回形式是json,如使用ajax請求,則需要設置contentType:application/json
三、使用參數
http://localhost:8080/test/user?format=json
http://localhost:8080/test/user?format=xml
上面了解了同一種資源的三種呈現方式,即json、xml、jsp,那麼我們要如何使用ContentNegotiatingViewResolver類配置,使客戶端請求的方式不同,返回同一種資源的三種方式呢?
ContentNegotiatingViewResolver配置
ContentNegotiatingViewResolver是視圖解析器,我們在使用jsp這個視圖的時候也配置了一個視圖解析器InternalResourceViewResolver,他們都是視圖解析器,後者著重在配置一個默認的視圖解析即jsp;ContentNegotiatingViewResolver本身不會解析,他會分配其他的viewResolver去解析,並選擇一個看起來像是客戶端請求需要返回的一種 View 返回。
下面是ContentNegotiatingViewResolver的具體配置
<!--springmvc中根據後綴不同返回不同格式的配置 如,XXX.json 返回json格式 XXX.xml 返回xml格式 xxx 返回jsp --> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <!--這裡是解析器的執行順序,如果有多個的話,配置的數值越小,則越早執行--> <property name="order" value="1" /> <!-- 這裡是是否啟用擴展名支持,默認就是true 例如 /user/{userid}.json --> <property name="favorPathExtension" value="true"></property> <!--這裡是是否啟用參數支持,默認就是true 例如 /user/{userid}?format=json --> <property name="favorParameter" value="false"></property> <!--這裡是否忽略掉accept header,默認就是false 例如 GET /user HTTP/1.1 Accept:application/json --> <property name="ignoreAcceptHeader" value="true"></property> <!-- 這裡是擴展名到mimeType的映射, 例如 /user/{userid}.json 中的 .json 就會映射到 application/json --> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </map> </property> <!--視圖--> <property name="defaultViews"> <list> <!--json視圖--> <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"></bean> <!--xml視圖--> <bean class="org.springframework.web.servlet.view.xml.MarshallingView" <constructor-arg> <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound"> <list> <value>com.cn.my.entity.Course</value> <value>com.cn.my.entity.CourseList</value> </list> </property> </bean> </constructor-arg> </bean> </list> </property> </bean>
order:如果存在多個viewResolver則order值小的被使用,如果沒有合適的viewResolver則會使用另外的;
favorPathExtension:是否支持擴展名,默認為true(支持),擴展名指的xxx.json、xxx.xml等形式
favorParameter:是否啟用參數支持,默認為true(支持),即xxx?format=json、xxx?format=xml等形式,這裡的參數名默認為format,可以通過配置改變。
ignoreAcceptHeader:是否忽略accept header,默認是false(不忽略),即請求時指定的contentType:application/json等,由於我這裡要使用擴展名的形式返回,所以把另外兩項都關閉了,可視不同情況,使用不同設置;
mediaTypes:配置擴展名到mimeType的映射,這裡配置了json和xml的映射;
defaultViews:配置視圖,這裡配置了json和xml的視圖,json使用的jackson;
最後,我還配置一個另外一個視圖解析器,InternalResourceViewResolver,
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="order" value="2" /> <property name="prefix" value="/WEB-INF/jsp/"></property> <property name="suffix" value=".jsp"></property> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> </bean>
這是jsp的視圖解析器,order屬性配置為了2,在無法匹配到json、xml的情況下,會返回jsp的視圖。
下面是controller的方法
package com.cn.my.controllor; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import com.cn.my.entity.Course; import com.cn.my.entity.CourseList; @Controller @RequestMapping("/mul") public class MultiView { @RequestMapping("/simple/{coursId}") public String method1(@PathVariable("coursId") String coursId,ModelMap model){ Course c=new Course(); c.setId(coursId); c.setContent("這是測試內容"); c.setName("李四"); model.put("course", c); return "course"; } }
這裡使用的restful服務中的uri的格式,用到了@PathVariable注解,這裡方法返回的String,且沒有@ResponseBody注解,在前邊的返回json一文中有返回json的配置,需要@ResponseBody注解,詳細的可以參看前邊,同時在方法參數中有ModelMap,為什麼這裡要返回一個字符串呢,目的是為了統一,我們知道如果要返回到jsp視圖,那麼這裡要返回的一個代表邏輯視圖名的字符串,為了使三種方式統一,這裡返回的是字符串,如果不返回到jsp也可以返回一個實際的對象。
下面看測試結果,
請求:http://localhost:8081/springmvc/mul/simple2/1212.json
請求:http://localhost:8081/springmvc/mul/simple2/1212.xml
請求:http://localhost:8081/springmvc/mul/simple2/1212
最後一個jsp的視圖,本來是要在jsp頁面中輸出內容的,我這裡沒做,只是輸出了一段話。請諒解!
從上邊的測試結果來看,我們分別使用了三種不同的請求方式去請求同一個資源,返回了各自的形式,這種方式很適合用在不同的系統調用同一個系統時,可能別的系統處理數據的方式不一樣,我們使用上邊的配置可以實現一套代碼,返回不同的形式。
最後
在配置默認的jsp解析器的時候也可以照下面的配置方式,
<!--springmvc中根據後綴不同返回不同格式的配置 如,XXX.json 返回json格式 XXX.xml 返回xml格式 xxx 返回jsp --> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <!--這裡是解析器的執行順序,如果有多個的話,配置的數值越小,則越早執行--> <property name="order" value="1" /> <!-- 這裡是是否啟用擴展名支持,默認就是true 例如 /user/{userid}.json --> <property name="favorPathExtension" value="true"></property> <!--這裡是是否啟用參數支持,默認就是true 例如 /user/{userid}?format=json --> <property name="favorParameter" value="false"></property> <!--這裡是否忽略掉accept header,默認就是false 例如 GET /user HTTP/1.1 Accept:application/json --> <property name="ignoreAcceptHeader" value="true"></property> <!-- 這裡是擴展名到mimeType的映射, 例如 /user/{userid}.json 中的 .json 就會映射到 application/json --> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </map> </property> <!--視圖解析器--> <property name="viewResolvers"> <list> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"></property> <property name="suffix" value=".jsp"></property> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> </bean> </list> </property> <!--視圖--> <property name="defaultViews"> <list> <!--json視圖--> <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"></bean> <!--xml視圖--> <bean class="org.springframework.web.servlet.view.xml.MarshallingView" <constructor-arg> <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound"> <list> <value>com.cn.my.entity.Course</value> <value>com.cn.my.entity.CourseList</value> </list> </property> </bean> </constructor-arg> </bean> </list> </property> </bean>
聲明:我這裡的環境是spring4.1
參考:
http://blog.csdn.net/z69183787/article/details/41654603
上邊有很好的解釋。
有不正之處歡迎指正,謝謝!