Localeによるリソース選択Interceptorの問題解消
何度かModelDrivenにしないと意図通りに動作しないとか、ModelになくActionに有るプロパティがsetされないと書いていたが、原因が判明した。
悪さをしていたのは Localeによるdispatch先の選択2 - Struts 2+Spring 2+Tiles+Acegi+iBatis+GWT+JUnit 4+JMockit でフルスタックJAVAフレームワークだった。
ValueStackで参照できるように次のようなコードで実装していたが、同じように新たなオブジェクトを積むExceptionMappingInterceptorのコードを参照するとsetではなくpushでオブジェクトを積んでいた。
その実装に習って、このコードを
stack.set( "localed", this );
次のように変更した
stack.push( this );
そして、localedはプロパティとして参照できるように、getLocaledを用意してあげる。
これで、ModelDrivenでModel側にプロパティが見つからなければ、正しくAction側(スタックの下側)のプロパティが呼ばれるようになった。
全体はつぎのようになる。
jp.co.hershe.struts2.util.LocaleResourceInterceptor.java
package jp.co.hershe.struts2.util; import java.net.URL; import java.text.MessageFormat; import java.util.Locale; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; import com.opensymphony.xwork2.util.ValueStack; /** * 国際化対応アプリケーション用のインターセプタ * * 結果を Locale 設定に従いそれぞれ固有のページで表示をする場合に * 利用する。 * * <result>$( localed.resource( "{0}/edit.jsp" )</result> * とすると Locale の Language が ja の場合 /ja/edit.jsp を探し * あればそちら、無ければ /edit.jsp を表示する。 * @author mikuni * */ public class LocaleResourceInterceptor extends AbstractInterceptor { public void destroy() { } public void init() { } // スタックに localed として自分を登録 public String intercept(ActionInvocation invocation) throws Exception { final ValueStack stack = invocation.getStack(); stack.push( this ); return invocation.invoke(); } public LocaleResourceInterceptor getLocaled() { return this; } // 置き換え処理を行う public String resource( String url ) throws Exception { Locale loc = ActionContext.getContext().getLocale(); String ans = MessageFormat.format(url, new Object[]{ "/"+loc.getLanguage(), "/"+loc.getCountry() } ); HttpServletRequest request = ServletActionContext.getRequest(); URL u = ServletActionContext.getServletContext().getResource(ans); if (u!=null) { return ans; } ans = MessageFormat.format(url, new Object[]{ "", "" } ); return ans; } }
struts.xml への記述に変更は必要無く、今まで通りである。
<result-types> <result-type name="templ" class="jp.co.hershe.struts2.util.TemplateResult" default="true"> <param name="template">${ localed.resource( "{0}#file#" ) }</param> <param name="key">#file#</param> </result-type> </result-types>