Struts1.3.5でTilesを使ってみる

感想おまちしてます!

http://struts.apache.org/1.3.5/struts-tiles/index.html

左にメニューがあって、右にコンテンツ・・・というようなレイアウトを使う場合、tilesを使えば、画面の構成要素の定義ができる。また、継承を使って、画面の一部分だけ変更する・・・という処理も可能。

スポンサーリンク

インストール

pluginとしてstruts-config.xmlに記述する。

<plug-in className="org.apache.struts.tiles.TilesPlugin">
  <set-property property="definitions-config" 
                value="/WEB-INF/tiles-defs.xml" />
 </plug-in>

web.xmlのActionServletに以下のパラメタを追加。

<init-param>
  <param-name>chainConfig</param-name>
  <param-value>
    org/apache/struts/tiles/chain-config.xml
  </param-value>
</init-param>

http://struts.apache.org/1.3.5/struts-tiles/installation.html

レイアウト用JSPの書き方

レイアウト用のJSPにはtailsタグを使ってインクルードする箇所を定義。

<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<tiles:insert attribute="header" flush="true" />
<tiles:insert attribute="content" flush="true" />
<tiles:insert attribute="footer" flush="true" />

attribute属性で指定した名前に対して、tiles-defs.xmlでどのJSPをインクルードするかを指定する。上記ではHTMLを使わずに書いているが、Tableタグなどを使ってレイアウトを決めておけば、「メニューのある画面」などが簡単にできる。

tiles-defs.xml

インサートするJSPを定義する。

XML宣言

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
      "-//Apache Software Foundation//DTD Tiles Configuration 1.3//EN"
      "http://struts.apache.org/dtds/tiles-config_1_3.dtd">

definition

定義名とその定義で使うJSPファイルを指定する。

<definition name="layout" path="/Resources/jsp/Layout.jsp">
  <put name="header" value="/Resources/jsp/Header.jsp" />
  <put name="content" value="/Resources/jsp/Main.jsp" />
  <put name="footer" value="/Resources/jsp/Footer.jsp" />
</definition>

definitionのname属性にはtilesのページ定義名を指定する。これはforwardで指定される名前に対応するため、以下のようにすればこの定義が呼ばれ、Layout.jspに遷移する。

 <action-mappings>
   <action path="/LoginAction"
           type="com.daipresents.struts135.login.LoginAction"
           name="LoginForm"
           scope="request">
           <forward name="success" path="layout" />
           <forward name="login" path="/login/login.jsp" />
  </action>

definitionを構成する要素をputタグで指定する。
putのname属性にはJSPのtilesタグで指定したattributeを指定する。上の場合だとheader属性部分に「/Resources/jsp/Header.jsp」がインクルードされる。

継承して一部分だけ変更したい場合は以下のように書く。

<definition name="layout" path="/WEB-INF/jsp/layout.jsp">
  <put name="header" value="/WEB-INF/jsp/header.jsp" />
  <put name="menu" value="/WEB-INF/jsp/menu.jsp" />
  <put name="content" value="" />
  <put name="footer" value="/WEB-INF/jsp/footer.jsp" />
</definition>
<definition name="regpage" extends="layout">
  <put name="content" value="/WEB-INF/jsp/reg.jsp" />
</definition>

これならばcontent部分にReg.jspがputされる以外は継承元のページが使われる。

tiles:insertで例外が発生した場合

ディレクティブでerrorPage属性を指定しても、そのページが表示されない。insert元のJSPがすでに出力を開始しているので、
insert部分でエラーがでても、すでに出力された部分は表示されてしまう。errorPageで指定しても、既に出力された部分に加えて、エラーペー
ジのJSPが表示されるわけだ。

pic20080304_234036

上記がその画像。layout.jspでtilesを使ってinsertしているのだけれど(テーブルの部分)layout.jspも表示されているのがわかる。

tilesを使うとinsert先でエラーが発生した場合

  • insert先のerrorPage属性が有効
  • insert先でerrorPage属性を指定しない場合はinsert元のerrorPage属性が有効
  • insert元のページにエラーページがinsertされてしまう
    となる。

web.xmlのerror-pageを使ってもstruts-config.xmlのglobal-exceptionsを使っても無理。これ、
バグじゃないかな?しかし、解決方法を発見。struts-config.xmlのexceptionタグの「SILENT_IF_COMMITTED」
というプロパティを使えば、ちょっと改善される。

SILENT_IF_COMMITTED
デフォルトはtrue。trueの場合、エラー時に何も表示しない。falseに設定すると、エラーページが表示される。pathにはglobal-forwardの名前は使えないのでパスをちゃんと指定すること。
 <global-exceptions>
   <exception key="errors.required" type="java.lang.Exception" path="/WEB-INF/jsp/error/50XError.jsp" >
     <set-property key="SILENT_IF_COMMITTED" value="false" /> 
   </exception>
 </global-exceptions>

参考:http://itpro.nikkeibp.co.jp/article/COLUMN/20060408/234852/?ST=lin-server&P=5

web.xmlに

 <error-page>
   <exception-type>java.lang.Exception</exception-type>
   <location>/WEB-INF/jsp/error/error50X.jsp</location>
 </error-page>

としていると、SILENT_IF_COMMITTEDがtrueでもfalseでもなにも表示されずweb.xmlの設定が勝ってしまう。