スマートフォン・ジン | Smartphone-Zine

引っ越し先→ https://smartphone-zine.com/

【Struts】*.do設定で、struts-config.xmlに設定していないアドレスにアクセスがあった場合、エラーページへ飛ばす。

web.xml

    <servlet-mapping>
            <servlet-name>action</servlet-name>
            <url-pattern>*.do</url-pattern>
    </servlet-mapping>


のように*.doを設定していると、
javax.servlet.ServletException: アクション /hogeAction に対応するマッピングが見つかりません
というエラーが出ることがあります。

これはstruts-config.xml に "/hogeAction" というパスを持つアクションが存在しないために発生するエラーです。

これを、対応するアクションが存在しない場合にはエラーページへ飛ばすように設定したい。

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=10418&forum=12&3
上記URLを参考にRequestProcessorを継承して実装してみました。

まず、存在しないアクションを指定した場合にデフォルトで移動するパスを保持するに
defaultPathというプロパティを追加する為、ControllerConfig を継承したクラスを作ります。

public class MyControllerConfig extends ControllerConfig {
/* 存在しないdoを開いた時にデフォルトで開くパスを指定する */
private String defaultPath;

    public String getDefaultPath() {
        return defaultPath;
    }

    public void setDefaultPath(String defaultPath) {
        this.defaultPath = defaultPath;
    }

}


RequestProcessor#init(ActionServlet,ModuleConfig)をオーバーライドして、初期化コードを実装します。
また、指定されたアクションが
存在しない場合、エラーを表示している部分はprocessMappingのようでうすので、これを拡張し、指定されたアクションが無ければ、プロパティで指定したアクションへ移動するようにコードを追加します。今回はTilesを使用したいのでTilesRequestProcessorを拡張します。

public class MyTilesRequestProcessor extends TilesRequestProcessor {
    private String defaultPath = null;
    @Override
    public void init(ActionServlet servlet, ModuleConfig moduleConfig) throws ServletException {
        super.init(servlet, moduleConfig);

        ControllerConfig cc = moduleConfig.getControllerConfig();

        if (cc instanceof MyControllerConfig) {
            MyControllerConfig icc = (MyControllerConfig) cc;
            defaultPath = icc.getDefaultPath();
        }

    }
    protected ActionMapping processMapping(HttpServletRequest request, HttpServletResponse response, String path)
            throws IOException {

        // Is there a mapping for this path?
        ActionMapping mapping = (ActionMapping) moduleConfig.findActionConfig(path);

        // If a mapping is found, put it in the request and return it
        if (mapping != null) {
            request.setAttribute(Globals.MAPPING_KEY, mapping);
            return (mapping);
        }

        // Locate the mapping for unknown paths (if any)
        ActionConfig configs[] = moduleConfig.findActionConfigs();
        for (int i = 0; i < configs.length; i++) {
            if (configs[i].getUnknown()) {
                mapping = (ActionMapping) configs[i];
                request.setAttribute(Globals.MAPPING_KEY, mapping);
                return (mapping);
            }
        }

        /* 追加ロジックここから */
        // Is there a mapping for default path?
        mapping = (ActionMapping) moduleConfig.findActionConfig(this.defaultPath);
        if (mapping != null) {
            request.setAttribute(Globals.MAPPING_KEY, mapping);
            return (mapping);
        }       
        /* 追加ロジックここまで */
      
        // No mapping can be found to process this request
        String msg = getInternal().getMessage("processInvalid", path);
        log.error(msg);
        response.sendError(HttpServletResponse.SC_NOT_FOUND, msg);

        return null;
    }

}

struts-config.xmlの設定は次のようにしました。

<controller processorClass="com.hoge.MyTilesRequestProcessor" 
className="com.hoge.MyControllerConfig">
<set-property property="defaultPath" value="/notFoundAction" />
</controller>


でもぉ、こんなことをしなくても unknown="true"にすれば万事解決。
以上