Solicitação de postagem RestTemplate com JSON

Solicitação de postagem RestTemplate com JSON

1. Introdução

Neste tutorial, ilustraremos como usarRestTemplate do Spring para fazer solicitações POST enviando conteúdo JSON.

Leitura adicional:

Explorando o Spring Boot TestRestTemplate

Aprenda a usar o novo TestRestTemplate no Spring Boot para testar uma API simples.

Read more

Tratamento de erros RestTemplate de primavera

Aprenda a lidar com erros com RestTemplate de Spring

Read more

2. Configurando o exemplo

Vamos começar adicionando uma classe de modeloPerson simples para representar os dados a serem postados:

public class Person {
    private Integer id;
    private String name;

    // standard constructor, getters, setters
}

Para trabalhar com objetosPerson, vamos adicionar uma interfacePersonService e implementação com 2 métodos:

public interface PersonService {

    public Person saveUpdatePerson(Person person);
    public Person findPersonById(Integer id);
}

A implementação desses métodos simplesmente retornará um objeto. Estamos usando uma implementação fictícia dessa camada aqui para que possamos nos concentrar na camada da web.

3. Configurando a API REST

Vamos definir uma API REST simples para nossa classePerson:

@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);
}

Como lembramos, queremos postar os dados no formato JSON. Para isso,we added the consumes attribute in the @PostMapping annotation with the value of “application/json” para ambos os métodos.

Da mesma forma, definimos o atributoproduces para “application / json” para dizer ao Spring que queremos o corpo da resposta no formato JSON.

Anotamos o parâmetroperson com a anotação@RequestBody para ambos os métodos. Isso dirá ao Spring que o objetoperson será vinculado ao corpo da solicitaçãoHTTP.

Por último, ambos os métodos retornam um objetoPerson que será vinculado ao corpo da resposta. Notemos que anotaremos nossa classe API com@RestController para anotar todos os métodos API com uma anotação@ResponseBody oculta.

4. UsandoRestTemplate

Agora podemos escrever alguns testes de unidade para testar nossa API RESTPerson. Aqui,we’ll try to send POST requests to the Person API by using the POST methods provided by the RestTemplate: postForObject, postForEntity, and postForLocation.

Antes de começarmos a implementar nossos testes de unidade, vamos definir um método de configuração para inicializar os objetos que usaremos em todos os nossos métodos de teste de unidade:

@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);
    personJsonObject = new JSONObject();
    personJsonObject.put("id", 1);
    personJsonObject.put("name", "John");
}

Além deste método de configuração, observe que nos referiremos ao seguinte mapeador para converter a String JSON em um objetoJSONNode em nossos testes de unidade:

private final ObjectMapper objectMapper = new ObjectMapper();

Como mencionamos anteriormente,we want to post the data in JSON format. In order to achieve this, we’ll add a Content-Type header to our request with the APPLICATION_JSON media type.

A classeHttpHeaders do Spring fornece métodos diferentes para acessar os cabeçalhos. Aqui, definimos o cabeçalhoContent-Type paraapplication/json chamando o métodosetContentType. Vamos anexar o objetoheaders às nossas solicitações.

4.1. Postando JSON compostForObject

O métodoRestTemplate depostForObject cria um novo recurso postando um objeto no modelo de URI fornecido. Ele retorna o resultado convertido automaticamente para o tipo especificado no parâmetroresponseType.

Digamos que queremos fazer uma solicitação POST para nossa APIPerson para criar um novo objetoPerson e retornar esse objeto recém-criado na resposta.

First, we’ll build the request object of type HttpEntity based on the personJsonObject and the headers containing the*Content-Type*. Isso permite que o métodopostForObject envie um corpo de solicitação JSON:

@Test
public void givenDataIsJson_whenDataIsPostedByPostForObject_thenResponseBodyIsNotNull()
  throws IOException {
    HttpEntity request =
      new HttpEntity(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());
}

Neste exemplo, o métodopostForObject() retorna o corpo da resposta como um tipoString. Também podemos retornar a resposta como um objetoPerson definindo o parâmetroresponseType:

Person person = restTemplate.postForObject(createPersonUrl, request, Person.class);

assertNotNull(person);
assertNotNull(person.getName());

Na verdade, nosso método de manipulador de solicitação correspondente ao URIcreatePersonUrl produz o corpo da resposta no formato JSON. Mas isso não é uma limitação para nós -postForObject é capaz de converter automaticamente o corpo da resposta no tipo Java solicitado (por exemplo String,Person) especificado no parâmetroresponseType.

4.2. Postando JSON compostForEntity

Comparado compostForObject(),postForEntity() returns the response as a ResponseEntity object. Fora isso, os dois métodos fazem o mesmo trabalho.

Digamos que queremos fazer uma solicitação POST para nossa APIPerson para criar um novo objetoPerson e retornar a resposta como umResponseEntity. Podemos usar o métodopostForEntity para implementar isso:

@Test
public void givenDataIsJson_whenDataIsPostedByPostForEntity_thenResponseBodyIsNotNull()
  throws IOException {
    HttpEntity request =
      new HttpEntity(personJsonObject.toString(), headers);

    ResponseEntity responseEntityStr = restTemplate.
      postForEntity(createPersonUrl, request, String.class);
    JsonNode root = objectMapper.readTree(responseEntityStr.getBody());

    assertNotNull(responseEntityStr.getBody());
    assertNotNull(root.path("name").asText());
}

Semelhante aopostForObject,postForEntity tem o parâmetroresponseType para converter o corpo da resposta para o tipo Java solicitado.

Aqui, pudemos retornar o corpo da resposta como umResponseEntity<String>.

Também podemos retornar a resposta como um objetoResponseEntity<Person> definindo o parâmetroresponseType paraPerson.class:

ResponseEntity responseEntityPerson = restTemplate.
  postForEntity(createPersonUrl, request, Person.class);

assertNotNull(responseEntityPerson.getBody());
assertNotNull(responseEntityPerson.getBody().getName());

4.3. Postando JSON compostForLocation

Semelhante aos métodospostForObjectepostForEntity,postForLocation também cria um novo recurso postando o objeto fornecido no URI fornecido. A única diferença é que ele retorna o valor do cabeçalhoLocation.

Lembre-se de que já vimos como definir o cabeçalhoLocation de uma resposta em nosso método de API RESTupdatePerson acima:

response.setHeader("Location", ServletUriComponentsBuilder.fromCurrentContextPath()
  .path("/findPerson/" + person.getId()).toUriString());

Agora, vamos imaginar quewe want to return the Location header of the response after updating the person object we posted. Podemos implementar isso usando o métodopostForLocation:

@Test
public void givenDataIsJson_whenDataIsPostedByPostForLocation_thenResponseBodyIsTheLocationHeader()
  throws JsonProcessingException {
    HttpEntity request = new HttpEntity(personJsonObject.toString(), headers);
    URI locationHeader = restTemplate.postForLocation(updatePersonUrl, request);

    assertNotNull(locationHeader);
}

5. Conclusão

Neste tutorial rápido, exploramos como usarRestTemplate para fazer uma solicitação POST com JSON.

Como sempre, todos os exemplos e fragmentos de código podem ser encontradosover on GitHub.