続 SAStrutsをStruts形式のURLでも動くようにする
前回エントリの続き。
S2ModuleConfigを継承して、もう少しコードを整理してみる。
まずはFilter
2009/10/6 追記
前回エントリの修正に合わせて修正しました。
public class MyRoutingFilter extends RoutingFilter { public static final String INCLUDE_PATH_INFO = "javax.servlet.include.path_info"; public static final String INCLUDE_SERVLET_PATH = "javax.servlet.include.servlet_path"; protected static final MessageResources messages = MessageResources .getMessageResources("org.apache.struts.actions.LocalStrings"); /** Struts URLパターンの正規表現 */ protected String strutsUrlPattern = ".*Action\\.do$"; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; String path = RequestUtil.getPath(req); if (!processDirectAccess(request, response, chain, path)) { return; } if (isStrutsPath(path)) { ActionConfig actionConfig = ((MyModuleConfig) S2ModuleConfigUtil .getModuleConfig()).findStrutsActionConfig(processPath(req, res)); if (actionConfig != null) { // struts-config.xmlに定義されているActionのフルクラス名を取得 String actionType = actionConfig.getType(); // ForwardAction の場合は、struts-config.xml の parameter // に定義されているパスへフォワードする if ("org.apache.struts.actions.ForwardAction" .equals(actionType)) { executeForwardAction(actionConfig, req, res); return; } // struts-config.xml に forward 属性が定義されている場合は、定義されているパスへフォワードする if (actionConfig.getForward() != null) { request.getRequestDispatcher(actionConfig.getForward()) .forward(request, response); return; } // IncludeAction の場合は、struts-config.xml の parameter // に定義されているパスをインクルードする if ("org.apache.struts.actions.IncludeAction" .equals(actionType)) { executeIncludeAction(actionConfig, req, res); return; } String actionPath = getActionPath(actionType); // Actionの実行メソッド名を取得 String methodName = getActionMethodName(actionConfig, req); if (SingletonS2ContainerFactory.getContainer() .hasComponentDef(ActionUtil.fromPathToActionName(actionPath))) { if (StringUtil.isEmpty(methodName)) { // RoutingFilter では、URLにメソッド指定がない場合は、 // S2ExecuteConfigUtil#findExecuteConfig(String, // HttpServletRequest)で // S2ExecuteConfigを取得しているが、その場合、SAStrutsの仕様により // URLのパラメータ名にメソッド名と一致するものがあれば // そのメソッドが実行されてしまうためStrutsと挙動が変わってしまう。 // Strutsと挙動を合わせるため、デフォルトメソッド名を補完する。 S2ExecuteConfig executeConfig = findExecuteConfig(actionPath, "index"); if (executeConfig != null) { forward(req, res, actionPath, null, null); return; } } else { S2ExecuteConfig executeConfig = findExecuteConfig(actionPath, methodName); if (executeConfig != null) { forward(req, res, actionPath, methodName, executeConfig); return; } } } } } else { super.doFilter(request, response, chain); return; } res.sendError(HttpServletResponse.SC_NOT_FOUND, req.getRequestURI()); } // 他のメソッドは前エントリと同じなので省略 }
Struts設定情報を保持するModuleConfig
public class MyModuleConfig extends S2ModuleConfig { private static final long serialVersionUID = 1L; /** Struts の Action 設定情報 */ protected HashMap<String, ActionConfig> strutsActionConfigs = null; public MyModuleConfig(String prefix) { super(prefix); initialize(); } @Override public void freeze() { super.freeze(); // struts-config.xml の設定情報は、ActionServlet 初期化時には actionConfigs に格納されるが、 // HotDeployではリクエストのたびに、S2ModuleConfig#disposeで actionConfigs がクリアされるため、 // strutsActionConfigs に退避しておく。 // struts-config.xml の設定情報は、HotDeploy 対象外となるため、strutsActionConfigs は // dispose でクリアしない。 if (strutsActionConfigs == null) { strutsActionConfigs = new HashMap<String, ActionConfig>(); for (Object key : actionConfigs.keySet()) { ActionConfig config = (ActionConfig) actionConfigs.get(key); if (!(config instanceof S2ActionMapping)) { // SAStruts ではない、Struts の ActionMapping を保存する strutsActionConfigs.put((String) key, config); } } } } public ActionConfig findStrutsActionConfig(String path) { return strutsActionConfigs.get(path); } }
最後はMyModuleConfigを使用させるためのファクトリ
public class MyModuleConfigFactory extends ModuleConfigFactory { @Override public ModuleConfig createModuleConfig(String prefix) { return new MyModuleConfig(prefix); } }
使い方
web.xmlに次のようにMyModuleConfigFactoryを設定する。
その他については、前回エントリと同じ。
<servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>configFactory</param-name> <param-value>hoge.config.MyModuleConfigFactory</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>