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
上邊有很好的解釋。
有不正之處歡迎指正,謝謝!