HTTP PUT vs HTTP PATCH i EN REST API

Oversikt

i denne raske artikkelen ser vi på forskjeller MELLOM HTTP PUT og PATCH verb og på semantikken til de to operasjonene.

Vi bruker Spring til å implementere TO RESTENDEPUNKTER som støtter disse to typer operasjoner, og for å bedre forstå forskjellene og den riktige måten å bruke dem på.

Når Skal Du Bruke Put og Når Patch?

la oss starte med en enkel og litt enkel setning.

når en klient må erstatte en eksisterende Ressurs helt, kan DE bruke PUT. Når de gjør en delvis oppdatering, kan de bruke HTTP PATCH.

for eksempel, når du oppdaterer et enkelt Felt Av Ressursen, kan sende den komplette Ressursrepresentasjonen være tungvint og bruker mye unødvendig båndbredde. I slike tilfeller GJØR PATCHENS semantikk mye mer fornuftig.

et annet viktig aspekt å vurdere her er idempotence; PUT er idempotent; PATCH kan være, men er ikke nødvendig. Og så-avhengig av semantikken til operasjonen vi implementerer, kan vi også velge den ene eller den andre basert på denne egenskapen.

Implementere PUT Og PATCH Logic

la oss si at VI vil implementere REST API for å oppdatere En HeavyResource med flere felt:

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

Først må vi opprette endepunktet som håndterer en full oppdatering av ressursen VED HJELP AV PUT:

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

dette er et standard endepunkt for oppdatering av ressurser.

la Oss nå si at adressefeltet ofte vil bli oppdatert av klienten. I så fall ønsker vi ikke å sende Hele HeavyResource-objektet med alle felt, men vi vil bare ha muligheten til å oppdatere adressefeltet-via PATCH-metoden.

Vi kan opprette En HeavyResourceAddressOnly DTO for å representere en delvis oppdatering av adressefeltet:

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

Deretter kan vi utnytte PATCH-metoden for å sende en delvis oppdatering:

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

Med denne mer granulære DTO kan vi sende feltet vi trenger å oppdatere bare-uten overhead for å sende Hele HeavyResource.

hvis vi har et stort antall av disse delvise oppdateringsoperasjonene, kan vi også hoppe over opprettelsen av en tilpasset DTO for hver ut-og bare bruke et kart:

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

denne løsningen vil gi OSS mer fleksibilitet i å implementere API; men vi mister også noen ting – for eksempel validering.

Testing PUT OG PATCH

Til Slutt, la oss skrive tester for BEGGE HTTP-metodene. Først vil vi teste oppdateringen av hele ressursen via PUT-metoden:

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

Utførelse av en delvis oppdatering oppnås ved Å bruke PATCH-metoden:

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

Vi kan også skrive en test for en mer generisk tilnærming:

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

Håndtering Av Delvise Forespørsler Med Nullverdier

når vi skriver en implementering For EN PATCH-metode, må vi spesifisere en kontrakt for hvordan vi behandler saker når vi får null som en verdi for adressefeltet I HeavyResourceAddressOnly.

Anta at klienten sender følgende forespørsel:

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

da kan vi håndtere dette som å sette en verdi av adressefeltet til null eller bare ignorere en slik forespørsel ved å behandle den som ingen endring.

Vi bør velge en strategi for håndtering av null og holde fast ved den i hver PATCH-metodeimplementering.

Konklusjon

i denne raske opplæringen fokuserte vi på å forstå forskjellene MELLOM HTTP-OPPDATERINGEN og PUT-metodene.

vi implementerte en enkel Spring REST-kontroller for å oppdatere En Ressurs via PUT-metoden og en delvis oppdatering ved HJELP AV PATCH.

implementeringen av alle disse eksemplene og kodebitene finnes i GitHub-prosjektet-dette Er Et maven-prosjekt, så det skal være enkelt å importere og kjøre som det er.

Kom I Gang Med Spring 5 og Spring Boot 2, gjennom Learn Spring course :

>> SJEKK UT KURSET

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.