HTTP PUT vs HTTP PATCH u REST API-ju
1. Pregled
U ovom kratkom članku promatramo razlike između glagola HTTP PUT i PATCH te semantiku dviju operacija.
Proljeće ćemo koristiti za implementaciju dviju krajnjih točaka REST koje podržavaju ove dvije vrste operacija te za bolje razumijevanje razlika i ispravan način njihove upotrebe.
2. Kada koristiti put i kada zakrpu?
Počnimo s jednostavnom i malo jednostavnom izjavom.
Kada klijent treba u potpunosti zamijeniti postojeći resurs, može koristiti PUT. Kad rade djelomično ažuriranje, mogu koristiti HTTP PATCH.
Na primjer, kada ažurirate jedno polje Resursa, slanje cjelovite reprezentacije Resursa može biti glomazno i koristi puno nepotrebne propusnosti. U takvim slučajevima semantika PATCH-a ima puno više smisla.
Sljedeći važan aspekt koji treba ovdje razmotriti je idempotencija; PUT je idempotentan; PATCH može biti, ali nije potreban. I, tako - ovisno o semantici operacije koju provodimo, također možemo odabrati jedno ili drugo na temelju ove karakteristike.
3. Implementacija logike PUT i PATCH
Recimo da želimo implementirati REST API za ažuriranje a HeavyResource s više polja:
javna klasa HeavyResource {private Integer id; privatni naziv niza; privatna string adresa; // ...
Prvo, moramo stvoriti krajnju točku koja obrađuje potpuno ažuriranje resursa pomoću PUT-a:
@PutMapping ("/ heavyresource / {id}") javni ResponseEntity saveResource (@RequestBody HeavyResource heavyResource, @PathVariable ("id") String id) {heavyResourceRepository.save (heavyResource, id); vratiti ResponseEntity.ok ("resurs spremljen"); }
Ovo je standardna krajnja točka za ažuriranje resursa.
Recimo sada da će klijent često ažurirati to polje adrese. U tom slučaju, ne želimo poslati cjelinu HeavyResource objekt sa svim poljima, ali želimo mogućnost ažuriranja samo adresa polje - metodom PATCH.
Možemo stvoriti HeavyResourceAddressOnly DTO predstavlja djelomično ažuriranje polja adrese:
javna klasa HeavyResourceAddressOnly {privatni cjeloviti id; privatna string adresa; // ...}
Dalje, možemo koristiti metodu PATCH za slanje djelomičnog ažuriranja:
@PatchMapping ("/ heavyresource / {id}") javni ResponseEntity djelomičnoUpdateName (@RequestBody HeavyResourceAddressOnly activUpdate, @PathVariable ("id") String id) {heavyResourceRepository.save (djelomično ažuriranje, id); return ResponseEntity.ok ("adresa resursa ažurirana"); }
Ovim granuliranijim DTO-om možemo poslati samo polje koje trebamo ažurirati - bez dodatnih troškova slanja cijelog HeavyResource.
Ako imamo velik broj ovih djelomičnih operacija ažuriranja, također možemo preskočiti stvaranje prilagođenog DTO-a za svaki izlaz - i koristiti samo kartu:
@RequestMapping (value = "/ heavyresource / {id}", method = RequestMethod.PATCH, konzumira = MediaType.APPLICATION_JSON_VALUE) javni ResponseEntity partUpdateGeneric (@RequestBody Map Updates, @PathVariable ("id") String id) {heavyResourve (ID) String id )Repository. ažuriranja, id); vratiti ResponseEntity.ok ("resurs ažuriran"); }
Ovo rješenje pružit će nam veću fleksibilnost u implementaciji API-ja; međutim, gubimo i nekoliko stvari - poput provjere valjanosti.
4. Testiranje PUT-a i PATCH-a
Na kraju, napišimo testove za obje HTTP metode. Prvo želimo testirati ažuriranje punog resursa metodom PUT:
mockMvc.perform (put ("/ heavyresource / 1") .contentType (MediaType.APPLICATION_JSON_VALUE) .content (objectMapper.writeValueAsString (novi HeavyResource (1, "Tom", "Jackson", 12, "nebeska ulica"))) .andExpect (status (). isOk ());
Izvršenje djelomičnog ažuriranja postiže se metodom PATCH:
mockMvc.perform (patch ("/ heavyrecource / 1") .contentType (MediaType.APPLICATION_JSON_VALUE) .content (objectMapper.writeValueAsString (new HeavyResourceAddressOnly (1, "5th avenue")))) (status (Expect). );
Također možemo napisati test za općenitiji pristup:
Ažuriranja HashMap-a = novi HashMap (); updates.put ("adresa", "5. avenija"); mockMvc.perform (patch ("/ heavyresource / 1") .contentType (MediaType.APPLICATION_JSON_VALUE) .content (objectMapper.writeValueAsString (updates))) .andExpect (status (). isOk ());
5. Obrada djelomičnih zahtjeva s Nula Vrijednosti
Kada pišemo implementaciju za metodu PATCH, moramo navesti ugovor o postupanju sa slučajevima kada ih dobijemo null kao vrijednost za adresa polje u HeavyResourceAddressOnly.
Pretpostavimo da klijent pošalje sljedeći zahtjev:
{"id": 1, "adresa": null}
Tada to možemo podnijeti kao postavljanje vrijednosti adresa polje do null ili samo ignoriranje takvog zahtjeva tretirajući ga kao promjenu.
Trebali bismo odabrati jednu strategiju rukovanja null i pridržavajte se toga u svakoj implementaciji PATCH metode.
6. Zaključak
U ovom smo se brzom vodiču usredotočili na razumijevanje razlika između metoda HTTP PATCH i PUT.
Implementirali smo jednostavni kontroler Spring REST za ažuriranje resursa metodom PUT i djelomično ažuriranje pomoću PATCH-a.
Provedbu svih ovih primjera i isječaka koda možete pronaći u projektu GitHub - ovo je Maven projekt, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.