Java Spring Boot その5
前回の続きで POST, PUT, DELETE メソッドを作成をします。
ソース
POST, PUT, DELETE を追加したソースは下記の通りです。
また、モックデータの作成方法を変更しました。
package hello; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.IntStream; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("api/tasks") @EnableAutoConfiguration public class RestSampleController { static class Task { public Task() { } public Task(Integer id, String context) { this.id = id; this.context = context; } public Integer id; public String context; } static Map<Integer, Task> tasks = new HashMap<>(); @RequestMapping(method = RequestMethod.GET) List<Task> getTasks() { // GET api/tasks で実行されるメソッド return new ArrayList<>(tasks.values()); } @RequestMapping(value = "{id}", method = RequestMethod.GET) Task getTask(@PathVariable Integer id) { // GET api/tasks/{id} で実行されるメソッド return tasks.get(id); } @RequestMapping(method = RequestMethod.POST) @ResponseStatus(HttpStatus.CREATED) Task createTask(@RequestBody Task task) { // POST api/tasks で実行されるメソッド int nextIndex = tasks.keySet().stream().max(Comparator.naturalOrder()).get() + 1; task.id = nextIndex; tasks.put(nextIndex, task); return task; } @RequestMapping(value = "{id}", method = RequestMethod.PUT) Task updateTask(@PathVariable Integer id, @RequestBody Task task) { // PUT api/tasks/{id} で実行されるメソッド Task targetTask = tasks.get(id); if (targetTask == null) { return null; } targetTask.context = task.context; tasks.put(id, targetTask); return targetTask; } @RequestMapping(value = "{id}", method = RequestMethod.DELETE) @ResponseStatus(HttpStatus.NO_CONTENT) void deleteTask(@PathVariable Integer id) { // DELETE api/tasks で実行されるメソッド tasks.remove(id); } public static void main(String[] args) { // モックデータ作成 IntStream.range(0, 3).forEach(index -> tasks.put(index, new Task(index, String.format("sample%d", index)))); SpringApplication.run(RestSampleController.class, args); } }
解説
前回解説した通り、@RequestMapping
で POST, PUT, DELETE 各メソッドにマッピングする Java のメソッドを作成しました。
@RequestMapping
今回 @RequestMapping(value = "{id}", method = RequestMethod.GET)
のように value 属性が登場しました。
value は相対パスを指定することができます。なので getTask メソッドは GET "api/tasks/{id}" とマッピングされます。
また value に指定した {id} はメソッドの引数で取得することができます。
取得するためには @PathVariable
アノテーションを付与した 変数を定義します。
@ResponseStatus
ResponseStatus アノテーションは名前の通りですが、レスポンスのステータスを指定することができます。
アノテーションに指定できる値は HttpStatus 型の値です。
HttpStatus は enum となっているので、HttpStatus.CREATED
など視覚的にわかりやすい形で指定できます。
@RequestBody
メソッドの引数に指定されている RequestBody アノテーションですが、
こちらも名前の通りリクエストボディの値をマッピングするためのアノテーションです。
今回、リクエストボディに設定される JSON を Task 型の値にマッピングするために使用しています。
結果
各メソッドを実行した結果をまとめました。
GET api/tasks
$ curl -v http://localhost:8080/api/tasks -X GET * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > GET /api/tasks HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.43.0 > Accept: */* > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Sat, 10 Oct 2015 23:40:31 GMT < * Connection #0 to host localhost left intact [{"id":0,"context":"sample0"},{"id":1,"context":"sample1"},{"id":2,"context":"sample2"}]
全てのタスクが返却されています。
GET api/tasks/{id}
$ curl -v http://localhost:8080/api/tasks/2 -X GET * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > GET /api/tasks/2 HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.43.0 > Accept: */* > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Sat, 10 Oct 2015 23:41:31 GMT < * Connection #0 to host localhost left intact {"id":2,"context":"sample2"}
id で指定したデータが返却されています。
POST api/tasks
$ curl -v http://localhost:8080/api/tasks -X POST -H "Content-Type: application/json" -d "{\"context\" : \"create\"}" * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > POST /api/tasks HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.43.0 > Accept: */* > Content-Type: application/json > Content-Length: 22 > * upload completely sent off: 22 out of 22 bytes < HTTP/1.1 201 Created < Server: Apache-Coyote/1.1 < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Sat, 10 Oct 2015 23:42:14 GMT < * Connection #0 to host localhost left intact {"id":3,"context":"create"}
作成したデータが返却されています。
@ResponseStatus(HttpStatus.CREATED)
を指定したのでレスポンスステータスが HTTP/1.1 201 Created
に変化しています。
PUT api/tasks/{id}
$ curl -v http://localhost:8080/api/tasks/1 -X PUT -H "Content-Type: application/json" -d "{\"context\" : \"update\"}" * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > PUT /api/tasks/1 HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.43.0 > Accept: */* > Content-Type: application/json > Content-Length: 22 > * upload completely sent off: 22 out of 22 bytes < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Sat, 10 Oct 2015 23:42:40 GMT < * Connection #0 to host localhost left intact {"id":1,"context":"update"}
id で指定した要素のデータが更新されています。
DELETE api/tasks/{id}
$ curl -v http://localhost:8080/api/tasks/1 -X DELETE * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > DELETE /api/tasks/1 HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.43.0 > Accept: */* > < HTTP/1.1 204 No Content < Server: Apache-Coyote/1.1 < Date: Sat, 10 Oct 2015 23:42:56 GMT < * Connection #0 to host localhost left intact
@ResponseStatus(HttpStatus.NO_CONTENT)
を指定したので HTTP/1.1 204 No Content
となり
レスポンスもありません。
以上で REST API の作成は完了です。
次回はモック部分のデータを DB とやりとりするよう修正したいと思います。
Java Spring Boot その4
今回は Spring Boot を使って REST API を作ろうと思います。
DB を使わず、モックを使用します。
次回以降、モックの実装を DB を使った実装に修正しようと思います。
一覧取得
まずは一覧を取得するソースのみ
package hello; import java.util.ArrayList; import java.util.List; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("api/tasks") @EnableAutoConfiguration public class RestSampleController { static class Task { Task(String title, String context) { this.title = title; this.context = context; } public String title; public String context; } @RequestMapping(method = RequestMethod.GET) List<Task> getTasks() { List<Task> tasks = new ArrayList<>(); tasks.add(new Task("sample1", "sample1")); tasks.add(new Task("sample2", "sample2")); tasks.add(new Task("sample3", "sample3")); return tasks; } public static void main(String[] args) { SpringApplication.run(RestSampleController.class, args); } }
http://localhost:8080/api/tasks にアクセスすると
[ { "title": "sample1", "context": "sample1" }, { "title": "sample2", "context": "sample2" }, { "title": "sample3", "context": "sample3" } ]
上記内容が返ってくると思います。
※上記 JSON は整形しています
解説
@RequestMapping("api/tasks")
をコントローラクラスに付与することで、このクラスが "api/tasks" とマッピングされます。
@RequestMapping(method = RequestMethod.GET)
を getTasks メソッドに付与することで
GET "api/tasks" が getTasks メソッドにマッピングされます。
同様に POST, PUT, DELETE をマッピングするメソッドを作成すれば、REST API の作成は完了です。
今回はここまで。
Java Spring Boot その3
今回は Spring Loaded について
Spring Loaded とは
Spring Loaded とは Seasar でいう Hot Deploy を可能にするライブラリです。 アプリケーションを再起動することなく、ソースの変更を反映することができます。 これにより生産性を向上することができます。
使い方
Spring Loaded をダウンロード github.com
アプリケーション実行時に JVM パラメータに Spring Loaded を指定
java -javaagent:<pathTo>/springloaded-{VERSION}.jar -noverify SomeJavaClass
サンプル
今回私が試した Eclipse での実行方法をサンプルとして載せます
- Spring Loaded をダウンロード
適当な場所にダウンロード
/path/to/spirng_loaded/springloaded-1.2.4.RELEASE.jar
Run as -> Run Configurations...
VM arguments に
-javaagent:/path/to/spirng_loaded/springloaded-1.2.4.RELEASE.jar -noverify
を指定し、実行
これだけで、変更が即時反映されるようになる
補足
本来は Gradle に依存ライブラリ、JVM パラメータを記載し、gradle bootRun
で Spring Loaded が動くようにしたかった。
Gradle x Spring Loaded x IntelliJ の記事は見つかるが、Eclipse の記事が見つからず、今の所できていない。
一旦動く状態にしたかったため、上記設定で行っている状態である。
解決次第改めて記事を書こうと思う。
Java Spring Boot その2
今回は 前回の記事 の解説を簡単にしようと思います。
package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller @EnableAutoConfiguration public class SampleController { @RequestMapping("/") @ResponseBody String home() { return "Hello Spring Boot!"; } public static void main(String[] args) { SpringApplication.run(SampleController.class, args); } }
@Controller
コントローラを表すアノテーション
@EnableAutoConfiguration
Spring Boot の重要なアノテーション。このアノテーション 1 つで色々な設定を自動で行ってくれる。
XML 等の設定ファイル不要で様々な設定をしてくれるところが有難い。
@RequestMapping
リクエストをメソッドにマッピングするためのアノテーション
上記例でいうと "/" というリクエストあった場合、 home メソッドが呼ばれる。
@ResponseBody
Web のレスポンスボディに値をバインドするためのアノテーション
今回は簡単にこんなところで。
Java Spring Boot
今回は Spring Boot の記事を書こうと思います。
開発メモという形で何回かに分けて上げていこうと思います。
まずは Spring Boot のセットアップから
開発環境
- MacBook Air OS X Yosemite 10.10.5 ( El Capitan に上げないと )
- Java JDK 1.8.0_60
- Gradle 2.7
- Eclipse Mars Release (4.5.0)
セットアップ
Gradle ファイルの作成、Java プロジェクトのディレクトリ構成作成
$ mkdir hello_boot $ cd hello_boot $ gradle init --type java-library # 不要なファイル削除 $ rm src/main/java/Library.java $ rm src/test/java/LibraryTest.java
Spring Boot 用の設定に修正
buildscript { repositories { jcenter() } dependencies { classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.2.6.RELEASE' } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'spring-boot' jar { baseName = 'hello_boot' version = '0.0.1-SNAPSHOT' } repositories { jcenter() } dependencies { compile 'org.springframework.boot:spring-boot-starter-web' testCompile 'org.springframework.boot:spring-boot-starter-test' }
Eclipse 設定ファイルを作成
$ gradle eclipse
サンプルアプリケーションを作成
参考:http://projects.spring.io/spring-boot/
package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller @EnableAutoConfiguration public class SampleController { @RequestMapping("/") @ResponseBody String home() { return "Hello Spring Boot!"; } public static void main(String[] args) { SpringApplication.run(SampleController.class, args); } }
サンプルアプリケーションを実行
$ gradle run
http://localhost:8080/ にアクセスして、Hello Spring Boot!
と表示されれば OK!
Java Spark
ブログを書く時間をうまく確保できてない mmts1007 です。
今回は Java のフレームワーク Spark について書きます。
Java Spark とは
Spark は Java の Web アプリケーションフレームワークです。
Ruby のフレームワーク Sinatra にインスパイアされたフレームワークです。
Java 8 で追加になった ラムダ式 を使うことでシンプルに記述することができます。
特徴
特徴としては前述のとおり
です。
サンプル
Hello Spark
とてもシンプルな例です
ルーティング
Sinatra は HTTP メソッドと URLを元にルーティングを決定します。
Spark は Sinatra にインスパイアされたため、Spark も同様にHTTP メソッドと URLを元にルーティングを決定します。
上記の例だと HTTP メソッド:GET、URL:"/" にリクエストした場合、上記のメソッドが実行されることになります。
シンプルな処理内容の記述
Spark はラムダ式を使用することで、シンプルに記述することができます。
get("URLパス", "処理内容");
となっており、第 2 引数にラムダ式を渡すことができます。
これにより、実際の処理内容をシンプルに記述することが可能となりました。
組み込みサーバ
今までの Web アプリケーションは war ファイルを作成し、それを Tomcat などのアプリケーションサーバにデプロイするのが主流でしたが今は組み込みサーバが流行っています。
サーバが組み込まれていると java -jar xxxx.jar
のように Java コマンドで実行するだけでサーバが起動します。
アプリケーションサーバを用意しなくとも Web アプリケーションが実行できるのはとても楽です。
Rest API
REST API のサンプルとしてタスクの取得/登録/更新/削除のソースの書き方のイメージです。
public class TaskSpark { public static void main(String[] args) { get("/tasks", (req, res) -> { // 1. タスク内容を全て戻す }); get("/tasks/:id", (req, res) -> { // 2. id に指定されたタスクを戻す }); post("/tasks", (req, res) -> { // 3. パラメータに指定された内容でタスクを作成する }); put("/tasks/:id", (req, res) -> { // 4. パラメータに指定された内容で id のタスクを更新する }); delete("/tasks/:id", (req, res) -> { // 5. id に指定されたタスクを削除する }); } }
Sinatra ライクな記述のため、どのようなルーティングなのか分かりやすいです。
get の /tasks のリクエストがきたら 1. が実行される といった形です。
上記のソースのように REST API のような HTTP のメソッドに意味を持たせる場合、分かりやすいフレームワークだと思います。
実際に処理を書いたサンプルが下記のとおりです。
※ DB 処理を書くのが面倒だったので、適当にメモリに保持。ここら辺の記述は適当ですw
new JsonTransformer()
を 引数に与えることで、戻りの型を変換することができます。これは Spark の機能です。
今回は JSON 型に変換したかったので JsonTransformer
クラスを作成し、指定しています。
まとめ
Sinatra ライクな Spark についての紹介でした。
といった Spark の特徴が少しでも分かって頂ければと思います。
Seasar サポート終了
2日に1回書くのがこんなに辛いとは…w もう少し頑張りますw
2015.09.26 に Seasar Conference 2015 が開催されました。
Seasar Conference 2015 | September 26, 2015 @ Hosei University
その中で、Seasar サポート終了 が発表されました。
Seasar 2 を使った開発を 2年位経験していた私にとっては、ビックニュースでした。
本気で次のフレームワークを探さなきゃなと思いました。
と言うことで、移行先に考えているフレームワークを紹介していこうと思います。
(あくまで私の好み、興味です。)
Spring Boot
http://projects.spring.io/spring-boot/
去年の JJUG CCC で知ったフレームワークです。 そこから興味を持ち、JJUG Night Seminer 等に参加しました。
【東京】JJUG ナイト・セミナー「中上級者向け!Spring Bootハンズオン!」3/25(水)開催 | 日本Javaユーザーグループ
本も持ってます!(著者のサイン入り!)
http://www.amazon.co.jp/%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E3%81%AESpring-Boot%E2%80%95%E3%80%8CSpring-Framework%E3%80%8D%E3%81%A7%E7%B0%A1%E5%8D%98Java%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA-I%E3%83%BBO-BOOKS/dp/4777518655www.amazon.co.jp
Spark
Sinatra Like なフレームワークです。
Sinatra が好きな私にとっては嬉しいフレームワークでした。
HTTP のメソッドと Java のメソッドがマッピングされているので、
Resutful API を作るときにはわかりやすいと思います。
LastaFlute
LastaFlute (Javaでリーンスタートアップ) | DBFlute
Seasar Conference 2015 で発表されたフレームワークです。
Seasar を Java 8 でフォークしたフレームワークとのことです。
( LastaFlute 早く触りたい。早く週末になれ!※まだ月曜日 )
それぞれのフレームワークの詳細については個別に書いていこうと思います。
次の記述でまずは Spark について書こうと思います。