2016年7月25日月曜日

【JavaでPlayFramwork2.4.6】Grobal.java

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

最近はPlayFrameworkについて勉強を進めています。

前回まででプロジェクトの作成に成功したところで、今回はいよいよ細かい機能の確認に入っていきたいと思います。
今回のテーマは「Grobal.java」です。

Grobal.java


公式の参考ページは以下です。


上記はバージョンPlay2.3の話です。
本ブログで取り扱うのは2.4.6ですが、公式そのものが枯れていないので公式に無い話を取り扱うのもやむなし。
頑張っていきましょう。

役割


まず、Grobalクラスの役割は全てのコントローラクラスの総合継承クラスとでも言いましょうか。
本来コントローラが担当するURLリクエスト活動の親クラスとしての他、システムの初回起動時専用など全体的な共通処理を担当するクラスです。

従って、

  • システム初回起動時に一回だけ行いたい処理
  • 各URLのリクエスト時に毎回実行したい処理

この辺りがGrobalクラスの役割と言えるでしょう。

特徴


Grobalクラスの特徴は、やはりクラス名が「Grobal」であるということです。
「Grobal2」とかちょっとクラス名を変えただけで動きません。
そう、Grobalクラスは、場所がルート直下で、クラス名がGrobal.javaであるというネーミング規約があります。

後は、「GlobalSettingsクラス」を継承しているという点くらいでしょうか。

public class Global extends GlobalSettings {


私が特徴に思うのは、やっぱり「Grobal.java」であることというネーミング規約が敷かれている点でしょうか。
「Grobal2」とかちょっとでも違うネーミングにするともう動きません。

外部ファイル名ではなくJava本体のクラス名にこのような規約を設定するのはJavaプログラミングでは余り見かけない特徴だと思います。
この辺りがscalaベースとしているPlayFramworkの特徴でしょう。

このように、JavaがJavaクラスのクラスやメソッドを「文字列として認識」して振り分けるという機能を「リフレクション」と言います。

メタプログラミングと言い換えても良いでしょうか。

普通にシステム開発者として従事している間は余り需要はありあせんが、ライブラリ開発社の立場からすると偶に裏技として出番がある時があります。
「こういう使い道もある」という程度に覚えておくと良いかもしれませんね。


各メソッド


Global.javaが実現する機能は親クラスであるGlobalSettingsの実装に準拠しています。


public class GlobalSettings {

    /**
     * Executed before any plugin - you can set-up your database schema here, for instance.
     */
    public void beforeStart(Application app) {
    }

    /**
     * Executed after all plugins, including the database set-up with Evolutions and the EBean wrapper.
     * This is a good place to execute some of your application code to create entries, for instance.
     */
    public void onStart(Application app) {
    }

    /**
     * Executed when the application stops.
     */
    public void onStop(Application app) {
    }

    /**
     * Called when an exception occurred.
     *
     * The default is to send the framework's default error page. This is achieved by returning null,
     * so that the Scala engine handles the excepetion and shows an error page.
     *
     * By overriding this method one can provide an alternative error page.
     *
     * @param t is any throwable
     * @return null as the default implementation
     */
    public F.Promise onError(RequestHeader request, Throwable t) {
        return null;
    }

    /**
     * Call to create the root Action of a request for a Java application.
     * The request and actionMethod values are passed for information.
     *
     * @param request The HTTP Request
     * @param actionMethod The action method containing the user code for this Action.
     * @return The default implementation returns a raw Action calling the method.
     */
    @SuppressWarnings("rawtypes")
    public Action onRequest(Request request, Method actionMethod) {
        return new Action.Simple() {
            public F.Promise call(Context ctx) throws Throwable {
                return delegate.call(ctx);
            }
        };
    }

    /**
    *
    * Called when an HTTP request has been received.
    * The default implementation (return null) means to use the application router to find the appropriate action
    *
    * By overriding this method one can provide an alternative routing mechanism.
    * Please note, though, this API is very low level, useful for plugin/module authors only.
    *
    * @param request the HTTP request header as seen by the core framework (the body has not been parsed yet)
    * @return an action to handle this request - if no action is returned, a 404 not found result will be sent to client
    */
    public play.api.mvc.Handler onRouteRequest(RequestHeader request) {
        return null;
    }

    /**
     * Called when no action was found to serve a request.
     *
     * The default behavior is to render the framework's default 404 page. This is achieved by returning null,
     * so that the Scala engine handles onHandlerNotFound.
     *
     * By overriding this method one can provide an alternative 404 page.
     *
     * @param request the HTTP request
     * @return null in the default implementation, you can return your own custom Result in your Global class.
     */
    public F.Promise onHandlerNotFound(RequestHeader request) {
        return null;
    }

    /**
     * Called when an action has been found, but the request parsing has failed.
     *
     * The default behavior is to render the framework's default 400 page. This is achieved by returning null,
     * so that the Scala engine handles onBadRequest.
     *
     * By overriding this method one can provide an alternative 400 page.
     *
     * @param request the HTTP request
     * @return null in the default implementation, you can return your own custom Result in your Global class.
     */
    public F.Promise onBadRequest(RequestHeader request, String error) {
        return null;
    }

    /**
     * Get the filters that should be used to handle each request.
     */
    public  Class[] filters() {
        return new Class[0];
    }

}


メソッドを抜き出すと以下です。

  • beforeStart
  • onStart
  • onStop
  • onError
  • onRequest
  • onRouteRequest
  • onHandlerNotFound
  • onBadRequest
  • filters

色々ありますね……。

このうち、私が現在のシステム開発で必要としているのは以下です。

  • beforeStart:システム初回起動
  • onRequest:各種リクエスト実行時
  • filters:フィルター

beforeStartメソッドというのはシステムで最初にリクエストを受けた時だけ実行されるメソッドです。
シングルトンクラスの初期化などで実行するのが良いでしょう。

onRequestメソッドはリクエスト毎に毎回実行。

filtersメソッドは、onRequestに連動しているものです。

各種リクエストの開始終了ログなど、システムの最初に用意するログ機構についてはこの辺りが活躍するわけですね。

終わりに


次回はログ出力の手法についてご紹介したいと思います。

0 件のコメント:

コメントを投稿