HTTP PUT vs HTTP PATCH em uma API REST

visão geral

neste artigo rápido, estamos olhando para as diferenças entre os verbos PUT e PATCH HTTP e na semântica das duas operações.

usaremos a Primavera para implementar dois parâmetros de descanso que suportam estes dois tipos de operações, e para compreender melhor as diferenças e a maneira correta de usá-las.

quando aplicar e quando aplicar o sistema transdérmico?

vamos começar com uma declaração simples, e um pouco simples.

quando um cliente precisa substituir um recurso existente inteiramente, eles podem usar PUT. Quando eles estão fazendo uma atualização parcial, eles podem usar PATCH HTTP.

por exemplo, ao atualizar um único campo do recurso, o envio da representação completa dos recursos pode ser complicado e utiliza uma grande quantidade de largura de banda desnecessária. Nesses casos, a semântica do PATCH faz muito mais sentido.

outro aspecto importante a considerar aqui é idempotência; PUT é idempotente; PATCH pode ser, mas não é necessário. E, dependendo da semântica da operação que estamos implementando, também podemos escolher uma ou outra com base nesta característica.

implementando a lógica PUT and PATCH

digamos que queremos implementar a API REST para atualizar um recurso pesado com vários campos:

public class HeavyResource { private Integer id; private String name; private String address; // ...

primeiro, precisamos criar o endpoint que lida com uma atualização completa do recurso usando PUT:

@PutMapping("/heavyresource/{id}")public ResponseEntity<?> saveResource(@RequestBody HeavyResource heavyResource, @PathVariable("id") String id) { heavyResourceRepository.save(heavyResource, id); return ResponseEntity.ok("resource saved");}

este é um endpoint padrão para a atualização de recursos.

agora, vamos dizer que o campo Endereço muitas vezes será atualizado pelo cliente. Nesse caso, não queremos enviar todo o objeto Heavy – Source com todos os campos, mas queremos a capacidade de apenas atualizar o campo Endereço-através do método PATCH.

podemos criar um HeavyResourceAddressOnly DTO para representar uma atualização parcial do campo de endereço:

public class HeavyResourceAddressOnly { private Integer id; private String address; // ...}

ao lado, podemos utilizar o PATCH método para enviar uma atualização parcial:

@PatchMapping("/heavyresource/{id}")public ResponseEntity<?> partialUpdateName( @RequestBody HeavyResourceAddressOnly partialUpdate, @PathVariable("id") String id) { heavyResourceRepository.save(partialUpdate, id); return ResponseEntity.ok("resource address updated");}

Com isso mais granular DTO, podemos enviar o campo que necessita para actualizar apenas – sem a sobrecarga de envio de toda a HeavyResource.

se tivermos um grande número destas operações de actualização parcial, também podemos ignorar a criação de um DTO personalizado para cada saída – e usar apenas um mapa:

@RequestMapping(value = "/heavyresource/{id}", method = RequestMethod.PATCH, consumes = MediaType.APPLICATION_JSON_VALUE)public ResponseEntity<?> partialUpdateGeneric( @RequestBody Map<String, Object> updates, @PathVariable("id") String id) { heavyResourceRepository.save(updates, id); return ResponseEntity.ok("resource updated");}

esta solução dar – nos-á mais flexibilidade na implementação da API; no entanto, também perdemos algumas coisas-como a validação.

Testing PUT and PATCH

Finally, let’s write tests for both HTTP methods. Primeiro, queremos testar a atualização do recurso completo através do método PUT:

mockMvc.perform(put("/heavyresource/1") .contentType(MediaType.APPLICATION_JSON_VALUE) .content(objectMapper.writeValueAsString( new HeavyResource(1, "Tom", "Jackson", 12, "heaven street"))) ).andExpect(status().isOk());

a execução de uma actualização parcial é obtida utilizando o método do PATCH:

mockMvc.perform(patch("/heavyrecource/1") .contentType(MediaType.APPLICATION_JSON_VALUE) .content(objectMapper.writeValueAsString( new HeavyResourceAddressOnly(1, "5th avenue"))) ).andExpect(status().isOk());

podemos também escrever um teste para uma abordagem mais genérica:

HashMap<String, Object> updates = new HashMap<>();updates.put("address", "5th avenue");mockMvc.perform(patch("/heavyresource/1") .contentType(MediaType.APPLICATION_JSON_VALUE) .content(objectMapper.writeValueAsString(updates)) ).andExpect(status().isOk());

Tratamento Parcial Pedidos Com Valores Null

Quando estamos a escrever uma implementação para um PATCH método, precisamos especificar um contrato de como tratar casos, quando chegar null como um valor para o campo de endereço na HeavyResourceAddressOnly.

suponha que o cliente envia o seguinte pedido:

{ "id" : 1, "address" : null}

então podemos lidar com isso como definir um valor do campo Endereço para nulo ou simplesmente ignorar tal pedido, tratando-o como não-mudança.

devemos escolher uma estratégia para lidar com null e aderir a ele em cada implementação do método PATCH.

Conclusion

In this quick tutorial, we focused on understanding the differences between the HTTP PATCH and PUT methods.

implementamos um controlador de repouso de mola simples para atualizar um recurso através do método PUT e uma atualização parcial usando o PATCH.

a implementação de todos estes exemplos e excertos de código podem ser encontrados no projeto GitHub – este é um projeto Maven, por isso deve ser fácil de importar e executar como ele é.

Começar com Mola 5 e Primavera de Inicialização 2, através do Aprender a Primavera curso :

>> confira O CURSO

Deixe uma resposta

O seu endereço de email não será publicado.