Spring MVCの例外処理 – @ControllerAdvice、@ExceptionHandler、HandlerExceptionResolver

Spring MVCの例外処理は、サーバの例外をクライアントに送信しないようにするために非常に重要です。今日は、@ExceptionHandlerや@ControllerAdvice、HandlerExceptionResolverを使用したSpringの例外処理について見ていきます。どんなWebアプリケーションでも、未処理の例外がアプリケーションで発生した場合には、コンテナが生成したページを提供したくないため、例外処理のための良いデザインが必要です。

Springの例外処理

ウェブアプリケーションフレームワークにおいて、明確な例外処理アプローチを持つことは非常に大きなプラスポイントです。それを考慮しても、Spring MVCフレームワークは、ウェブアプリケーションにおける例外とエラー処理において優れた実績を持っています。Spring MVCフレームワークは、以下の方法で強力な例外処理をサポートしています。

    1. コントローラーベース – コントローラークラスで例外ハンドラーメソッドを定義することができます。これらのメソッドには、@ExceptionHandlerアノテーションを付ける必要があります。このアノテーションはExceptionクラスを引数に取ります。したがって、Exceptionクラスのハンドラーメソッドを定義すると、リクエストハンドラーメソッドでスローされるすべての例外が処理されます。これらの例外ハンドラーメソッドは他のリクエストハンドラーメソッドと同様であり、エラーレスポンスを構築し、異なるエラーページで応答することができます。後で例を見るように、JSONエラーレスポンスも送信することができます。複数の例外ハンドラーメソッドが定義されている場合、最も近い例外クラスに対応するハンドラーメソッドが使用されます。例えば、IOExceptionとExceptionの2つのハンドラーメソッドが定義されていて、リクエストハンドラーメソッドがIOExceptionをスローする場合、IOExceptionのハンドラーメソッドが実行されます。

 

    1. グローバル例外ハンドラー – 例外処理は横断的な関心事であり、アプリケーションのすべてのポイントカットに対して行う必要があります。既にSpring AOPを見てきたので、Springは@ControllerAdviceアノテーションを提供しており、任意のクラスでグローバル例外ハンドラーを定義することができます。グローバルコントローラーアドバイスのハンドラーメソッドは、コントローラーベースの例外ハンドラーメソッドと同じであり、コントローラークラスが例外を処理できない場合に使用されます。

 

    HandlerExceptionResolver – 一般的な例外に対しては、ほとんどの場合、静的なページを提供します。Spring FrameworkはHandlerExceptionResolverインターフェースを提供しており、これを実装してグローバル例外ハンドラーを作成することができます。グローバル例外ハンドラーをさらに定義するためのこの別の方法の背後にある理由は、Springフレームワークがデフォルトの実装クラスを提供しているため、Springフレームワークの例外処理の利点を得るためです。SimpleMappingExceptionResolverはデフォルトの実装クラスであり、例外ごとにどのリソースを使用するかを指定できるexceptionMappingsを設定できます。また、例外メッセージのログ記録など、アプリケーション固有の変更を行うために独自にオーバーライドすることもできます。

「Controllerベース、AOPベース、例外解決ベースの例外およびエラーハンドリングアプローチの実装を検討するSpring MVCプロジェクトを作成しましょう。また、JSONレスポンスを返す例外ハンドラーメソッドも作成します。SpringでJSONを使うことに関して初めての方は、Spring Restful JSONチュートリアルを読んでください。最終的なプロジェクトは以下の画像のようになります。アプリケーションの各コンポーネントを一つずつ見ていきましょう。」

スプリングの例外処理に必要なMavenの依存関係

標準のSpring MVCの依存関係に加えて、JSONのサポートのためにJackson JSONの依存関係も必要です。最終的なpom.xmlファイルは以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.scdev.spring</groupId>
	<artifactId>SpringExceptionHandling</artifactId>
	<name>SpringExceptionHandling</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.6</java-version>
		<org.springframework-version>4.0.2.RELEASE</org.springframework-version>
		<org.aspectj-version>1.7.4</org.aspectj-version>
		<org.slf4j-version>1.7.5</org.slf4j-version>
		<jackson.databind-version>2.2.3</jackson.databind-version>
	</properties>
	<dependencies>
		<!-- Jackson -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>${jackson.databind-version}</version>
		</dependency>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>

		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>

		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-eclipse-plugin</artifactId>
				<version>2.9</version>
				<configuration>
					<additionalProjectnatures>
						<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
					</additionalProjectnatures>
					<additionalBuildcommands>
						<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
					</additionalBuildcommands>
					<downloadSources>true</downloadSources>
					<downloadJavadocs>true</downloadJavadocs>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.5.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
					<compilerArgument>-Xlint:all</compilerArgument>
					<showWarnings>true</showWarnings>
					<showDeprecation>true</showDeprecation>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>exec-maven-plugin</artifactId>
				<version>1.2.1</version>
				<configuration>
					<mainClass>org.test.int1.Main</mainClass>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

最新バージョンのSpring Framework、AspectJ、Jackson、およびslf4jを使用するためにアップデートしました。 (Saishin bājon no Spring Framework, AspectJ, Jackson, oyobi slf4j o shiyō suru tame ni appudēto shimashita.)

Spring MVCの例外処理デプロイメント記述子

私たちのweb.xmlファイルは以下のように見えます。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/spring.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<error-page>
		<error-code>404</error-code>
		<location>/resources/404.jsp</location>
	</error-page>
</web-app>

私たちのウェブアプリケーションにSpring Frameworkを組み込むためのほとんどの部分は、404エラーに対して定義されたエラーページ以外です。したがって、アプリケーションが404エラーをスローする場合、このページが応答として使用されます。この設定は、スプリングのウェブアプリケーションが404エラーコードをスローした場合にコンテナによって使用されます。

スプリングの例外処理 – モデルクラス

モデルクラスとしてEmployee beanを定義しましたが、アプリケーション内では特定のシナリオでの有効なレスポンスを返すために使用します。殆どの場合、意図的に異なるタイプの例外を投げます。

package com.scdev.spring.model;

public class Employee {

	private String name;
	private int id;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
}

JSONレスポンスも返すので、例外の詳細を含むJavaビーンを作成し、それをレスポンスとして送信しましょう。

package com.scdev.spring.model;

public class ExceptionJSONInfo {

	private String url;
	private String message;
	
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
}

スプリングの例外処理 – カスタム例外クラス

私たちのアプリケーションで使用するために、カスタム例外クラスを作成しましょう。

package com.scdev.spring.exceptions;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Employee Not Found") //404
public class EmployeeNotFoundException extends Exception {

	private static final long serialVersionUID = -3332292346834265371L;

	public EmployeeNotFoundException(int id){
		super("EmployeeNotFoundException with id="+id);
	}
}

以下のように言い換えることができます。

私たちのアプリケーションが例外クラスとともに@ResponseStatusアノテーションを使用して、アプリケーションでこのタイプの例外がスローされ、例外処理の実装で処理された場合に送信されるHTTPコードを定義できることに注意してください。私が404というHTTPステータスを設定していることがわかるように、このような例外の場合にはエラーページが定義されているため、ビューを返さない場合はアプリケーションがエラーページを使用するべきです。例外ハンドラメソッドではステータスコードを上書きすることもできます。例外ハンドラメソッドがビューページをレスポンスとして返さない場合のデフォルトのHTTPステータスコードと考えてください。

Spring MVCの例外処理Controllerクラスの例外ハンドラ

コントローラークラスを見て、さまざまな種類の例外を投げることにしましょう。

package com.scdev.spring.controllers;

import java.io.IOException;
import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.scdev.spring.exceptions.EmployeeNotFoundException;
import com.scdev.spring.model.Employee;
import com.scdev.spring.model.ExceptionJSONInfo;

@Controller
public class EmployeeController {
	
	private static final Logger logger = LoggerFactory.getLogger(EmployeeController.class);
	
	@RequestMapping(value="/emp/{id}", method=RequestMethod.GET)
	public String getEmployee(@PathVariable("id") int id, Model model) throws Exception{
		//deliberately throwing different types of exception
		if(id==1){
			throw new EmployeeNotFoundException(id);
		}else if(id==2){
			throw new SQLException("SQLException, id="+id);
		}else if(id==3){
			throw new IOException("IOException, id="+id);
		}else if(id==10){
			Employee emp = new Employee();
			emp.setName("Pankaj");
			emp.setId(id);
			model.addAttribute("employee", emp);
			return "home";
		}else {
			throw new Exception("Generic Exception, id="+id);
		}
		
	}
	
	@ExceptionHandler(EmployeeNotFoundException.class)
	public ModelAndView handleEmployeeNotFoundException(HttpServletRequest request, Exception ex){
		logger.error("Requested URL="+request.getRequestURL());
		logger.error("Exception Raised="+ex);
		
		ModelAndView modelAndView = new ModelAndView();
	    modelAndView.addObject("exception", ex);
	    modelAndView.addObject("url", request.getRequestURL());
	    
	    modelAndView.setViewName("error");
	    return modelAndView;
	}	
}

EmployeeNotFoundExceptionハンドラーには、ModelAndViewを返しているので、httpステータスコードはOK(200)として送信されます。もしvoidを返していた場合は、httpステータスコードは404となります。このような実装方法は、グローバルな例外ハンドラーの実装にて検討します。コントローラーでEmployeeNotFoundExceptionのみを処理しているため、他の例外はグローバルな例外ハンドラーによって処理されます。

@ControllerAdvice と @ExceptionHandler

こちらは私たちのグローバル例外処理のコントローラークラスです。クラスには@ControllerAdviceのアノテーションが付けられています。また、メソッドには@ExceptionHandlerのアノテーションが付けられています。

package com.scdev.spring.controllers;

import java.io.IOException;
import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class GlobalExceptionHandler {

	private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
	
	@ExceptionHandler(SQLException.class)
	public String handleSQLException(HttpServletRequest request, Exception ex){
		logger.info("SQLException Occured:: URL="+request.getRequestURL());
		return "database_error";
	}
	
	@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="IOException occured")
	@ExceptionHandler(IOException.class)
	public void handleIOException(){
		logger.error("IOException handler executed");
		//returning 404 error code
	}
}

SQLExceptionの場合、レスポンスページとしてdatabase_error.jspを返し、HTTPステータスコードは200としています。IOExceptionの場合、ステータスコードが404でvoidを返すため、この場合はエラーページが使用されます。ここで他の種類の例外を処理していないことがわかると思いますが、その部分はHandlerExceptionResolverの実装に任せています。

ハンドラーエクセプションリゾルバ

私たちはただSimpleMappingExceptionResolverを拡張して、その中の1つのメソッドをオーバーライドしていますが、ログ記録や異なる種類のビューページの送信のために、最も重要なメソッドresolveExceptionもオーバーライドすることができます。しかし、それはControllerAdviceの実装を使用するのと同じですので、私はそれを残しています。私たちは、私たちが処理していない他のすべての例外に対して汎用エラーページで応答するためにビューページを構成するためにそれを使用する予定です。

春の例外処理の設定ファイル

私たちの春のビーン設定ファイルは以下のようになっています。spring.xmlのコードは次のようです。

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="https://www.springframework.org/schema/beans"
	xmlns:context="https://www.springframework.org/schema/context"
	xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	
	<beans:bean id="simpleMappingExceptionResolver" class="com.scdev.spring.resolver.MySimpleMappingExceptionResolver">
		<beans:property name="exceptionMappings">
			<beans:map>
				<beans:entry key="Exception" value="generic_error"></beans:entry>
			</beans:map>
		</beans:property>
		<beans:property name="defaultErrorView" value="generic_error"/>
	</beans:bean>
	
	<!-- Configure to plugin JSON as request and response in method handler -->
	<beans:bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<beans:property name="messageConverters">
			<beans:list>
				<beans:ref bean="jsonMessageConverter"/>
			</beans:list>
		</beans:property>
	</beans:bean>
	
	<!-- Configure bean to convert JSON to POJO and vice versa -->
	<beans:bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
	</beans:bean>
	
	<context:component-scan base-package="com.scdev.spring" />
	
</beans:beans>

私たちのウェブアプリケーションでは、JSONをサポートするために設定されたビーンに注目してください。例外処理に関連する唯一の部分は、simpleMappingExceptionResolverビーンの定義であり、Exceptionクラスのviewページとしてgeneric_error.jspを定義しています。これにより、私たちのアプリケーションで処理されていない例外は、サーバーが生成したエラーページをレスポンスとして送信しないことが保証されます。

Spring MVCでの例外処理JSPビューページ

「私たちのアプリケーションの最後の部分、アプリケーションで使用されるビューページについて調べる時が来ました。home.jspのコードです。」

<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
	<h3>Hello ${employee.name}!</h3><br>
	<h4>Your ID is ${employee.id}</h4>  
</body>
</html>

home.jspは、クライアントのリクエストでidが10である場合、有効なデータで応答するために使用されます。404.jspのコードは以下の通りです。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>404 Error Page</title>
</head>
<body>

<h2>Resource Not Found Error Occured, please contact support.</h2>

</body>
</html>

クライアントのリクエストでIDが3の場合、404.jspは404 HTTPステータスコードのビューを生成するために使用されます。私たちの実装では、これが応答となるべきです。error.jspのコードです。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Error Page</title>
</head>
<body>
<h2>Application Error, please contact support.</h2>

<h3>Debug Information:</h3>

Requested URL= ${url}<br><br>

Exception= ${exception.message}<br><br>

<strong>Exception Stack Trace</strong><br>
<c:forEach items="${exception.stackTrace}" var="ste">
	${ste}
</c:forEach>

</body>
</html>

エラー.jspは、コントローラークラスのリクエストハンドラーメソッドがEmployeeNotFoundExceptionをスローした場合に使用されます。クライアントのリクエストでid値が1である場合、このページが応答として返されるべきです。database_error.jspコード:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Database Error Page</title>
</head>
<body>

<h2>Database Error, please contact support.</h2>

</body>
</html>

「database_error.jsp」は、私たちのアプリケーションがSQLExceptionをスローする場合に使用されます。これは、GlobalExceptionHandlerクラスで設定されています。クライアントのリクエストでid値が2の場合、このページをレスポンスとして受け取る必要があります。generic_error.jspのコード:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Generic Error Page</title>
</head>
<body>

<h2>Unknown Error Occured, please contact support.</h2>

</body>
</html>

アプリケーションコードで処理されない例外が発生した場合、simpleMappingExceptionResolverビーンがそれを処理するため、このページが応答として表示されるはずです。クライアントリクエストのid値が1、2、3、または10以外の場合にこのページを応答として受け取るべきです。

Spring MVCの例外処理アプリケーションを実行する

以下は、日本語でネイティブな表現を一つ挙げましょう。
この例では、使用しているサーブレットコンテナにアプリケーションを展開してください。私はこの例ではApache Tomcat 7を使用しています。以下の画像は、ID値に基づいて返されるアプリケーションの異なる応答ページを示しています。ID=10の場合、有効な応答です。ID=1の場合、コントローラベースの例外ハンドラが使用されます。ID=2の場合、ビューとして応答するためにグローバルな例外ハンドラが使用されます。ID=3の場合、404エラーページが使用されます。ID=4の場合、応答ビューとしてsimpleMappingExceptionResolverが使用されます。すべての場合で、期待どおりの応答を得ることができることがわかります。

春の例外ハンドラーのJSONレスポンス

私たちはチュートリアルのほとんどを終えました。ただし、最後の部分では、例外ハンドラメソッドからJSONレスポンスを送信する方法について説明します。アプリケーションにはすべてのJSON依存関係があり、jsonMessageConverterが設定されているため、例外ハンドラメソッドを実装する必要があります。簡単にするために、EmployeeControllerのhandleEmployeeNotFoundException()メソッドをJSONレスポンスを返すように書き直します。以下のコードでEmployeeControllerの例外ハンドラメソッドを更新し、アプリケーションを再度デプロイしてください。

	@ExceptionHandler(EmployeeNotFoundException.class)
	public @ResponseBody ExceptionJSONInfo handleEmployeeNotFoundException(HttpServletRequest request, Exception ex){
		
		ExceptionJSONInfo response = new ExceptionJSONInfo();
		response.setUrl(request.getRequestURL().toString());
		response.setMessage(ex.getMessage());
		
		return response;
	}

以下に示す画像のように、クライアントのリクエストでidを1として使用すると、次のようなJSONレスポンスが得られます。Springの例外処理とSpring MVCの例外処理に関しては以上です。さらに学ぶために、以下のURLからアプリケーションをダウンロードして試してみてください。

Springの例外処理プロジェクトをダウンロードしてください。

コメントを残す 0

Your email address will not be published. Required fields are marked *