// 下階層用テンプレート
#topicpath
----
//ここにコンテンツを記述します。
#contents

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

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

***流れ [#ff613522]
 normalEx -> エラー発生 -> error.jsp
という流れのサンプルです。


***ソース [#f26192bf]
-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が処理を行うのですが((これはstruts-config.xmlのhandler属性で変更可能))、その中で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の処理と同じですね。

**実行結果 [#z939794d]
 <ul>
   <li>NormalException!! [普通のハンドリングをする例外!]</li>
 </ul>
 <hr />
 <ul><li>NormalException!! [普通のハンドリングをする例外!]</li></ul>
 <hr />
といったhtmlが出力されました。


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

**org.apache.struts.action.ExceptionHandlerを変更して独自の処理を入れる [#ob58be2a]

-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からでなく、ハンドラ内で制御する [#w12bde3d]
デフォルトの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"); <-自分で指定
 }
このように自分でやることもできますね。


**サンプル。 [#b8c2c51b]
-[[サンプルプログラム(ViewVC)>http://www.masatom.in/cgi-bin/viewvc.cgi/tags/V1.0.0_20080121_01/strutsExamples/?root=Others]]
-[[サンプルプログラム(Subversion)>https://www.masatom.in/svnsamples/repo/tags/V1.0.0_20080121_01/strutsExamples]]


**TIPS [#l4248dab]
***スローされた例外にアクセスする [#t3a733b1]
スローされたExceptionは
 Globals.EXCEPTION_KEY
というキー値((実際の値は"org.apache.struts.action.EXCEPTION"))でリクエストスコープに格納されているので
 <logic:present name="<%=Globals.EXCEPTION_KEY %>" >
   <bean:write name="<%=Globals.EXCEPTION_KEY %>"/> 
 </logic:present>
でアクセス可能です。



**関連リンク [#scf0c3f3]
-[[Strutsで掲示板! 例外ハンドラを使おう>http://yamarou.at.infoseek.co.jp/javanawake/020.html]]

この記事は
#vote(おもしろかった[39],そうでもない[4])
#vote(おもしろかった[40],そうでもない[4])
- 勉強になります。ありがとうございます --  &new{2011-12-13 (火) 20:33:38};

#comment
#topicpath


SIZE(10){現在のアクセス:&counter;}

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS