RestTemplate如何使用JSON发送Post请求

 更新时间:2023年09月27日 10:17:53   作者:梦想画家  
这篇文章主要介绍了RestTemplate如何使用JSON发送Post请求问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

我们说下如何使用Spring的 RestTemplate调用post请求,发送json内容。

1. 定义服务端web接口

1.1. 定义业务接口

先定义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. 定义业务REST API

下面我们为Person类定义简单的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);
}

我们需要发送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发送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方法发送json

RestTemplate的postForObject 方法post对象给uri并返回新的对象。返回值自动被转换为responseType参数指定的类型,这里是字符串。

我们的需求是发送post请求至person api,创建新的Person对象并响应中包括新创建的对象。

首先,基于personJsonObject构建HttpEntity 类型的请求对象,并在请求头中指定Content-Type。

然后调用postForObject 方法发送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发送json

相比于postForObject()方法, postForEntity() 返回响应体为 ResponseEntity 类型,其他两个方法功能一致。

我们的需求是发送post请求至person api,创建新的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发送json

与postForObject 和 postForEntity 方法类型, postForLocation 也发送post请求至特定uri并创建新的对象。

唯一的差异是返回值为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 如何发送json类型的post请求,共三种方法应用与不同场景。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Netty分布式ByteBuf使用directArena分配缓冲区过程解析

    Netty分布式ByteBuf使用directArena分配缓冲区过程解析

    这篇文章主要介绍了Netty分布式ByteBuf使用directArena分配缓冲区过程解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03
  • Spring Security 表单登录功能的实现方法

    Spring Security 表单登录功能的实现方法

    这篇文章主要介绍了Spring Security 表单登录,本文将构建在之前简单的 Spring MVC示例 之上,因为这是设置Web应用程序和登录机制的必不可少的。需要的朋友可以参考下
    2019-06-06
  • Java中List与数组之间的相互转换

    Java中List与数组之间的相互转换

    在日常Java学习或项目开发中,经常会遇到需要int[]数组和List列表相互转换的场景,然而往往一时难以想到有哪些方法,最后可能会使用暴力逐个转换法,往往不是我们所满意的,下面这篇文章主要给大家介绍了关于Java中List与数组之间的相互转换,需要的朋友可以参考下
    2023-05-05
  • SpringCloud Gateway HttpWebHandlerAdapter链路调用请求流程介绍

    SpringCloud Gateway HttpWebHandlerAdapter链路调用请求流程介

    Spring Cloud Gateway旨在为微服务架构提供一种简单有效的、统一的 API 路由管理方式。Spring Cloud Gateway 作为 Spring Cloud 生态系中的网关,它不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全、监控/埋点和限流等
    2022-10-10
  • Java关键字之instanceof详解

    Java关键字之instanceof详解

    instanceof是Java的一个二元操作符,和==,>,<是同一类东东。由于它是由字母组成的,所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据
    2021-11-11
  • Spring WebFlux使用函数式编程模型构建异步非阻塞服务

    Spring WebFlux使用函数式编程模型构建异步非阻塞服务

    这篇文章主要介绍了Spring WebFlux使用函数式编程模型构建异步非阻塞服务,重点介绍如何使用函数式编程模型创建响应式 RESTful 服务,这种编程模型与传统的基于 Spring MVC 构建 RESTful 服务的方法有较大差别,感兴趣的朋友跟随小编一起看看吧
    2023-08-08
  • 解决RabbitMq消息队列Qos Prefetch消息堵塞问题

    解决RabbitMq消息队列Qos Prefetch消息堵塞问题

    这篇文章主要为大家介绍了关于如何解决解决RabbitMq Qos Prefetch消息堵塞的问题分析,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2022-01-01
  • java开发微信分享到朋友圈功能

    java开发微信分享到朋友圈功能

    这篇文章主要为大家详细介绍了java开发微信发送给朋友和分享到朋友圈功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • 解决Spring使用@MapperScan问题

    解决Spring使用@MapperScan问题

    这篇文章主要介绍了解决Spring使用@MapperScan问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Java递归算法经典实例(经典兔子问题)

    Java递归算法经典实例(经典兔子问题)

    本文主要对经典的兔子案例分析,来进一步更好的理解和学习java递归算法,具有很好的参考价值,需要的朋友一起来看下吧
    2016-12-12

最新评论