功能,使用 Spring 3 MVC HttpMessageConverter 功能構建 RESTful web 服務

 2023-11-19 阅读 27 评论 0

摘要:Spring,構建 Java? 平臺和 Enterprise Edition (Java EE) 應用程序的著名框架,現在在其模型-視圖-控制器(Model-View-Controller ,MVC)層支持具象狀態傳輸 (REST)。RESTful web 服務根據客戶端請求生成多個具象(representations&#

Spring,構建 Java? 平臺和 Enterprise Edition (Java EE) 應用程序的著名框架,現在在其模型-視圖-控制器(Model-View-Controller ,MVC)層支持具象狀態傳輸 (REST)。RESTful web 服務根據客戶端請求生成多個具象(representations)很重要。在本篇文章中,學習使用HttpMessageConverter?生成多個具象。代碼示例展示如何使用?RestTemplate?和HttpMessageConverter?與服務進行通信。此外,還將學習如何使用 Spring API 和注釋構建 RESTful web 服務,生成常見具象,比如 ATOM Feed、XML 和 JavaScript Object Notation (JSON)。

簡介

隨附文章,“使用 Spring 3 構建 RESTful web 服務”(參見?參考資料),介紹了使用 Spring 構建 RESTful web 服務的方式。還解釋了如何使用?ContentNegotiatingViewResolver?生成多個具象,這是 RESTful web 服務的一個重要功能。本文還闡述了使用?HttpMessageConverter?生成多個具象的另一種方式,并且本文中的示例展示了如何使用?RestTemplate?和?HttpMessageConverter?與服務進行通信。

Spring MVC 中的 REST 支持

本部分提供了支持 RESTful web 服務的主要 Spring 功能(或注釋)的概述。

@Controller
使用?@Controller?注釋對將成為 MVC 中控制器的類進行注釋并處理 HTTP 請求。
@RequestMapping
使用?@RequestMapping?注釋對函數進行注釋,該函數處理某些 HTTP 方法、URI 或 HTTP 頭。此注釋是 Spring REST 支持的關鍵。可以更改method?參數以處理其他 HTTP 方法。

例如:

@RequestMapping(method=RequestMethod.GET, value="/emps", 
headers="Accept=application/xml, application/json")
@PathVariable
使用?@PathVariable?注釋可將 URI 中的路徑變量作為參數插入。

例如:

@RequestMapping(method=RequestMethod.GET, value="/emp/{id}")
public ModelAndView getEmployee(@PathVariable String id) { … }
其他有用的注釋
使用?@RequestParam?將 URL 參數插入方法中。

功能?使用?@RequestHeader?將某一 HTTP 頭插入方法中。

使用?@RequestBody?將 HTTP 請求正文插入方法中。

使用?@ResponseBody?將內容或對象作為 HTTP 響應正文返回。

使用?HttpEntity<T>?將它自動插入方法中,如果將它作為參數提供。

使用?ResponseEntity<T>?返回具有自定義狀態或頭的 HTTP 響應。

例如:

public @ResponseBody Employee getEmployeeBy(@RequestParam("name") 
String name, @RequestHeader("Accept") String accept, @RequestBody String body) {…} 
public ResponseEntity<String> method(HttpEntity<String> entity) {…}

HTML獲取JAVA后端發來的數據、參見 Spring 文檔(參見?參考資料) 獲得可插入方法中的支持注釋或對象的完整列表。

多具象支持

使用不同 MIME 類型表示同一資源是 RESTful web 服務的一個重要方面。通常,可以使用具有不同 "accept" HTTP 頭的同一 URI 提取具有不同表示的資源。還可以使用不同的 URI 或具有不同請求參數的 URI。

“使用 Spring 3 構建 RESTful web 服務”(參見?參考資料)介紹了?ContentNegotiatingViewResolver,可以挑選不同的視圖解析器處理同一 URI(具有不同的 accept 頭)。因此,ContentNegotiatingViewResolver?可用于生成多個具象。

還有另一種方式可生成多具象 — 將?HttpMessageConverter?和?c@ResponseBody?注釋結合起來使用。使用這種方法無需使用視圖技術。

HttpMessageConverter

HTTP 請求和響應是基于文本的,意味著瀏覽器和服務器通過交換原始文本進行通信。但是,使用 Spring,controller 類中的方法返回純 'String' 類型和域模型(或其他 Java 內建對象)。如何將對象序列化/反序列化為原始文本?這由?HttpMessageConverter?處理。Spring 具有捆綁實現,可滿足常見需求。表 1 顯示了一些示例。

表 1. HttpMessageConverter 示例
使用......您可以......
StringHttpMessageConverter從請求和響應讀取/編寫字符串。默認情況下,它支持媒體類型 text/* 并使用文本/無格式內容類型編寫。
FormHttpMessageConverter從請求和響應讀取/編寫表單數據。默認情況下,它讀取媒體類型 application/x-www-form-urlencoded 并將數據寫入 MultiValueMap<String,String>。
MarshallingHttpMessageConverter使用 Spring 的 marshaller/un-marshaller 讀取/編寫 XML 數據。它轉換媒體類型為 application/xml 的數據。
MappingJacksonHttpMessageConverter使用 Jackson 的?ObjectMapper?讀取/編寫 JSON 數據。它轉換媒體類型為 application/json 的數據。
AtomFeedHttpMessageConverter使用 ROME 的 Feed API 讀取/編寫 ATOM 源。它轉換媒體類型為 application/atom+xml 的數據。
RssChannelHttpMessageConverter使用 ROME 的 feed API 讀取/編寫 RSS 源。它轉換媒體類型為 application/rss+xml 的數據。

構建 RESTful web 服務

在此部分中,學習構建可生成多個具象的簡單 RESTful web 服務。示例應用程序中使用的一些資源在 “使用 Spring 3 構建 RESTful web 服務”(參見?參考資料)中構建。還可以?下載?示例代碼。

Spring MVC、首先,您必須配置?HttpMessageConverter。要生成多個具象,自定義幾個?HttpMessageConverter?實例,以將對象轉換為不同的媒體類型。此部分包括 JSON、ATOM 和 XML 媒體類型。

JSON

從最簡單的示例開始。JSON 是一個輕量型的數據交換格式,人們可輕松地進行讀取和編寫。清單 1 顯示了配置 JSON converter 的代碼。

清單 1. 配置 rest-servlet.xml 中的 HttpMessageConverter
  <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"><property name="messageConverters"><list><ref bean="marshallingConverter" /><ref bean="atomConverter"  /><ref bean="jsonConverter" /></list></property></bean>

在配置中,注冊了 3 個轉換程序。MappingJacksonHttpMessageConverter?用于將對象轉換為 JSON,反之亦然。此內置轉換程序使用 Jackson 的?ObjectMapper?將 JSON 映射到 JavaBean,因此您必須將下列 Jackson JAR 文件添加到類路徑。

  • org.codehaus.jackson.jar
  • org.codehaus.jackson.mapper.jar

下一步是編寫一個方法,處理請求 JSON 具象的請求。清單 2 顯示了詳細信息。

清單 2. 處理在 EmployeeController 中定義的 JSON 請求
@RequestMapping(method=RequestMethod.GET, value="/emp/{id}", headers="Accept=application/xml, application/json")public @ResponseBody Employee getEmp(@PathVariable String id) {Employee e = employeeDS.get(Long.parseLong(id));return e;}
@RequestMapping(method=RequestMethod.GET, value="/emps", headers="Accept=application/xml, application/json")public @ResponseBody EmployeeList getAllEmp() {List<Employee> employees = employeeDS.getAll();EmployeeList list = new EmployeeList(employees);return list;}

@ResponseBody?注釋用于將返回對象(Employee?或?EmployeeList)變為響應的正文內容,將使用?MappingJacksonHttpMessageConverter?將其映射到 JSON。

使用?HttpMessageConverter?和?@ResponseBody,您可以實現多個具象,而無需包含 Spring 的視圖技術 — 這是使用ContentNegotiatingViewResolver?所不具有的一個優勢。

servlet返回json給前端、現在您可以使用 CURL 或 REST Client Firefox 插件調用請求。記住添加一個 HTTP 頭:Accept=application/json。清單 3 以 JSON 格式顯示了所需的響應。

清單 3. getEmp() 和 getAllEmp() 的 JSON 結果
Response for /rest/service/emp/1
{"id":1,"name":"Huang Yi Ming","email":"huangyim@cn.ibm.com"}Response for /rest/service/emps
{"count":2,
"employees":[
{"id":1,"name":"Huang Yi Ming","email":"huangyim@cn.ibm.com"},
{"id":2,"name":"Wu Dong Fei","email":"wudongf@cn.ibm.com"}
]}

XML

Spring 的內置轉換程序?MarshallingHttpMessageConverter?用于在對象和 XML (OXM) 之間進行映射。本示例使用 JAXB 2 作為轉換程序的 marshaller/un-marshaller。清單 4 顯示了配置。

清單 4. 配置 MarshallingHttpMessageConverter
  <bean id="marshallingConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"><constructor-arg ref="jaxbMarshaller" /><property name="supportedMediaTypes" value="application/xml"/></bean>......<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"><property name="classesToBeBound"><list><value>dw.spring3.rest.bean.Employee</value><value>dw.spring3.rest.bean.EmployeeList</value></list></property></bean>

了解 JAXB 2 不能很好地支持 java.util.List<T> 到 XML 的映射很重要。常用實踐是為對象集添加一個包裝類。參見 “使用 Spring 3 構建 RESTful web 服務”(參見?參考資料)或?下載?源代碼,了解此 JAXB 注釋類的詳細信息。

在處理請求的控制器中的方法如何?回顧一下?清單 2?中的代碼。發現在此處不需要添加任何代碼一點也不奇怪。您只需要在?Accept?頭中添加另一個支持的媒體類型,如下所示。

headers=”Accept=application/json, application/xml”

轉換程序將對象正確地映射到請求的類型(JSON 或 XML)。清單 5 顯示了請求 application/xml 具象的理想結果。

清單 5. getEmp() 和 getAllEmp() 的 XML 結果
Response for /rest/service/emp/1
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><employee><email>huangyim@cn.ibm.com</email><id>1</id><name>Huang Yi Ming</name></employee>
Response for /rest/service/emps
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><employees><count>2</count><employee><email>huangyim@cn.ibm.com</email><id>1</id><name>Huang Yi Ming</name></employee><employee><email>wudongf@cn.ibm.com</email><id>2</id><name>Wu Dong Fei</name></employee></employees>

ATOM 源

ATOM 源是另一種在 RESTful web 服務中交換數據的常見格式。Atom 源文檔是 Atom 源(包括有關源及與其相關的所有或部分項的元數據)的具象。其根是?atom:feed?元素。還有一個 ATOM Publish Protocol (APP) 定義交換格式和行為。(定義 ATOM 和 APP 格式不在本文的討論范圍內。參見?參考資料?了解更多信息。)

servlet中session的用法,本示例使用?AtomFeedHttpMessageConverter?轉換 ATOM 源,利用 ROME ATOM API。因此,您必須在類路徑中包含 JAR 文件 sun.syndication.jar。清單 6 顯示了此轉換程序的配置。

清單 6. 配置 AtomFeedHttpMessageConverter
  <bean id="atomConverter" class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter"><property name="supportedMediaTypes" value="application/atom+xml" /></bean>

清單 7 顯示了處理 ATOM 請求和源生成的代碼。

清單 7. EmployeeController & AtomUtil 類中的 getEmpFeed()
@RequestMapping(method=RequestMethod.GET, value="/emps", headers="Accept=application/atom+xml")
public @ResponseBody Feed getEmpFeed() {List<Employee> employees = employeeDS.getAll();return AtomUtil.employeeFeed(employees, jaxb2Mashaller);
}

AtomUtil.java
public static Feed employeeFeed(List<Employee> employees, Jaxb2Marshaller marshaller) {Feed feed = new Feed();feed.setFeedType("atom_1.0");feed.setTitle("Employee Atom Feed");List<Entry> entries = new ArrayList<Entry>();for(Employee e : employees) {StreamResult result = new StreamResult(new ByteArrayOutputStream());marshaller.marshal(e, result);String xml = result.getOutputStream().toString();Entry entry = new Entry();entry.setId(Long.valueOf(e.getId()).toString());entry.setTitle(e.getName());Content content = new Content();content.setType(Content.XML);content.setValue(xml);List<Content> contents = new ArrayList<Content>();contents.add(content);entry.setContents(contents);entries.add(entry);}feed.setEntries(entries);return feed; }

在上述代碼中,注意:

  • getEmpFeed()?方法將同一 URI 處理為?getAllEmp(),但具有不同的?Accept?頭。
  • 使用?employeeFeed()?方法,您可以將?Employee?對象解析為 XML,然后將其添加到源項的?<content>?元素。

清單 8 顯示了請求 URI /rest/service/emps 的 application/atom+xml 具象時的輸出。

清單 8. 請求 application/atom+xml 時的 /rest/service/emps 輸出
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Employee Atom Feed</title><entry><title>Huang Yi Ming</title><id>1</id><content type="xml"><employee><email>huangyim@cn.ibm.com</email><id>1</id><name>Huang Yi Ming</name></employee></content>
</entry><entry><title>Wu Dong Fei</title><id>2</id><content type="xml"><employee><email>wudongf@cn.ibm.com</email><id>2</id><name>Wu Dong Fei</name></employee></content></entry></feed>

實現 POST、PUT 和 DELETE

目前為止,示例已實現了幾個處理 HTTP?GET?方法的方法。清單 9 顯示了?POSTPUT?和?DELETE?方法的實現。

清單 9. EmployeeController 中的 POST、PUT 和 DELETE 方法
@RequestMapping(method=RequestMethod.POST, value="/emp")
public @ResponseBody Employee addEmp(@RequestBody Employee e) {
employeeDS.add(e);
return e;
}@RequestMapping(method=RequestMethod.PUT, value="/emp/{id}")
public @ResponseBody Employee updateEmp(@RequestBody Employee e, @PathVariable String id) {
employeeDS.update(e);
return e;
}@RequestMapping(method=RequestMethod.DELETE, value="/emp/{id}")
public @ResponseBody void removeEmp(@PathVariable String id) {
employeeDS.remove(Long.parseLong(id));
}

@RequestBody?注釋在?addEmp()?和?updateEmp()?方法中使用。它接收 HTTP 請求正文并試圖使用注冊的?HttpMessageConverter?將其轉換為對象類。在下一部分中,您將使用?RestTemplate?與這些服務進行通信。

使用 RestTemplate 與 REST 服務進行通信

“使用 Spring 3 構建 RESTful web 服務”(參見?參考資料)介紹了如何使用 CURL 和 REST 客戶端測試 REST 服務。從編程水平上講,Jakarta Commons HttpClient 通常用于完成此測試(但這不在本文的討論范圍中)。您還可以使用名為?RestTemplate?的 Spring REST 客戶端。從概念上講,它與 Spring 中的其他模板類相似,比如?JdbcTemplate?和?JmsTemplate

RestTemplate?還使用?HttpMessageConverter。您可以將對象類傳入請求并使轉換程序處理映射。

配置 RestTemplate

清單 10 顯示了?RestTemplate?的配置。它還使用之前介紹的 3 個轉換程序。

清單 10. 配置 RestTemplate
  <!-- Client --><bean id="restTemplate" class="org.springframework.web.client.RestTemplate"><property name="messageConverters"><list><ref bean="marshallingConverter" /><ref bean="atomConverter"  /><ref bean="jsonConverter" /></list></property></bean>

本文中的示例僅使用了一些可簡化服務器之間通信的方法。RestTemplate支持其他方法,包括:

  • exchange:使用請求正文執行一些 HTTP 方法并獲得響應。
  • getForObject:執行 HTTP?GET?方法并將響應作為對象獲得。
  • postForObject:使用特定請求正文執行 HTTP?POST?方法。
  • put:使用特定請求正文執行 HTTP?PUT?方法。
  • delete:執行 HTTP?DELETE方法以獲得特定 URI。

代碼示例

下列代碼示例幫助闡述如何使用?RestTemplate。參見 RestTemplate API(參見?參考資料)獲得使用的 API 的詳細說明。

清單 11 顯示如何將頭添加到請求中,然后調用請求。使用?MarshallingHttpMessageConverter?您可以獲得響應并將其轉換為類型類。可以使用不同的媒體類型測試其他具象。

清單 11. XML 具象請求
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<EmployeeList> response = restTemplate.exchange(
"http://localhost:8080/rest/service/emps", 
HttpMethod.GET, entity, EmployeeList.class);
EmployeeListingemployees = response.getBody();
// handle the employees

清單 12 顯示了如何將新員工發布到服務器。服務器端服務?addEmp()?可接受媒體類型為 application/xml 和 application/json 的數據。

清單 12. 發布新員工
Employee newEmp = new Employee(99, "guest", "guest@ibm.com");
HttpEntity<Employee> entity = new HttpEntity<Employee>(newEmp);
ResponseEntity<Employee> response = restTemplate.postForEntity(
"http://localhost:8080/rest/service/emp", entity, Employee.class);
Employee e = response.getBody();
// handle the employee

清單 13 顯示了如何 PUT 修改的員工以更新舊員工。它還顯示了可用作請求 URI 占位符({id})的功能。

清單 13. PUT 以更新員工
Employee newEmp = new Employee(99, "guest99", "guest99@ibm.com");
HttpEntity<Employee> entity = new HttpEntity<Employee>(newEmp);
restTemplate.put("http://localhost:8080/rest/service/emp/{id}", entity, "99");

清單 14 顯示了如何 DELETE 現有員工。

清單 14. DELETE 現有員工
restTemplate.delete("http://localhost:8080/rest/service/emp/{id}", "99");

結束語

在本篇文章中,您學習了 Spring 3 中引入的?HttpMessageConverter。它提供了對多具象的客戶端和服務器端支持。使用提供的?源代碼,您可以探索本文中的?HttpMessageConverter?實現和使用 “使用 Spring 3 構建 RESTful web 服務” 中的?ContentNegotiatingViewResolver?實現之間的差異。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/184117.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息