HTTP PUT vs HTTP PATCH in een REST API

overzicht

in dit snelle artikel kijken we naar verschillen tussen de HTTP PUT en PATCH werkwoorden en naar de semantiek van de twee bewerkingen.

we gebruiken Spring om twee REST-eindpunten te implementeren die deze twee soorten operaties ondersteunen, en om de verschillen en de juiste manier om ze te gebruiken beter te begrijpen.

wanneer gebruik je Put en wanneer Patch?

laten we beginnen met een eenvoudig, en enigszins eenvoudig statement.

wanneer een client een bestaande bron volledig moet vervangen, kunnen ze PUT gebruiken. Als ze een gedeeltelijke update doen, kunnen ze HTTP PATCH gebruiken.

bijvoorbeeld, wanneer een enkel veld van de bron wordt bijgewerkt, kan het verzenden van de volledige Bronrepresentatie omslachtig zijn en veel onnodige bandbreedte gebruiken. In dergelijke gevallen is de semantiek van PATCH veel zinvoller.

een ander belangrijk aspect om hier te overwegen is idempotentie; PUT is idempotent; PATCH kan zijn, maar is niet vereist. En, dus-afhankelijk van de semantiek van de operatie die we implementeren, kunnen we ook kiezen voor een of andere op basis van deze eigenschap.

implementatie van PUT-en PATCHLOGICA

stel dat we de REST API willen implementeren voor het bijwerken van een HeavyResource met meerdere velden:

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

eerst moeten we het eindpunt maken dat een volledige update van de bron afhandelt met PUT:

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

dit is een standaard eindpunt voor het bijwerken van bronnen.

stel nu dat het adresveld vaak door de client wordt bijgewerkt. In dat geval willen we niet het hele HeavyResource object met alle velden verzenden, maar we willen wel de mogelijkheid om alleen het adres veld bij te werken – via de PATCH methode.

we kunnen een Heavyresourceaddress only Dto maken om een gedeeltelijke update van het adresveld weer te geven:

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

vervolgens kunnen we de PATCHMETHODE gebruiken om een gedeeltelijke update te verzenden:

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

met deze meer gedetailleerde DTO, kunnen we het veld dat we nodig hebben om alleen te updaten verzenden – zonder de overhead van het verzenden van hele zware bron.

als we een groot aantal van deze gedeeltelijke updatebewerkingen hebben, kunnen we ook de creatie van een aangepaste DTO overslaan voor elke out-en alleen een kaart gebruiken:

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

deze oplossing geeft ons meer flexibiliteit bij het implementeren van API; we verliezen echter ook een paar dingen-zoals validatie.

testen PUT en PATCH

ten slotte, laten we testen schrijven voor beide HTTP methoden. Eerst willen we de update van de volledige bron via PUT-methode testen:

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

uitvoering van een gedeeltelijke update wordt bereikt met behulp van de PATCH-methode:

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

we kunnen ook een test schrijven voor een meer algemene aanpak:

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());

partiële aanvragen met Null-waarden

wanneer we een implementatie schrijven voor een PATCHMETHODE, moeten we een contract specificeren over hoe we gevallen moeten behandelen wanneer we null krijgen als een waarde voor het adresveld in de Zwaarresourceaddressonly.

stel dat de client het volgende verzoek verzendt:

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

dan kunnen we dit behandelen als het instellen van een waarde van het adresveld op null of gewoon een dergelijk verzoek negeren door het te behandelen als geen-verandering.

we moeten één strategie kiezen voor het verwerken van null en ons daaraan houden in elke PATCH methode implementatie.

conclusie

in deze korte handleiding hebben we ons gericht op het begrijpen van de verschillen tussen de HTTP PATCH en PUT methoden.

we hebben een eenvoudige Spring REST controller geïmplementeerd om een bron bij te werken via PUT methode en een gedeeltelijke update met behulp van PATCH.

de implementatie van al deze voorbeelden en codefragmenten kan worden gevonden in het GitHub project – Dit is een Maven project, dus het zou eenvoudig moeten zijn om te importeren en te draaien zoals het is.

aan de slag met Spring 5 en Spring Boot 2, Via de learn Spring course :

>> bekijk de cursus

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.