springMVCの例外ハンドラの実装例(HandlerExceptionResolver編)

spring

springMVCのコントローラクラスでは、発生した例外(Exception)をHandlerExceptionResolverを使ってハンドリングします。

ハンドラクラスを作ることで各コントローラで「try catch」を入れる必要もなく一つのクラスでハンドリングすることが出来ます。
例外をハンドリングする方法は、他にもいくつかあります。
今回は、HandlerExceptionResolverを使って、例外をハンドリングする方法を紹介します。

[スポンサーリンク]

この章でやること

springMVCのハンドラクラスを作ります。(HandlerExceptionResolverを使います。)

springMVCのバージョン

org.springframework-versionは、3.1.0を使っています。
javaは、1.6.0を使っています。

今回作成したクラス&設定ファイルはこちらです。

修正ファイル一覧

springMVCのひな型の作成方法は、「springsource tool suite Webアプリを自動生成してみよう編」を参照して下さい。

例外ハンドラクラスを作成します。

ハンドラクラスを作成するには、HandlerExceptionResolver をimplementsします。spring設定ファイル(servlet-context.xml)にbeanの定義を行ったら、各コントローラで発生した例外はこのハンドラクラスでキャッチできます。

/**
 * 例外のハンドラクラスです。
 *
 */
public class GlobalExceptionResolver implements HandlerExceptionResolver {
	private static final Logger logger = 
			LoggerFactory.getLogger(GlobalExceptionResolver.class);

	public ModelAndView resolveException(
						HttpServletRequest request,
						HttpServletResponse response,
						Object object,
						Exception ex) {

		logger.error("例外をキャッチしました。", ex);

		ModelAndView mav = new ModelAndView();

		// JSPに表示するメッセージをセットします。
		mav.addObject("message", "予期せぬエラーが発生しました。" +
						" 詳細:【" + ex + "】");

		// 遷移先のJSPを指定します。(error.jspに遷移します。)
		mav.setViewName("error");
		return mav;

	}

}

JSPを作成します。

例外ハンドラで指定しました、error.jspを作成します。

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>error</title>
</head>
<body>
<h1>
	error page  
</h1>
<P>  ${message} </P>

</body>
</html>

spring設定ファイル(servlet-context.xml)にハンドラクラスを定義します。

上で作成したハンドラクラスをspringの設定ファイルに以下を追加します。

	<!-- 例外のハンドラクラス  -->
	<beans:bean class="com.javatech.apl.handler.GlobalExceptionResolver"/>

実行しましょう

それではさっそく実行しましょう。とその前に例外を発生させるコントローラを作成しましょう。例外を意図的に発生させるコントローラをブラウザから実行すると例外ハンドラクラスの挙動が確認出来ます。

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	private static final Logger logger = 
			LoggerFactory.getLogger(HomeController.class);
	
	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		logger.info("Welcome home! the client locale is "
					+ locale.toString());
		
		// わざと例外を発生させます。
		String str = null;
		if(str.equals("ok"));
		
		return "home";
	}
	
}

実行結果

APIを実行するとJSONが出力されます。

ブラウザからの実行方法については、「springsource tool suite Webアプリを自動生成してみよう編」を参照して下さい。

実行結果

解説

コントローラで発生した例外は全てこの例外ハンドラがキャッチして処理してくれます。try-catchは不要ですね。ただしDaoやUtil等のコントローラより下位階層で発生した例外をtry-catch握りつぶしてしまうと例外ハンドラはキャッチ出来なくなります。(当然ですが)
下位階層で発生した例外は必ずスローするようにしておけば、ハンドラクラスでキャッチできるので取りこぼす心配はありません。

最後に

springMVCで例外を取得する方法は、HandlerExceptionResolver以外にもあります。@AfterThrowingや@ExceptionHandlerでキャッチは出来ます。どこでキャッチをするのかが変わってきますが。こちらのやり方についても今後記事にしたいなぁと考えています。