tilesを使った時のJSPの評価タイミングについて
背景
tilesを使ってJSPファイルを分割+統合(?)したときに、思っていた動きと違った部分があったのでメモっときます。結論
tilesで分割したJSPはそれぞれで評価される(=tilesで統合したあとの構造で評価はされない)。前提
以下のようなファイルの配置の例で記載します。(一部略)/WEB-INF |- /tiles/definition.xml |- /views/common |-layout.jsp |-navigation.jsp
<tiles-definitions> <definition name=".baseLayout" template="/WEB-INF/views/common/layout.jsp"> <put-attribute name="header" value="/WEB-INF/views/common/header.jsp" /> <put-attribute name="navigation" value="/WEB-INF/views/common/navigation.jsp" /> </definition>
<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <html> <head> <tiles:insertAttribute name="header" /> </head> <body> <tiles:insertAttribute name="navigation" /> </body> </html>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script> <script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css"> <link rel="stylesheet" type="text/css" href="./resources/css/custom.css">
- ナビゲーションバー定義
- /WEB-INF/views/common/navigation.jsp
- "app"の部分がこのアプリのコンテキストパス("http://example.com/app/view/users")
(略) <ul class="nav navbar-nav"> <li><a href="app/view/users">一覧を見る<span class="sr-only">(current)</span></a></li> </ul> (略)
最初にやろうと思ったこと
- ヘッダ定義で"./resources/css/custom.css"のように相対パスで定義していたが、パスがあっちこっち行った場合相対パスがうまく一致せずうまく読めなくなった。*1
- ナビゲーションバー定義でコンテキストパスがいろんなところに出てきてメンテが大変そうなので、文字列指定をやめたい。
次にやろうと思ったこと
- コンテキストパスは以下のように定義できるので使う。
- ヘッダ定義で使った例
<c:set var="contextPath" value="${pageContext.request.contextPath}"/> <link rel="stylesheet" type="text/css" href="${contextPath}/resources/css/custom.css">
- この定義はすべての画面でtiles的に取り込まれるので、ナビゲーションバー定義のほうでもそのまま使ってみる。<- この考えが間違い(;´Д`)
(略) <ul class="nav navbar-nav"> <li><a href="${contextPath}/view/users">一覧を見る<span class="sr-only">(current)</span></a></li> </ul> (略)
起きた問題
ナビゲーションバー内のリンクを押しても"http://example.com/view/users"に飛ばされる(=コンテキストパスがない)対応
ナビゲーションバー定義にヘッダ定義にしたようにコンテキストパス定義を書くと、ちゃんと意図した動きになった("http://example.com/app/view/users"への遷移)ので、各JSPごとに評価されていることに気づく。で、結局以下のように定義しました。
/WEB-INF |- /tiles/definition.xml |- /views/common |-layout.jsp |-navigation.jsp |-variable.jsp <- 各種変数定義用JSP
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>
- ヘッダ定義(修正版)
- 定義を読み込む。
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script> <script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> <%@ include file="variable.jsp" %> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css"> <link rel="stylesheet" type="text/css" href="${contextPath}/resources/css/custom.css">
- ナビゲーションバー定義(修正版)
- 定義を読み込む。
<%@ include file="variable.jsp" %> (略) <ul class="nav navbar-nav"> <li><a href="${contextPath}/view/users">一覧を見る<span class="sr-only">(current)</span></a></li> </ul> (略)
各JSPが評価され統合されたものがtilesで統合されクライアントに返却される。
まとめ
- その他の定義(scriptやstylesheet)とかは、クライアント側(ブラウザ)で全体を受け取ってから解釈がスタートするので、定義を分離できる。
- 今回のケースは、サーバサイドで値を評価しなければならないので、各JSPで閉じた定義・処理が必要なよう(たぶん)。
- 使っても使われるな(;´Д`)
参考
html - Spring MVC Request URLs in JSP - Stack Overflow*1:そのときの心情である。— なみひ~ら (@namihira_k) 2015, 10月 25