Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Spring HATEOAS
Search
Dai Yamasaki
November 15, 2019
Programming
0
1.2k
Spring HATEOAS
JSUG勉強会 2019その10 SpringOne Platform 2019報告会
Dai Yamasaki
November 15, 2019
Tweet
Share
Other Decks in Programming
See All in Programming
Feature Toggle は捨てやすく使おう
gennei
0
300
S3ストレージクラスの「見える」「ある」「使える」は全部違う ─ 体験から見た、仕様の深淵を覗く
ya_ma23
0
940
Pythonデータ分析コトハジメinFukuoka
kanan
0
100
PHP でエミュレータを自作して Ubuntu を動かそう
m3m0r7
PRO
2
140
KagglerがMixSeekを触ってみた
morim
0
110
OTP を自動で入力する裏技
megabitsenmzq
0
120
社内規程RAGの精度を73.3% → 100%に改善した話
oharu121
13
8.3k
PHPで TLSのプロトコルを実装してみる
higaki_program
0
420
GC言語のWasm化とComponent Modelサポートの実践と課題 - Scalaの場合
tanishiking
0
120
Symfony + NelmioApiDocBundle を使った スキーマ駆動開発 / Schema Driven Development with NelmioApiDocBundle
okashoi
0
210
脱 雰囲気実装!AgentCoreを良い感じにWEBアプリケーションに組み込むために
takuyay0ne
3
390
Fundamentals of Software Engineering In the Age of AI
therealdanvega
2
290
Featured
See All Featured
Rails Girls Zürich Keynote
gr2m
96
14k
4 Signs Your Business is Dying
shpigford
187
22k
Designing for Timeless Needs
cassininazir
0
170
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
180
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
GraphQLとの向き合い方2022年版
quramy
50
14k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
110
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Test your architecture with Archunit
thirion
1
2.2k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
61k
Transcript
4QSJOH)"5&0"4 %BJ:BNBTBLJ 5BHCBOHFST *OD
Who am I •Dai Yamasaki •Born to develop •I k6o
dislike Tokyo
r,BNFIBNFIB*** ΧΠέΞΦϦ l6B.BVLF&BPLBb⒖JOBJLB1POP ʢʮͷੜ໋ʢ㲈ओݖʣਖ਼ٛʹΑͬͯӬଓ͢Δʯʣz
Spring HATEOAS - Hypermedia APIs with Spring https://www.youtube.com/watch?v=o4cc6KzNrpI&list=PLAdzTan_eSPRlQ8t4TU5c-AB4SHV939M6&index=46
Who use HATEOAS
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
Hypermedia -JOL -JOL -JOL -JOL
REST ख़ • Level 0 ҰͭͷURLͱҰͭͷHTTPϝιου • Level 1 ҟͳΔURLͱҰͭͷHTTPϝιου
• Level 2 ҟͳΔURLͱҟͳΔHTTPϝιου • Level 3 APIͷϨεϙϯεʹϋΠύʔϦϯΫใΛ࣋ͭ
Hypermedia + REST { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ {
"rel":"customer", "href":"...", }, { "rel":"self", "href":"...", }] }
Hypermedia As The Engine Of Application State H A T
E O A S HATEOAS
Hypermedia + REST { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ {
“rel":"cancel", "href":"...", }, { "rel":"self", "href":"...", }] }
Why HATEOAS • ϦϯΫ͕Θ͔Ε CRUD ͕Ͱ͖Δ • ϏδωεϩδοΫͷྲྀग़Λආ͚Δ ΫϥΠΞϯτϦϯΫͷ༗ແͰஅ •
ϖʔδϯάͷදݱʹ໎Θͳ͍ { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ { “rel":"cancel", "href":"...", }, { "rel":"self", "href":"...", }] }
Spring HATEOAS
Representation Model
Representation Model
Links & Affordance
ΞϑΥʔμϯεʢaffordanceʣͱɺ ڥ͕ಈʹରͯ͠༩͑Δʮҙຯʯͷ͜ͱͰ͋Δɻ ΞϝϦΧͷ֮৺ཧֶऀδΣʔϜζɾJɾΪϒιϯʹΑΔޠͰ͋Γɺ ੜଶޫֶɺੜଶ৺ཧֶͷجఈత֓೦Ͱ͋Δɻ ʮ༩͑Δɺఏڙ͢Δʯͱ͍͏ҙຯͷӳޠ afford ͔ΒΒΕͨɻ Affordances
Affordance https://www.amazon.co.jp/%E3%82%B5%E3%83%B3%E3%82%A2%E3%83%BC%E3%83%88-%E3%81%8A%E3%82%82%E3%81%97%E3%82%8D%E9%A3%9F%E5%99%A8-4%E6%96%87%E5%AD%97%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC- %E3%83%9E%E3%82%B0%E3%82%AB%E3%83%83%E3%83%97-SAN1858/dp/B003NEPOTW
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" } …
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)))); }
4FQBSBUFSFTPVSDF Links & Affordances { "_links": { "my-app:payment": {...}, "curies":
[ { "name": "my-app", "href": "http://hoge.com/docs/{rel}", "templated": true }] } } IUUQNZBQQDPNEPDTQBZNFOU
*OMJOFSFTPVSDF { ... "_templates": { "default": { "method": "put", "properties":
[{ "name": "number", "regex": "[0-9]{16}" }] } } } Links & Affordances
.FEJB5ZQFT
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"); }
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
0UIFS • RepresentationModelAssembler • I18N support • LinkRelationProvider
5IBOLT