RestResponder のビュー選択ロジック
- Controller クラスで respond メソッドを打った時の挙動についてわかったことをダラダラ書いておく
前提
- Grails で rest profile でアプリを作成しているとき
- Grails は 3.2.4 のときの挙動
RestResponder って…?
- rest profile で起動すると、Controller クラスに勝手に implements されるクラス(trait)
respond メソッドが打たれた時の大まかな流れ
ソース
流れ
RestResponder#render()
RestResponder#internalRespond()
- リクエストの MIME タイプから適切なレスポンス MIME タイプを入れる
RendererRegistry
から MIME タイプ、respond メソッドに指定されたオブジェクトクラス、オブジェクトから適切な Renderer
を引っ張ってくる
RendererRegistry
は特に指定してなければ、 org.grails.plugins.web.rest.render.DefaultRendererRegistry
クラスのインスタンスが作られる
Renderer
も特に設定しなければ grails.plugin.json.renderer.JsonViewJsonRenderer
クラスのインスタンスが返ってくる
- 実装はほとんど
grails.views.mvc.renderer.DefaultViewRenderer
- 実は
org.springframework.validation.Errors
クラスのインスタンスが引数に指定されたときは処理ロジックが違ったり…
DefaultViewRenderer#render()
- こいつが本命
- Controller クラスで指定されたオプションの解釈、テンプレートの解決、描画まですべて受け持っている
テンプレートの解決方法
ビュー名
の解決
respond
メソッド呼び出し時に渡した view
オプション
- なければ、アクション名
ビュー URI
の解決
- ビュー名が
/
から始まっている場合はそのまま使う
- それ以外の場合は
/${コントローラ名}/${ビュー名}
を設定する
- namespace が指定されている場合はさらに頭に
/${namespace}
を追加する
- ここまでで一度テンプレートファイルがあるかどうか探してみる
- 見つからなければ、
respond
メソッド呼び出し時に渡したオブジェクトのクラスから適切なテンプレートを探す
- ここでも見つからなければ
object/_object.gson
に落ちる
RestResponder にまつわるTips
respond
に渡したインスタンスに対応するテンプレートで描画されない!
respond
に渡しているインスタンスは、あるモデルクラスの関連クラスのインスタンスを渡していませんか?
- 渡している場合は、そのインスタンスのクラス名を要チェキ
- 以下のようになっている場合は、そのまま渡してもテンプレート解決できない
class jp.co.hoge.domain.user.Worker_$$_jvst806_3
なんかくっついてる ^^^^^^^^^^^^^
- 以下のようにビュー名を直接指定して、テンプレートを見つけさせる
respond([mission: mission], view: '/mission/_mission')
- 渡すモデル、ビュー名は全部しっかり指定する
- インスタンスのクラス名に余分なものがついているので、Grails によるモデルの補完、ビュー名の解決はうまく動かない