Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Spring HATEOAS

Spring HATEOAS

JSUG勉強会 2019その10 SpringOne Platform 2019報告会

Dai Yamasaki

November 15, 2019
Tweet

Other Decks in Programming

Transcript

  1. Migration script 0.x $ ./migrate-to-1.0.sh Migrating Spring HATEOAS references to

    1.0 for files : *.java Adapting ./src/main/java/… … Done! https://github.com/spring-projects/spring-hateoas/tree/master/etc
  2. REST ੒ख़౓ • Level 0
 ҰͭͷURLͱҰͭͷHTTPϝιου • Level 1
 ҟͳΔURLͱҰͭͷHTTPϝιου

    • Level 2
 ҟͳΔURLͱҟͳΔHTTPϝιου • Level 3
 APIͷϨεϙϯεʹϋΠύʔϦϯΫ৘ใΛ࣋ͭ
  3. Hypermedia + REST { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ {

    "rel":"customer", "href":"...", }, { "rel":"self", "href":"...", }] }
  4. Hypermedia + REST { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ {

    “rel":"cancel", "href":"...", }, { "rel":"self", "href":"...", }] }
  5. Why HATEOAS • ϦϯΫ͕Θ͔Ε͹ CRUD ͕Ͱ͖Δ • ϏδωεϩδοΫͷྲྀग़Λආ͚Δ
 ΫϥΠΞϯτ͸ϦϯΫͷ༗ແͰ൑அ •

    ϖʔδϯάͷදݱʹ໎Θͳ͍ { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ { “rel":"cancel", "href":"...", }, { "rel":"self", "href":"...", }] }
  6. Links & Affordances { "name": "Dai Yamasaki", "role": "Developer", "_links":

    { "self": { "href": “/employees/0" }, "employees": { "href": "/employees" } }, "_templates": { "default": { "method": "put", "properties": [ { "name": "name", "required": true }, { "name": "role" } ] }, "partiallyUpdateEmployee": { "method": "patch", "properties": [ { "name": "name" }, { "name": "role" } …
  7. Links & Affordances @GetMapping("/employees/{id}") public EntityModel<Employee> findOne(@PathVariable Integer id) {

    Employee employee = employeeRepository.findOneById(id); // ࣗ෼ࣗ਎ "self" ͷϦϯΫΛ࡞੒ WebMvcEmployeeController controller = methodOn(WebMvcEmployeeController.class); Link findOneLink = linkTo(controller.findOne(id)).withSelfRel(); // Affordance ΛؚΊͨ৘ใΛฦ͢ return new EntityModel<>( employee, findOneLink .andAffordance( afford(controller.updateEmployee(null, id))) .andAffordance( afford(controller.partiallyUpdateEmployee(null, id)))); }
  8. 4FQBSBUFSFTPVSDF Links & Affordances { "_links": { "my-app:payment": {...}, "curies":

    [ { "name": "my-app", "href": "http://hoge.com/docs/{rel}", "templated": true }] } } IUUQNZBQQDPNEPDTQBZNFOU
  9. *OMJOFSFTPVSDF { ... "_templates": { "default": { "method": "put", "properties":

    [{ "name": "number", "regex": "[0-9]{16}" }] } } } Links & Affordances
  10. 5SBWFSTPO @Test void traverson() { Traverson traverson = new Traverson(baseUri,

    MediaTypes.HAL_JSON); ParameterizedTypeReference<EntityModel<Actor>> typeReference = new ParameterizedTypeReference<EntityModel<Actor>>() {}; EntityModel<Actor> result = traverson.follow("movies", "movie", “actor") .toObject(typeReference); assertThat(result.getContent().name) .isEqualTo("Dwayne Douglas Johnson"); }
  11. 5SBWFSTPO { "_links": { "movie": { "href": "http://localhost:8080/movies/63e0c973-1606-4fe7-b4e3-0de03d2e0c06" } }

    } { "title": "Fast & Furious Presents: Hobbs & Shaw", "_links": { "actor": { "href": "http://localhost:8080/actors/f58ebb17-abd8-48fb-b06c-5a912251631c" } } } { "name": "Dwayne Douglas Johnson" } NPWJFT EntityModel<Actor> result = traverson.follow("movies", "movie", “actor") .toObject(typeReference); NPWJF BDUPS