Top / Struts / 例外ハンドラ(ExceptionHandler)を用いた宣言的な例外処理

Strutsの例外処理についてまとめます。Strutsの例外処理はいわゆる宣言的な例外処理機構があります。 全てのアクション、もしくは特定のアクションで××Exceptionが発生した場合はこのエラー画面へ遷移、などということができます。また、ある例外が発生したときに画面遷移だけでなく特殊な処理をしたい場合、例外ハンドラを定義することによって処理を組み込むこともできます。たとえばある例外で、内部のエラーIDを見て遷移先を切り替えたい、なんてことが可能です。

やってみる

サンプルで見てみます。アクションクラスで特定の例外(NormalException?としました)が発生したときに、error.jspに遷移させることを考えます。

流れ

normalEx -> エラー発生 -> error.jsp

という流れのサンプルです。

ソース

  • struts-config.xml
    <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?を作成しなさい、という意味です。

  • アクションクラス(NormalExceptionAction?)
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        throw new NormalException("普通のハンドリングをする例外!");
    }
  • MessageResources?.properties
    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}を置換しなさい、という意味になります。

  • error.jsp
    <?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が出力されました。

アクションクラスで作成したActionMessages?がでないような、、。

ここではアクションクラスでは例外をスローしただけでしたが、アクションクラス内でいろいろなActionMessage?を作成しておいても、画面には表示されません。これについてはStruts/ActionMessagesによるエラー処理と、例外ハンドラで処理した場合の挙動の違いにまとめました。

org.apache.struts.action.ExceptionHandler?を変更して独自の処理を入れる

  • struts-config.xml
    <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?を使うようになります。実際のソースは以下の通り。
  • 例外ハンドラクラス(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?を見てなんかするとか、ある場合だけ別の遷移とか、自由に色々やることができますね。

遷移先もstruts-config.xmlからでなく、ハンドラ内で制御する

デフォルトの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すればよいですね。

  • struts-config.xml
    <global-exceptions>
        <exception
            key="error.NormalException"
            type="nu.mine.kino.strutsexamples.exceptions.NormalException"
            handler="nu.mine.kino.strutsexamples.exceptions.CustomizeExceptionHandler" 
    </global-exceptions>
  • 例外ハンドラクラス(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 mapping.findForward("success"); <-自分で指定
    }
    このように自分でやることもできますね。

サンプル。

TIPS

スローされた例外にアクセスする

スローされたExceptionは

Globals.EXCEPTION_KEY

というキー値*2でリクエストスコープに格納されているので

<logic:present name="<%=Globals.EXCEPTION_KEY %>" >
  <bean:write name="<%=Globals.EXCEPTION_KEY %>"/> 
</logic:present>

でアクセス可能です。

関連リンク

この記事は

選択肢 投票
おもしろかった 40  
そうでもない 4  
  • 勉強になります。ありがとうございます -- 2011-12-13 (火) 20:33:38

Top / Struts / 例外ハンドラ(ExceptionHandler)を用いた宣言的な例外処理

現在のアクセス:47382


*1 これはstruts-config.xmlのhandler属性で変更可能
*2 実際の値は"org.apache.struts.action.EXCEPTION"

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-06-06 (水) 16:41:53 (2313d)