今回はBuilding a Hypermedia-Driven RESTful Web Serviceをやってみようと思う。
Hypermediaってどういうことやろうかと思っていたんだけれども、どうもJSONで色々返すことのようだ。
hypermedia-driven RESTは、Spring HATEOASというライブラリを使うらしい。これを使うとSpring MVCのコントローラーとリソースを簡単に設定できる(?)ようである。
まずはbuild.gradleを編集する
dependencies { // compile("org.springframework.boot:spring-boot-starter-web:1.2.2.RELEASE") // compile("org.springframework.boot:spring-boot-starter-actuator:1.2.2.RELEASE") compile("org.springframework.boot:spring-boot-starter-thymeleaf:1.2.2.RELEASE") // compile("org.springframework.boot:spring-boot-starter-security:1.2.2.RELEASE") compile("org.springframework.boot:spring-boot-starter-data-rest:1.2.2.RELEASE") compile("org.springframework.boot:spring-boot-starter-data-jpa:1.2.2.RELEASE") compile("com.h2database:h2:1.4.183") compile("org.webjars:jquery:2.1.3") testCompile("org.springframework.boot:spring-boot-starter-test:1.2.2.RELEASE") compile("com.fasterxml.jackson.core:jackson-databind") compile("org.springframework.hateoas:spring-hateoas") compile("org.springframework.plugin:spring-plugin-core:1.1.0.RELEASE") compile("com.jayway.jsonpath:json-path:0.9.1") }
gradle buildDependentsを実行しておく。
リソースにアクセスするためのクラスを作成
ここでは/greetingにアクセスしたらJSONを返すクラスを作るようなのだが、Greetingクラスを作ると前に作ったものとバッティングしそうなので、違うクラスを作成してみる。
ResourceSupportクラスを継承したら、Spring HATEOASに則ったモデルクラスが作れるらしい(適当に読んでいるので違う気もする)。あとはシンプルなPOJOを作るだけ。コンストラクタで代入とgetterを作ってねーと書いてある。
ちなみに私は未だにPOJOってのがなんなのかわかっていないのでついでに調べてみる。
シンプルなJavaのオブジェクトのことを指すらしい…。なんだろう、通常のクラスが色々脚色されすぎたせいで、普通のクラスが普通という感じがしなくなったからプレーンなやつのことをわざわざPOJOと呼ぶのか。
で、サンプルコードを参考に作ったのが以下のコードとなる。
package sample; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.hateoas.ResourceSupport; public class Happy extends ResourceSupport { private final String content; @JsonCreator public Happy(@JsonProperty("content") String content) { this.content = content; } public String getContent() { return content; } }
アノテーションが付いてるんだけれども、これもPOJOなんか?どこからがPOJOでどこからばPOJOでないのかがわからない。@JsonCreaterと@JsonPropertyがあると、Jacksonでインスタンスを生成するときに捗る、みたいに書いてある。こうしておくとJacksonがHappyクラスを自動でJSONにしてくれるらしい。
モデルはできたので次はコントローラーを作ってみよう。
HappyControllerを作ってみる
あとはHappyモデルを返すHappyControllerを作ってみる。
HappyControllerは@Controllerアノテーションを使うことと、@RequestMappingアノテーション、@ResponseBodyアノテーションを使う。
package sample; import org.springframework.http.HttpEntity; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*; @Controller public class HappyController { private static final String TEMPLATE = "Hello, %s"; @RequestMapping("/happy") @ResponseBody public HttpEntity<Happy> happy( @RequestParam(value = "name", required = false, defaultValue = "Happy") String name ) { Happy happy = new Happy(String.format(TEMPLATE, name)); happy.add(linkTo(methodOn(HappyController.class).happy(name)).withSelfRel()); return new ResponseEntity<Happy>(happy, HttpStatus.OK); } }
linkToメソッド、methodOnメソッド、withSelfRelメソッドなどが、ここの面白いところ(らしい)。HappyモデルはResourceSupportを継承しているので、addメソッドでlinkを追加できる。引数として、Linkクラスのインスタンスが必要なのだが、それをControllerLinkBuilderのメソッドで作っているらしい。
アプリケーションを起動する
ここまできたらあとは起動するだけ。いつものやつを打つ。
gradle bootRun
これで、http://localhost:8080/happy にアクセスしたら、JSONを返してくれる。
うーん、できたはできたのだが、Javaはアノテーションを使いまくる感じがするのだが、アノテーションってそんなにみんな覚えていられるものなのだろうか?いまいちお手軽さを感じられないのだが…。慣れのような気はするけれど、なんとなくモヤモヤする。