HTTP PUT vs HTTP PATCH egy REST API-ban

1. Áttekintés

Ebben a rövid cikkben a HTTP PUT és a PATCH igék közötti különbségeket, valamint a két művelet szemantikáját vizsgáljuk.

A Spring segítségével két olyan REST végpontot valósítunk meg, amelyek támogatják ezt a kétféle műveletet, valamint hogy jobban megértsük a különbségeket és a használatuk helyes módját.

2. Mikor kell használni a Put and When Patch-et?

Kezdjük egy egyszerű és kissé egyszerű állítással.

Amikor egy ügyfélnek teljesen ki kell cserélnie egy meglévő erőforrást, használhatja a PUT-t. Részleges frissítéskor használhatják a HTTP PATCH-ot.

Például az erőforrás egyetlen mezőjének frissítésekor a teljes erőforrás-ábrázolás elküldése nehézkes lehet, és sok felesleges sávszélességet használ fel. Ilyen esetekben a PATCH szemantikájának sokkal több értelme van.

Egy másik fontos szempont, amelyet itt figyelembe kell venni idempotencia; A PUT idempotens; A PATCH lehet, de nem kötelező. Tehát - az általunk végrehajtott művelet szemantikájától függően e jellemző alapján választhatunk egyet vagy mást is.

3. A PUT és a PATCH logika megvalósítása

Tegyük fel, hogy a REST API-t szeretnénk megvalósítani az a frissítéséhez HeavyResource több mezővel:

public class HeavyResource {private Integer id; privát karakterlánc neve; privát String cím; // ...

Először létre kell hoznunk azt a végpontot, amely az erőforrás teljes frissítését kezeli a PUT használatával:

@PutMapping ("/ heavyyresource / {id}") public ResponseEntity saveResource (@RequestBody HeavyResource heavyResource, @PathVariable ("id") String id) {heavyResourceRepository.save (heavyResource, id); return ResponseEntity.ok ("mentett erőforrás"); }

Ez az erőforrások frissítésének szabványos végpontja.

Tegyük fel, hogy az ügyfél gyakran frissíti a cím mezőt. Ebben az esetben, nem akarjuk az egészet elküldeni HeavyResource objektum az összes mezővel, de azt akarjuk, hogy csak a cím mező - a PATCH módszerrel.

Hozhatunk létre a HeavyResourceAddressOnly A DTO a cím mező részleges frissítését jelenti:

public class HeavyResourceAddressOnly {private Integer id; privát String cím; // ...}

Ezután kihasználhatjuk a PATCH metódust egy részleges frissítés küldésére:

@PatchMapping ("/ heavyyresource / {id}") nyilvános ResponseEntity részlegesUpdateName (@RequestBody HeavyResourceAddressOnly partUpdate, @PathVariable ("id") karakterlánc azonosító) {heavyResourceRepository.save (particionális frissítés, id); return ResponseEntity.ok ("az erőforrás címe frissítve"); }

Ezzel a szemcsésebb DTO-val csak azt a mezőt tudjuk elküldeni, amelyet frissítenünk kell - anélkül, hogy az egészet küldenénk HeavyResource.

Ha ezeknek a részleges frissítési műveleteknek nagy száma van, akkor mindegyikhez kihagyhatjuk az egyedi DTO létrehozását - és csak térképet használhatunk:

@RequestMapping (value = "/ heavyyresource / {id}", metódus = RequestMethod.PATCH, fogyaszt = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity partialUpdateGeneric (@RequestBody Map frissítések, @PathVariable ("id") String azonosító) {heavyRes frissítések, id); return ResponseEntity.ok ("erőforrás frissítve"); }

Ez a megoldás nagyobb rugalmasságot biztosít számunkra az API megvalósításában; azonban elveszítünk néhány dolgot is - például az érvényesítést.

4. A PUT és a PATCH tesztelése

Végül írjunk teszteket mindkét HTTP módszerhez. Először a teljes erőforrás PUT módszerrel történő frissítését akarjuk tesztelni:

mockMvc.perform (put ("/ heavyyresource / 1") .contentType (MediaType.APPLICATION_JSON_VALUE) .content (objectMapper.writeValueAsString (új HeavyResource (1, "Tom", "Jackson", 12, "menny utca"))) .andExpect (status (). isOk ());

A részleges frissítés a PATCH módszerrel érhető el:

mockMvc.perform (patch ("/ heavyyrecource / 1") .contentType (MediaType.APPLICATION_JSON_VALUE) .content (objectMapper.writeValueAsString (új HeavyResourceAddressOnly (1, "5. avenue"))) (állapotEx (). );

Tesztet is írhatunk egy általánosabb megközelítéshez:

HashMap frissítések = new HashMap (); updates.put ("cím", "5. sugárút"); mockMvc.perform (patch ("/ heavyyresource / 1") .contentType (MediaType.APPLICATION_JSON_VALUE) .content (objectMapper.writeValueAsString (frissítések)) .andExpect (status (). isOk ()); 

5. Részleges kérelmek kezelése Nulla Értékek

Amikor egy PATCH módszer megvalósítását írjuk, meg kell határoznunk egy szerződést arról, hogyan kell kezelni az eseteket, amikor megkapjuk nulla értékeként a cím mező a HeavyResourceAddressOnly.

Tegyük fel, hogy az ügyfél a következő kérést küldi:

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

Akkor ezt úgy kezelhetjük, hogy beállítjuk a cím mezőt nulla vagy csak figyelmen kívül hagyja az ilyen kérést azzal, hogy változtatás nélküliként kezeli.

Egy kezelési stratégiát kell választanunk nulla és ragaszkodjon hozzá minden PATCH módszer megvalósításakor.

6. Következtetés

Ebben a gyors bemutatóban a HTTP PATCH és PUT módszerek közötti különbségek megértésére összpontosítottunk.

Megvalósítottunk egy egyszerű Spring REST vezérlőt az erőforrás PUT módszerrel történő frissítésére és egy részleges frissítést a PATCH használatával.

Ezeknek a példáknak és kódrészleteknek a megvalósítása megtalálható a GitHub projektben - ez egy Maven projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.