HATEOAS a tavaszi Pihenés szolgáltatásért
Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:
>> ELLENŐRIZZE A FOLYAMATOT1. Áttekintés
Ez a cikk a a felfedezhetőség megvalósítása egy tavaszi REST szolgáltatásban és a HATEOAS korlátozásának teljesítéséről.
Ez a cikk a Spring MVC-re összpontosít. Az Intro to Spring HATEOAS cikkünk leírja a HATEOAS használatát a tavaszi rendszerindításban.
2. A felfedezhetőség függetlenítése az események révén
A felfedezhetőséget, mint a webréteg külön szempontját vagy gondját, el kell választani a vezérlőtől a HTTP kérés kezelése. Ebből a célból a Vezérlő eseményeket indít el minden olyan művelet esetében, amely a reakció további manipulációját igényli.
Először hozzuk létre az eseményeket:
public class SingleResourceRetrieved kiterjeszti az ApplicationEvent {private HttpServletResponse választ; public SingleResourceRetrieved (Object source, HttpServletResponse response) {szuper (forrás); ez.válasz = válasz; } public HttpServletResponse getResponse () {return response; }} public class ResourceCreated kiterjeszti az ApplicationEvent {private HttpServletResponse választ; privát hosszú idOfNewResource; public ResourceCreated (Object source, HttpServletResponse response, long idOfNewResource) {super (forrás); ez.válasz = válasz; this.idOfNewResource = idOfNewResource; } public HttpServletResponse getResponse () {return response; } public long getIdOfNewResource () {return idOfNewResource; }}
Azután, a vezérlő, 2 egyszerű művelettel - id szerint találni és teremt:
@RestController @RequestMapping (value = "/ foos") nyilvános osztályú FooController {@Autowired private ApplicationEventPublisher eventPublisher; @Autowired privát IFooService szolgáltatás; @GetMapping (value = "foos / {id}") public Foo findById (@PathVariable ("id") Long id, HttpServletResponse response) {Foo resourceById = Preconditions.checkNotNull (service.findOne (id)); eventPublisher.publishEvent (új SingleResourceRetrieved (ez, válasz)); return resourceById; } @PostMapping @ResponseStatus (HttpStatus.CREATED) public void create (@RequestBody Foo erőforrás, HttpServletResponse válasz) {Preconditions.checkNotNull (erőforrás); Long newId = service.create (erőforrás) .getId (); eventPublisher.publishEvent (new ResourceCreated (this, response, newId)); }}
Ezután tetszőleges számú független hallgatóval kezelhetjük ezeket az eseményeket. Ezek mindegyike a saját egyedi esetére összpontosíthat, és segíthet az általános HATEOAS-korlát teljesítésében.
A hallgatók legyenek a hívásverem utolsó objektumai, és nincs szükség közvetlen hozzáférésre; mint ilyenek nem nyilvánosak.
3. Egy újonnan létrehozott erőforrás URI-jának felfedezhetővé tétele
Amint azt a HATEOAS-ról szóló előző bejegyzés egy új erőforrás létrehozásának műveletének vissza kell adnia az erőforrás URI-ját a Elhelyezkedés HTTP fejléc a válasz.
Ezt egy hallgató segítségével kezeljük:
@Component class ResourceCreatedDiscoverabilityListener implementálja az ApplicationListener {@Override public void onApplicationEvent (ResourceCreated resourceCreatedEvent) {Preconditions.checkNotNull (resourceCreatedEvent); HttpServletResponse response = resourceCreatedEvent.getResponse (); hosszú idOfNewResource = resourceCreatedEvent.getIdOfNewResource (); addLinkHeaderOnResourceCreation (válasz, idOfNewResource); } void addLinkHeaderOnResourceCreation (HttpServletResponse válasz, hosszú idOfNewResource) {URI uri = ServletUriComponentsBuilder.fromCurrentRequestUri (). elérési út ("/ {idOfNewResource}"). buildAndExpand (idOfNewResource) .toUri (); response.setHeader ("Hely", uri.toASCIIString ()); }}
Ebben a példában felhasználjuk a ServletUriComponentsBuilder - amely segít az aktuális Kérés használatában. Így nincs szükségünk semmire sem, és egyszerűen statikusan hozzáférhetünk ehhez.
Ha az API visszatérne ResponseEntity - használhatnánk a Elhelyezkedés támogatás.
4. Egyetlen forrás megszerzése
Egyetlen erőforrás lekérésekor az ügyfélnek képesnek kell lennie felfedezni az URI-t az összes erőforrás megszerzéséhez ilyen típusú:
@Component osztály SingleResourceRetrievedDiscoverabilityListener implementálja az ApplicationListener {@Orride public void onApplicationEvent (SingleResourceRetrieved resourceRetrievedEvent) {Preconditions.checkNotNull (resourceRetrievedEvent); HttpServletResponse response = resourceRetrievedEvent.getResponse (); addLinkHeaderOnSingleResourceRetrieval (kérés, válasz); } void addLinkHeaderOnSingleResourceRetrieval (HttpServletResponse válasz) {String requestURL = ServletUriComponentsBuilder.fromCurrentRequestUri (). build (). toUri (). toASCIIString (); int positionOfLastSlash = requestURL.lastIndexOf ("/"); Karakterlánc uriForResourceCreation = requestURL.substring (0, positionOfLastSlash); String linkHeaderValue = LinkUtil .createLinkHeader (uriForResourceCreation, "gyűjtemény"); response.addHeader (LINK_HEADER, linkHeaderValue); }}
Vegye figyelembe, hogy a linkkapcsolat szemantikája a "Gyűjtemény" relációs típus, amelyet több mikroformátumban határoztak meg és használtak, de még nem szabványosítottak.
A Link fejléc az egyik leggyakrabban használt HTTP fejléca felfedezhetőség céljából. A fejléc létrehozásának segédprogramja elég egyszerű:
public class LinkUtil {public static String createLinkHeader (String uri, String rel) {return "; rel = \" "+ rel +" \ ""; }}
5. Felfedezhetőség a gyökérnél
A gyökér a teljes szolgáltatás belépési pontja - ez az, amellyel az ügyfél kapcsolatba lép az API első használatakor.
Ha a HATEOAS-korlátozást figyelembe kell venni és végre kell hajtani, akkor itt kell elindulnia. Ebből kifolyólag a rendszer összes fő URI-jának a gyökérből kell felfedezhetőnek lennie.
Most nézzük meg ennek vezérlőjét:
@GetMapping ("/") @ResponseStatus (érték = HttpStatus.NO_CONTENT) public void adminRoot (végleges HttpServletRequest kérés, végleges HttpServletResponse válasz) {String rootUri = request.getRequestURL (). ToString (); URI fooUri = új UriTemplate ("{rootUri} {erőforrás}"). Expand (rootUri, "foos"); String linkToFoos = LinkUtil.createLinkHeader (fooUri.toASCIIString (), "gyűjtemény"); response.addHeader ("Link", linkToFoos); }
Ez természetesen a koncepció szemléltetése, egyetlen, URI mintára összpontosítva Foo Erőforrások. A valódi megvalósításnak hasonlóan hozzá kell adnia az URI-kat az összes, az ügyfél számára közzétett erőforráshoz.
5.1. A felfedezhetőség nem az URI-k megváltoztatásáról szól
Ez ellentmondásos kérdés lehet - egyrészt a HATEOAS célja, hogy az ügyfél felfedezze az API URI-ját, és ne támaszkodjon kemény kódolású értékekre. Másrészt - a web nem így működik: igen, felfedezik az URI-kat, de könyvjelzővel is ellátják őket.
Finom, de fontos megkülönböztetés az API fejlődése - a régi URI-knak továbbra is működniük kell, de minden ügyfélnek, aki felfedezi az API-t, fel kell fedeznie az új URI-kat - ami lehetővé teszi az API dinamikus változását, és a jó kliensek akkor is jól működnek, ha a API-változtatások.
Összegzésképpen - csak azért, mert a RESTful webszolgáltatás összes URI-ját hűvös URI-nak kell tekinteni (és a hűvös URI-k nem változnak) - ez nem azt jelenti, hogy a HATEOAS-korlátozás betartása nem rendkívül hasznos az API fejlesztésekor.
6. A felfedezhetőség figyelmeztetései
Ahogyan az előző cikkek körüli vitákból kiderül, a felfedezhetőség első célja, hogy minimálisan vagy egyáltalán nem használja a dokumentációt és az ügyfél megtanulja és megérti az API használatát a kapott válaszokon keresztül.
Valójában ezt nem szabad ilyen elrugaszkodott ideálnak tekinteni - így használjuk fel minden új weboldalt - mindenféle dokumentáció nélkül. Tehát, ha a koncepció a REST összefüggésében problematikusabb, akkor technikai megvalósításról van szó, nem pedig arról, hogy lehetséges-e vagy sem.
Ennek ellenére technikailag még mindig távol állunk a teljesen működő megoldástól - a specifikáció és a kerettámogatás még fejlődik, és emiatt kompromisszumokat kell kötnünk.
7. Következtetés
Ez a cikk a felfedezhetőség néhány tulajdonságának megvalósítását ismertette a RESTful szolgáltatás keretében a Spring MVC-vel, és a gyökérben a felfedezhetőség fogalmát érintette.
Ezeknek a példáknak és kódrészleteknek a megvalósítása megtalálható a GitHub-on - ez egy Maven-alapú projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.
REST alsó