Java8ベースの Webフレームワークを作ってみた - Java7 EOLを迎えて -
Java7 も本日、EOLを迎えました。 ということで、Java8ベースの Selva という Webフレームワークを作ってみました。
Overview
まずは、最小の コード例
package io.github.chibat.selva.example; import io.github.chibat.selva.App; import io.github.chibat.selva.server.Server; public class FirstApp implements App { public void init() { resource("/").get(req -> text("Hello, World!")); // (1) resource("/users/(.+)") // (2) .get(req -> text("Show " + req.pathParam())) // (3) .post(req -> text("Update " + req.pathParam())); // (4) } public static void main(String[] args) { Server server = new Server(); server.add(FirstApp.class); server.listen(); } }
このmainメソッドを実行すると、アプリケーションサーバが起動し、Webブラウザが起動し、
Hello, World!
と表示されます。(1)のコードが実行されています。
次に以下のコマンドを実行してみます。 (2)で指定している正規表現でURLのパスが解析され、パスパラメータとして(3)で利用しています。
$ curl -x GET http://localhost:8080/users/chiba Show chiba
次にHTTPメソッドをPOSTに変更すると(4)のコードが実行されます。
$ curl -x POST http://localhost:8080/users/chiba Update chiba
一見 Sinatra風なフレームワークに見えるかもしれませんが、素のサーブレットの構成に近いと思っています。 Sinatra風だとリソース(パスパターン)とHTTPメソッドが1対1で結びつきますが、このSelvaは、一つのリソースが複数のHTTPメソッドを持ちます。 この構成の方が、自然かと思ったので。(実はSinatraよく分かってない)
Features
実装した機能を列挙します。
Request に関する処理
- リクエストとHandlerオブジェクトのルーティング
- URLパスパターンによる、パスパラメータの取得
- リクエストパラメータをbeanにマッピング
- バリデーション(Hibernate validatorに依存)
Response の種類
種類 | メソッド | 依存 |
---|---|---|
Plain Text | text | |
HTML Template | template | Thymeleaf |
JSON | json | Jackson |
Redirect | redirect | |
Forward | forward | - |
その他
maven レポジトリの利用
今は、Maven Central じゃなく jCenter なんですかね。'Forget Maven Central'とか書かれてる。ということで jCenter にモジュールを登録してみました。
selva-core
selva-core 自体は、特定のサーブレットコンテナに依存しないため、任意のサーブレットコンテナで動作させるパターンで使えます。build.gradle は以下のように書きます。pom.xml の書き方は忘れました。
apply plugin: 'java' repositories { jcenter() } dependencies { compile 'io.github.chibat:selva-core:0.0.+' }
selva-jetty
selva-jetty モジュールを使うと、アプリケーション内にJettyを組み込んで起動できます。build.gradle は以下のように書きます。
apply plugin: 'java' repositories { jcenter() } dependencies { compile 'io.github.chibat:selva-jetty:0.0.+' }
Example アプリの起動
Download ダウンロードして展開します。
起動
$ gradlew selva-example:run
サーバが起動し、Webブラウザが起動します。
Executable Jar の作成 & 起動
$ gradlew selva-example:jar $ java -Dfile.encoding=UTF-8 -jar selva-example/build/libs/selva-example-0.0.0.jar
同じく、サーバが起動し、Webブラウザが起動します。Windowsの場合は、ディレクトリセパレタを\
で。
TODO
思いつくTODOを。
- コメント書くw
- テスト書くw
- selva-core は、依存ライブラリをなくす。
- モジュール分割してプラグイン的な仕組みにする。
- 拡張性が低いのでそこんとこ考える。
- 国際化機能
- Tomcat や Undertow 組み込みでの起動
- DBアクセス機能
- TypeScript の呼び出し用クライアントコード自動生成機能。(無理そう)
感想
- 以前だとフレームワーク作るとなるとリフレクションは必須だし、アノテーションは使った方が良いしとなってましたが、Java8 のラムダベースでシンプルなフレームワークが作れるなーと思いました。
- bintray, jcenter へのモジュール登録を初めてしましたが、予想外に簡単でした。
- eclipseでチェーンメソッド + ラムダのコードに綺麗にフォーマッタかけることできん。と思いました。
- Gradle のマルチプロジェクトも初めて使ってみましたが、便利ですね。
以上