Spring BootでWebアプリケーションに"必要な機能"を揃えてみる
Webを参考にSpring Bootを使ってWebアプリケーションに"必要な機能"を揃えてみる。
必要な機能
"必要な機能"として、以下のようなものをサンプルとして含めてみた
- 設定による開発環境、本番環境の設定切り替え
- propertyや、ログの設定など
- HTMLを返すコントローラ(@Controller)
- JSONを返すコントローラ(@RestController)
- パラメータにより、200以外にも400系を返したいといった例も
- HTML生成に、テンプレートエンジンを利用
- thymeleafを利用
- js,cssの利用
- HTMLに表示するメッセージの国際化
- フォームのバリデーション
- エラーの表示機能と、その国際化
- DBへの永続化
- jpaを利用
- jodatimeの利用
- csrfトークンの利用
- テスト
- 統合テストや、ComponentをMockするようなテスト
web.xmlみたいなものは極力避けたい気持ちで、まぁそこそこに。
所感
Springの持つ世界観を軽く理解出来たのは良かった。
Spring Boot
そもそもSpring Boot以前にSpring自体も触ったことがなかったが、軽くWebで検索したりサンプルを眺めた所、各種ライブラリのバージョン互換の管理など、Spring Bootで管理してもらえるところはそちらに任せてしまうのが良い気がした。一方、Spring Bootの対応が遅れても、結局はSpring BootはSpringの各ライブラリなどを統合してるだけのものなので、適宜こちら側で変更・上書きが効く。今回で言えば、spring-boot-securityの対応版がform
に対して自動的にcsrfトークンを付与しないものになっていたので、代わりとして、spring-security-webとspring-security-configを入れる事で実装が出来た。logbackの設定も、当然こちら側に置けた。これを何度となくするとSpringで良いのでは...などとなってしまうが、まぁそこは状況によりけりで。
thymeleaf
thymeleafを利用したのは、静的ファイルとしても可読性のあるものが表示できるためである。デザイナがサーバを立ち上げたりせず、静的ファイルとして記述したhtmlを、こちらからthymeleafの記述を一部足すだけで利用が出来る。言ってしまえば、あちらが書いたhtmlに書き加えたものを再度共有すれば、消したり足したりをお互いがしたりする事は無くなる。
jpa
分かりやすいAPIが用意されていたり、複雑なクエリも@Query
を用いて自分でクエリをjavaのソースの中にSQL文を書けるのが良い。JpaRepositoryを使うと分かりやすいAPIがシュッと増えるのだが、findOne
がOptionalを返して欲しいといった要求の中でもspringが提供するRepositoryを用いて、適切な名前のメソッドにする事で簡単にそれらのクエリを用いる事ができる。ついでに利用しているAPIがどれかってのも分かるし、自分はRepositoryを使う方が性にあってる。別の話になるが、永続化層との間に情報を保つ層を置いてflush
すれば反映される、みたいな世界観は一度体験した中ではあまり良い思い出がなかった。その時のものに比べてこちらの方はより多くの人に使われてる事からその辺はましになってると信じたい。
テスト
サービスのテストにモックを入れたりするのはうまくいった。一方コントローラのユニットテストに、モックを挟むことは出来たのだが、コントローラ毎にアプリケーションが立ち上がるようになってしまっているため、どうにかしたい。誰かうまい方法を教えて欲しい。そもそも今回のような簡単な例に対しては、個人的にはテスト用のDBがあるしそこまでの過程にモックを入れる必要はそんな無い気がしている。メールを送ったり外部APIを叩いたりする以外には、そこまでモックは利用しなくて良いのでは...。まぁ色んな人の考えがあるだろう。
諸々
Springのパスは、1つのパスの情報は分割せずに1箇所にまとめたい。Controllerに/foos/
って書いてメソッドに/list
とか書いてるやつ、grepしづらいしやりたくない。せめて同じパスのGETとPOSTを分けたいなら、1つの変数に/foos/list
って書いてそれ使うだけにして欲しい。web.xmlにその辺の情報まで書き出すとだいぶ厳しい。Pathsみたいな定数値置くクラス作るのは結構ありだと思う。リダイレクトも文字列でやってるし、Pathsに定数とリダイレクト用のメソッドとか、viewで参照出来るメソッドとか生やすともっと良くなると思う。@PathVariable
とpathの情報が離れた場所にあるってのだけが懸念点だけど、それぐらい諦めてもまだいける。pathが変更になった時に変更箇所が分からない方がつらすぎる。
いじったらそれっぽいの出来た
Controllerなどでstaticに呼び出すPath
と、dialect作るためのPathAlias
みたいなクラスがあるのが微妙だ
ちなみに
Java8書いてるとこういうのが欲しくなる
あと
こういう感じです