Strutsの例外処理についてまとめます。Strutsの例外処理はいわゆる宣言的な例外処理機構があります。 全てのアクション、もしくは特定のアクションで××Exceptionが発生した場合はこのエラー画面へ遷移、などということができます。また、ある例外が発生したときに画面遷移だけでなく特殊な処理をしたい場合、例外ハンドラを定義することによって処理を組み込むこともできます。たとえばある例外で、内部のエラーIDを見て遷移先を切り替えたい、なんてことが可能です。
サンプルで見てみます。アクションクラスで特定の例外(NormalExceptionとしました)が発生したときに、error.jspに遷移させることを考えます。
normalEx -> エラー発生 -> error.jsp
という流れのサンプルです。
<global-exceptions>
<exception key="error.NormalException"
type="nu.mine.kino.strutsexamples.exceptions.NormalException"
path="/WEB-INF/jsp/error.jsp"/>
<!-- このkey値でActionMessageを生成してスコープにセットしている。
メッセージのvalueは、propertiesから取得している。
-->
</global-exceptions>NormalExceptionをスローしたらerror.jspに遷移しなさい、またerror.NormalExceptionというキー値のActionMessageを作成しなさい、という意味です。
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
throw new NormalException("普通のハンドリングをする例外!");
}error.NormalException=NormalException!! [{0}]例外がスローされると、org.apache.struts.action.ExceptionHandlerが処理を行うのですが*1、その中でActionMessageを生成する処理があります。そこで
ActionMessage error = new ActionMessage(ae.getKey(), ex.getMessage()); ae.getKey() はstruts-config.xmlのキー値(error.NormalException) ex.getMessage() は例外のgetMessage()
という処理があります。つまり error.NormalException というキー値、例外のメッセージで{0}を置換しなさい、という意味になります。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <%@ page language="java" contentType="text/html; charset=UTF-8" %> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %> <%@page import="org.apache.struts.Globals"%> <html:html xhtml="true" lang="true"> <head> <title>エラーハンドラのサンプル</title> <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" /> <html:base /> </head> <body> <ul> <html:messages id="message"> <li><bean:write name="message" /></li> </html:messages> </ul> <hr /> <html:errors /> <hr /> </body> </html:html>
あとは普通のActionMessageの処理と同じですね。
<ul> <li>NormalException!! [普通のハンドリングをする例外!]</li> </ul> <hr /> <ul><li>NormalException!! [普通のハンドリングをする例外!]</li></ul> <hr />
といったhtmlが出力されました。
ここではアクションクラスでは例外をスローしただけでしたが、アクションクラス内でいろいろなActionMessageを作成しておいても、画面には表示されません。これについてはStruts/ActionMessagesによるエラー処理と、例外ハンドラで処理した場合の挙動の違いにまとめました。
<global-exceptions>
<exception
key="error.NormalException"
type="nu.mine.kino.strutsexamples.exceptions.NormalException"
handler="nu.mine.kino.strutsexamples.exceptions.CustomizeExceptionHandler"
path="/WEB-INF/jsp/error.jsp"/>
</global-exceptions>
に変更するだけですね。デフォルトのExceptionHandlerではなくCustomizeExceptionHandlerを使うようになります。実際のソースは以下の通り。public ActionForward execute(Exception exception, ExceptionConfig config,
ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws ServletException {
NormalException normalException = (NormalException) exception;
// エラーコード見るとか、なんか処理。
ActionForward forward = super.execute(exception, config, mapping, form,
request, response);
return forward;
}
ここではなんにもしてませんが、実際はNormalExceptionを見てなんかするとか、ある場合だけ別の遷移とか、自由に色々やることができますね。デフォルトのExceptionHandlerは基本的に
<exception
key="error.NormalException"
type="nu.mine.kino.strutsexamples.exceptions.NormalException"
handler="nu.mine.kino.strutsexamples.exceptions.CustomizeExceptionHandler"
path="/WEB-INF/jsp/error.jsp"/>
と遷移先が固定でしたが、実はこの値はオプショナルで、実際の遷移先を全てハンドラにやらせることもできます。実際ExceptionHandlerのソースを見てみると、
if (ae.getPath() != null) {
forward = new ActionForward(ae.getPath());
} else {
forward = mapping.getInputForward();
}
というように、exceptionタグのpathから遷移先を取り出す、もしくはからactionタグのinput属性から取り出す、とやっていますが、ここをOverrideすればよいですね。
<global-exceptions>
<exception
key="error.NormalException"
type="nu.mine.kino.strutsexamples.exceptions.NormalException"
handler="nu.mine.kino.strutsexamples.exceptions.CustomizeExceptionHandler"
</global-exceptions>public ActionForward execute(Exception exception, ExceptionConfig config,
ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws ServletException {
NormalException normalException = (NormalException) exception;
// エラーコード見るとか、なんか処理。
// 一応、親クラスの処理を呼ぶけど、遷移先は自分で指定する
ActionForward forward = super.execute(exception, config, mapping, form,
request, response);
return mapping.findForward("success"); <-自分で指定
}
このように自分でやることもできますね。スローされたExceptionは
Globals.EXCEPTION_KEY
というキー値*2でリクエストスコープに格納されているので
<logic:present name="<%=Globals.EXCEPTION_KEY %>" > <bean:write name="<%=Globals.EXCEPTION_KEY %>"/> </logic:present>
でアクセス可能です。
この記事は
現在のアクセス:48931