2016年9月27日火曜日

【JavaでPlayFramwork2.4.6】routesファイル

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

ただ今、もうすぐ始まるプロジェクトの実装で使用するPlayFrameworkについて事前勉強を進めています。


今回はURLを制御するroutesファイルについてご紹介します。

伝説のXML地獄


JavaWebシステム業界では長年の間、Struts1が支配的な地位を占めてきました。
そこで常に大問題を起こしてきたのが「struts-config.xml」「web.xml」という巨大XMLです。

コイツラはWebシステムが受け付けるURLを制御したり、そのリクエストを行った際に取得するパラメータを格納するFormや、遷移先のjspなど、WebシステムのWeb部分を管轄する設定ファイル達です。

欠点は、もの凄く煩雑なんですよね!!

基本的にココで躓くのは新人レベルの人なのですが、XMLなんでちょっと壊れただけでも動かなくなりますし、設定が間違っていても動かないし、ログを追うのも難しいし、と不慣れな若手プログラマーの未来の芽を摘むのに多大な役割を果してきました。

更にORMappingにSpringとHibernateを導入すれば完璧。

今やJavaWebシステム業界の金字塔とも言える究極のXML地獄が完成します。

これね、慣れれば分かるんですよ。でも不慣れだと全然分からない。
だから自分が数年の月日を経て手慣れてきても、その頃には会社には後輩が入ってきているわけで、「何か動かないんですけど~」と単体環境で起動も出来ないような始末になっていることは日常茶飯事。

あのXML地獄は最悪だとみんな身に染みて分かっているんですね。
そうして出てきた概念が、あの有名なRubyOnRailsのキャッチフレーズ、

「設定より規約」

です。

一言で言いますと、「ファイル名、クラス名を合わせておけばXMLは省略出来るよ」というものです。

RubyOnRailsの命脈を引き継ぐPlayFramworkもこの思想がありまして、膨大な設定ファイルを多数記述しなくても、ある程度の命名規約に則してソースを作っておくだけでとりあえず動いてくれる。

もう「設定より規約」はRubyOnRailsがどうこうと言うより、Webシステム業界の基本概念と言って良いくらいになってきましたね。

今回はPlayFramworkでURL制御をする為のやり方を検証してみたいと思います。

コントローラ


まず最初にリクエストを叩いた直後に呼び出されるクラス「コントローラ」を作成します。

public class LoginController extends Controller {
 /**
  * @return Result
  */
 public Result index() {

  Form userForm = Form.form(LoginForm.class);

  return ok(views.html.layout.login.render(userForm));
 }

}


命名規約と言っておいてなんですが、実際には「Controllerクラスを継承する」という点だけ守っておけばOKです。

しかし、ここで特徴が一つ。
コントローラを格納するcontrollersパッケージはルート直下に置くのがオススメです。


普通はJavaのパッケージって言うと組織を表現する長~いフルパスを指定するものじゃないですか?
弊社ジェニシスで言えば「jp.co.net.genesis.controllers」というパッケージにするのがJava業界のお約束ですが、PlayFrameworkはいきなり「controllers」だけにするのが普通です。

理由は後述します。

routesファイル


クラスを作ったところで、次にURLの定義に移ります。

上記「LoginController」のメソッド「index」とURLリクエストを結びつけるには、confフォルダ配下のroutesファイルに以下のように記述すればOKです。


GET     /                           controllers.LoginController.index()
GET     /login/                           controllers.LoginController.index()


見た目そのままかと。簡単ですね。

RubyOnRailsと違い「LoginというURLを打ち込めば自動的にLoginクラス」という挙動はありません。
「設定より規約」の思想を受け継ぎつつも、この辺りは「規約より設定の方が便利」という崩しが入っているんですね。

ほら、上記の例だと「URLに何も入力しなかったら自動的にログインを表示」という挙動も簡単に表現できます。
このくらいが自動化するのに丁度良い塩梅だと考えたのでしょう。

また、従来のStruts1のAction方式が「1URL1アクションクラス」だったのに対し、PlayFrameworkのコントローラはメソッド分けにも対応しています。
なのでクラス数が膨大に増えていってしまう問題が解消されている一方、URL設計をちゃんとやらないと1クラスにメソッドが大量終結してしまう欠点があります。
この辺りは設計者の腕の見せ所ですね。

しかし、ここで注意事項。

  • controllers.LoginController.index()

「controllers」という文字がありますね。そう、このroutesファイルの記述はフルパスなんですよ。
これが上記でルート直下をオススメした理由です。

もし「jp.co.net.genesis.controllers」と書いてしまうと、記述がこうなります。

  • jp.co.net.genesis.controllers.LoginController.index()

長いんですよ。
もちろん1システムにURL数は数十~数百まで沢山ありますから、もし会社名まで含めたパッケージにしてしまうと、routesファイルは以下のようになってしまいます。


  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()

これは冗長でしょう!!

気にしなければ良いと言えばそれだけなのですが、PlayFrameworkは軽快にアプリケーションを作っていくという思想がありますから、「フルパスがどれだけ長かろうがコピペするだけなんだから作業効率は変わらん」ということは分かりつつも、
出来るだけ記述する文字数を減らすのがPlayFramework。

伝統的なJavaエンジニアにはちょっと気持ち悪いですが、ここはルートフォルダ直下にcontrollersパッケージを置くのがPlayFrameworkの標準かな、という所感です。

終わりに


これでURL制御は終わりです。
PlayFrameworkの簡単さがよく分かる一例だったと思います。

引き続きPlayFrameworkの検証を進めます。

0 件のコメント:

コメントを投稿