Tech Sketch Bucket of Technical Chips by TIS Inc.

Spring MVCでExceptionをハンドリングする

Pocket

この記事はeXcale Developer's Blogから移転されたものです。

eXcale開発チームの西谷です。

今回はJavaのフレームワークであるSpringMVCを利用する場合のTipsです。

SpringMVCのアノテーションに@ResponseBodyというものがあります。これはレスポンスの内容を簡単にモデルからJsonなどの形式に変換するというものですが、この@ResponseBodyを使っている場合はStringでreturnできません。つまり、メソッド内で例外が発生した際に遷移させるエラーページのパスを返すことができません。

そこで、今回はコントローラで発生した例外をコントローラ内でハンドリングする方法をご紹介します。さらにそのエラー自体もJson形式でレスポンスするようにしてみます。と言ってもすごく簡単で@ExceptionHandlerというアノテーションを付与したハンドリング用のメソッドをコントローラ内に用意するだけです。

サンプルではこんな感じのモデルを2つ使ってます。

加えて、サンプルで発生させる例外クラスも以下のような感じで用意しておきます。中身は何もありません。もちろん、わざわざ用意することなく既存の例外をハンドリングするような形でも大丈夫です。

続いてコントローラを用意します。

ここでは/sampleというURLに0というidを付けてGETリクエストした場合にエラーとなって例外を発生させるようなメソッドを用意してます。加えてレスポンスはモデルをJSON形式に変換したものが返されるようになってます。

今回の本題ではないですが、この{id}の部分を簡単に説明しておきます。 @RequestMappingアノテーションのvalueではHTTPリクエストとメソッドをマッピングする設定ができますが、ここで変数として{}で囲った文字列を定義すると@PathVariableを使ってメソッドの引数として展開できます。ここでは{id}として指定したパス上の変数をString型の変数としてメソッドに渡しています。

そして、冒頭に説明した@ResponseBodyですが、このアノテーションをつけてモデルをメソッドの戻り値に指定しておくことで、そのモデルが変換されて自動的にレスポンスのボディにセットされます。ここでは@RequestMappingでヘッダ指定をしているので自動的にJSON形式に変換されます。

さて、上記のメソッドではidが0という文字列でリクエストされた場合に例外をスローするようにしています。

では、この例外をハンドリングするメソッドを同じコントローラ内に作成します。

@ExceptionHandlerの引数としてハンドリングしたい例外クラスを指定します。これは一つのハンドラメソッドで複数指定できます。

加えて、ハンドラメソッドの引数として実際にスローされた例外を取得しています。これは後でメッセージを出力するために使ってます。

基本的にこれだけでも動きますがサンプルではついでに@ResponseStatusアノテーションを付けてこの例外が発生したらレスポンスコードを400にするようにしています。

そして先ほどと同じように@ResponseBodyアノテーションでエラーレスポンスもJSONで返すようにしてます。したがってメソッド内ではレスポンス用のモデルにメッセージをセットしてます。

と、こんな感じで簡単にハンドリングできます。

例外が発生してもwrapして500番台のコードを返したくない場合とか、別エントリで記載した@RequestBodyと@Validを組み合わせて使用する場合なんかに使えますね。

エンジニア採用中!私たちと一緒に働いてみませんか?