RestTemplate如何使用JSON發(fā)送Post請求
我們說下如何使用Spring的 RestTemplate調(diào)用post請求,發(fā)送json內(nèi)容。
1. 定義服務(wù)端web接口
1.1. 定義業(yè)務(wù)接口
先定義Person實(shí)體類表示post請求的數(shù)據(jù):
public class Person { private Integer id; private String name; // standard constructor, getters, setters }
再定義PersonService接口并實(shí)現(xiàn)兩個(gè)方法,關(guān)聯(lián)使用Person類:
public interface PersonService { public Person saveUpdatePerson(Person person); public Person findPersonById(Integer id); }
這些方法的實(shí)現(xiàn)僅返回對象,不再具體討論,讓我們聚焦web層。
1.2. 定義業(yè)務(wù)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請求數(shù)據(jù),為此,在兩個(gè)方法的@PostMapping中增加consumes屬性并設(shè)置值為“application/json”。
類似的,設(shè)置produces屬性值為“application/json”,為了告訴Spring我們希望響應(yīng)數(shù)據(jù)也是json格式。
person參數(shù)前的注解@RequestBody,表明person對象和http請求體綁定。
最后兩個(gè)方法返回Person對象會綁定至http響應(yīng)體。
如果給api類增加@RestController注解,則所有api方法都帶有@ResponseBody注解。
2. 使用RestTemplate
現(xiàn)在寫幾個(gè)單元測試,測試Person rest api。
我們嘗試使用RestTemplate發(fā)送post請求給Person api,
共三個(gè)方法:
postForObject
postForEntity
and postForLocation
開始實(shí)現(xiàn)單元測試之前,先定義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對象轉(zhuǎn)換JSON字符串為JSONNode對象:
private final ObjectMapper objectMapper = new ObjectMapper();
我們前面提到,post請求數(shù)據(jù)使用json格式。
因此,在請求頭中增加 Content-Type屬性,值為APPLICATION_JSON 。
Spring的 HttpHeaders提供不同的方法訪問請求頭信息。
這里需要通過setContentType方法設(shè)置Content-Type 屬性值為 application/json。然后給請求對象附加頭信息。
2.1. 使用postForObject方法發(fā)送json
RestTemplate的postForObject 方法post對象給uri并返回新的對象。返回值自動(dòng)被轉(zhuǎn)換為responseType參數(shù)指定的類型,這里是字符串。
我們的需求是發(fā)送post請求至person api,創(chuàng)建新的Person對象并響應(yīng)中包括新創(chuàng)建的對象。
首先,基于personJsonObject構(gòu)建HttpEntity 類型的請求對象,并在請求頭中指定Content-Type。
然后調(diào)用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() 方法返回字符串響應(yīng)體。
我們也可以通過設(shè)置responseType參數(shù)使其返回Person類型:
Person person = restTemplate.postForObject(createPersonUrl, request, Person.class); assertNotNull(person); assertNotNull(person.getName());
實(shí)際上我們的請求處理方法(createPersonUrl 參數(shù)匹配的)產(chǎn)生json格式的響應(yīng)體,但對postForObject 方法沒有限制,通過設(shè)置responseType參數(shù)可以自動(dòng)轉(zhuǎn)換為響應(yīng)的java類型。
2.2. 使用postForEntity發(fā)送json
相比于postForObject()方法, postForEntity() 返回響應(yīng)體為 ResponseEntity 類型,其他兩個(gè)方法功能一致。
我們的需求是發(fā)送post請求至person api,創(chuàng)建新的Person對象并返回ResponseEntity類型響應(yīng)體。
可以使用postForEntity實(shí)現(xiàn)該功能:
@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()); }
類似的,也可以設(shè)置responseType 參數(shù)轉(zhuǎn)換響應(yīng)體為Java類型。
這里我們能夠返回響應(yīng)體為ResponseEntity,也能返回響應(yīng)為 ResponseEntity 對象,只要設(shè)置responseType參數(shù)為 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在響應(yīng)中設(shè)置Location 頭信息:
response.setHeader("Location", ServletUriComponentsBuilder.fromCurrentContextPath() .path("/findPerson/" + person.getId()).toUriString());
現(xiàn)在我們需要實(shí)現(xiàn)更新person對象后接收返回帶有Location頭信息的響應(yīng),使用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. 總結(jié)
本文講解了RestTemplate 如何發(fā)送json類型的post請求,共三種方法應(yīng)用與不同場景。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決myBatis中openSession()自動(dòng)提交的問題
在學(xué)習(xí)MySQL過程中,發(fā)現(xiàn)插入操作自動(dòng)提交,問題原因可能是myBatis中的openSession()方法設(shè)置了自動(dòng)提交,或者是MySQL的默認(rèn)引擎設(shè)置為不支持事務(wù)的MyISAM,解決辦法包括更改myBatis的提交設(shè)置或?qū)ySQL表的引擎改為InnoDB2024-09-09springboot集成redis哨兵集群的實(shí)現(xiàn)示例
本文主要介紹了springboot集成redis哨兵集群的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08mybatis-plus的SafetyEncryptProcessor安全加密處理示例解析
這篇文章主要為大家介紹了mybatis-plus的SafetyEncryptProcessor安全加密處理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08Java實(shí)現(xiàn)curl調(diào)用帶參數(shù)接口方法
本文主要介紹了Java實(shí)現(xiàn)curl調(diào)用帶參數(shù)接口方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04淺談SpringBoot中的@Conditional注解的使用
這篇文章主要介紹了淺談SpringBoot中的@Conditional注解的使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-04-04