SAStrutsの例外処理
やりたいこと
- Exceptionしたらログを吐いて自作のエラーページに飛ばす
- 自作のエラーページにはExceptionごとのエラーメッセージを表示する
実装
いろいろな方法がありますが、今回はカスタムExceptionを作成しつつ
throwしとけばException毎のメッセージが出せるような仕組みを構築します。
まずカスタムExceptionを作ります。
public class AuthException extends RuntimeException { private static final long serialVersionUID = 1L; public AuthException(String message) { super(message); } }
Exceptionを起こすとき(=エラーページに飛ばすとき)はこんな感じにします。
throw new AuthException("testdes");
このままではtomcatのエラー画面に飛んでしまうし、ログも出力されません。
まずログを吐くにはExceptionが起こった後、エラー画面を出す前に呼ばれるクラス(ハンドラー)を
作る必要があります。
その中でログを吐いて、エラー画面に飛ばすということをしてやります。
まずハンドラーです。
public class ExceptionForwardHandler extends ExceptionHandler{ Logger logger = Logger.getLogger("error"); @Override public ActionForward execute(Exception ex, ExceptionConfig ae, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response) throws ServletException { // logger出力 logger.error(ex.getLocalizedMessage(), ex); // struts-configで設定したException処理を実行 super.execute(ex, ae, mapping, formInstance, request, response); return (ae.getPath() != null ? ((S2ActionMapping) mapping).createForward(ae.getPath()) : mapping.getInputForward()); } }
さっぱりわかりませんね。
なんだかいろいろ受け取って何かを返しています。
ポイントは途中のlogger出力の部分だけです。これを処理に追加したかっただけです。
後はstrutsそのものの動作になります。
つぎに作成したハンドラーを経由してくれるように設定を変えます。
これはstruts-config.xmlに書きます。
<!-- key: application.propertiesのメッセージに対応するキー名 path: エラー発生後の遷移先JSP handler: 固定で"net.hoge.exception.ExceptionForwardHandler" --> <exception key="exceptions.auth" type="net.hoge.exception.AuthException" path="/errors/error.jsp" handler="net.hoge.exception.ExceptionForwardHandler" /> <!-- その他例外 --> <exception key="exceptions.other" type="java.lang.Exception" path="/errors/error.jsp" handler="net.hoge.exception.ExceptionForwardHandler" />
作成したカスタムExceptionはここにどんどこ追加していきます。
typeの部分にカスタムExceptionのクラス名、pathにはこのExceptionが起こった後の遷移先JSPを記載します。
handlerはさっき作ったExceptionForwardHandlerですね。
この設定により、
- AuthExceptionがthrowされた
- ExceptionForwardHandlerが呼ばれる→ログを吐く
- error.jspが呼ばれる
という一連の流れができることになります。
次にエラーメッセージを用意します。AuthExceptionがthrowされたら
「認証エラーが発生しました」
とでも出しましょうか。
application_ja.propertiesに以下のように追加します。
exceptions.auth=認証エラーが発生しました。
ここで指定するキー名はstruts-config.xmlで指定したkey名と連動してます。
struts-config.xmlはkeyに指定された文字でapplication*.propertiesを読み
後続のjspにメッセージを渡す仕組みとなっています。
最後にエラーページの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 /> <logic:present name="<%=Globals.EXCEPTION_KEY %>" > <bean:write name="<%=Globals.EXCEPTION_KEY %>"/> </logic:present> </body> </html:html>
messageの部分で取得したエラーメッセージを表示してます。
またGlobals.EXCEPTION_KEYにはExceptionクラス名がセットされます
こんな感じで実装しておけば
例外処理も簡単になるのではないでしょうか。