RestTemplate如何使用JSON發(fā)送Post請求
我們說下如何使用Spring的 RestTemplate調用post請求,發(fā)送json內容。
1. 定義服務端web接口
1.1. 定義業(yè)務接口
先定義Person實體類表示post請求的數據:
public class Person { private Integer id; private String name; // standard constructor, getters, setters }
再定義PersonService接口并實現兩個方法,關聯使用Person類:
public interface PersonService { public Person saveUpdatePerson(Person person); public Person findPersonById(Integer id); }
這些方法的實現僅返回對象,不再具體討論,讓我們聚焦web層。
1.2. 定義業(yè)務REST API
下面我們?yōu)镻erson類定義簡單的Rest api:
@PostMapping(value = "/createPerson", consumes = "application/json", produces = "application/json") public Person createPerson(@RequestBody Person person) { return personService.saveUpdatePerson(person); } @PostMapping(value = "/updatePerson", consumes = "application/json", produces = "application/json") public Person updatePerson(@RequestBody Person person, HttpServletResponse response) { response.setHeader("Location", ServletUriComponentsBuilder.fromCurrentContextPath() .path("/findPerson/" + person.getId()).toUriString()); return personService.saveUpdatePerson(person); }
我們需要發(fā)送json格式post請求數據,為此,在兩個方法的@PostMapping中增加consumes屬性并設置值為“application/json”。
類似的,設置produces屬性值為“application/json”,為了告訴Spring我們希望響應數據也是json格式。
person參數前的注解@RequestBody,表明person對象和http請求體綁定。
最后兩個方法返回Person對象會綁定至http響應體。
如果給api類增加@RestController注解,則所有api方法都帶有@ResponseBody注解。
2. 使用RestTemplate
現在寫幾個單元測試,測試Person rest api。
我們嘗試使用RestTemplate發(fā)送post請求給Person api,
共三個方法:
postForObject
postForEntity
and postForLocation
開始實現單元測試之前,先定義setup方法初始化單元測試方法中使用的對象:
@BeforeClass public static void runBeforeAllTestMethods() { createPersonUrl = "http://localhost:8082/spring-rest/createPerson"; updatePersonUrl = "http://localhost:8082/spring-rest/updatePerson"; restTemplate = new RestTemplate(); headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); ObjectNode personJsonObject = objectMapper.createObjectNode(); personJsonObject.put("id", 1); personJsonObject.put("name", "John"); }
除了setup方法,還要引入ObjectMapper對象轉換JSON字符串為JSONNode對象:
private final ObjectMapper objectMapper = new ObjectMapper();
我們前面提到,post請求數據使用json格式。
因此,在請求頭中增加 Content-Type屬性,值為APPLICATION_JSON 。
Spring的 HttpHeaders提供不同的方法訪問請求頭信息。
這里需要通過setContentType方法設置Content-Type 屬性值為 application/json。然后給請求對象附加頭信息。
2.1. 使用postForObject方法發(fā)送json
RestTemplate的postForObject 方法post對象給uri并返回新的對象。返回值自動被轉換為responseType參數指定的類型,這里是字符串。
我們的需求是發(fā)送post請求至person api,創(chuàng)建新的Person對象并響應中包括新創(chuàng)建的對象。
首先,基于personJsonObject構建HttpEntity 類型的請求對象,并在請求頭中指定Content-Type。
然后調用postForObject 方法發(fā)送json請求體:
@Test public void givenDataIsJson_whenDataIsPostedByPostForObject_thenResponseBodyIsNotNull() throws IOException { HttpEntity<String> request = new HttpEntity<String>(personJsonObject.toString(), headers); String personResultAsJsonStr = restTemplate.postForObject(createPersonUrl, request, String.class); JsonNode root = objectMapper.readTree(personResultAsJsonStr); assertNotNull(personResultAsJsonStr); assertNotNull(root); assertNotNull(root.path("name").asText()); }
該示例中 postForObject() 方法返回字符串響應體。
我們也可以通過設置responseType參數使其返回Person類型:
Person person = restTemplate.postForObject(createPersonUrl, request, Person.class); assertNotNull(person); assertNotNull(person.getName());
實際上我們的請求處理方法(createPersonUrl 參數匹配的)產生json格式的響應體,但對postForObject 方法沒有限制,通過設置responseType參數可以自動轉換為響應的java類型。
2.2. 使用postForEntity發(fā)送json
相比于postForObject()方法, postForEntity() 返回響應體為 ResponseEntity 類型,其他兩個方法功能一致。
我們的需求是發(fā)送post請求至person api,創(chuàng)建新的Person對象并返回ResponseEntity類型響應體。
可以使用postForEntity實現該功能:
@Test public void givenDataIsJson_whenDataIsPostedByPostForEntity_thenResponseBodyIsNotNull() throws IOException { HttpEntity<String> request = new HttpEntity<String>(personJsonObject.toString(), headers); ResponseEntity<String> responseEntityStr = restTemplate. postForEntity(createPersonUrl, request, String.class); JsonNode root = objectMapper.readTree(responseEntityStr.getBody()); assertNotNull(responseEntityStr.getBody()); assertNotNull(root.path("name").asText()); }
類似的,也可以設置responseType 參數轉換響應體為Java類型。
這里我們能夠返回響應體為ResponseEntity,也能返回響應為 ResponseEntity 對象,只要設置responseType參數為 Person.class:
ResponseEntity<Person> responseEntityPerson = restTemplate. postForEntity(createPersonUrl, request, Person.class); assertNotNull(responseEntityPerson.getBody()); assertNotNull(responseEntityPerson.getBody().getName());
2.3. 使用postForLocation發(fā)送json
與postForObject 和 postForEntity 方法類型, postForLocation 也發(fā)送post請求至特定uri并創(chuàng)建新的對象。
唯一的差異是返回值為Location頭信息。
前面updatePerson rest api在響應中設置Location 頭信息:
response.setHeader("Location", ServletUriComponentsBuilder.fromCurrentContextPath() .path("/findPerson/" + person.getId()).toUriString());
現在我們需要實現更新person對象后接收返回帶有Location頭信息的響應,使用postForLocation 方法:
@Test public void givenDataIsJson_whenDataIsPostedByPostForLocation_thenResponseBodyIsTheLocationHeader() throws JsonProcessingException { HttpEntity<String> request = new HttpEntity<String>(personJsonObject.toString(), headers); URI locationHeader = restTemplate.postForLocation(updatePersonUrl, request); assertNotNull(locationHeader); }
3. 總結
本文講解了RestTemplate 如何發(fā)送json類型的post請求,共三種方法應用與不同場景。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
解決myBatis中openSession()自動提交的問題
在學習MySQL過程中,發(fā)現插入操作自動提交,問題原因可能是myBatis中的openSession()方法設置了自動提交,或者是MySQL的默認引擎設置為不支持事務的MyISAM,解決辦法包括更改myBatis的提交設置或將MySQL表的引擎改為InnoDB2024-09-09mybatis-plus的SafetyEncryptProcessor安全加密處理示例解析
這篇文章主要為大家介紹了mybatis-plus的SafetyEncryptProcessor安全加密處理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08淺談SpringBoot中的@Conditional注解的使用
這篇文章主要介紹了淺談SpringBoot中的@Conditional注解的使用,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-04-04