Spring Mvc全局異常捕獲

我們在開發過程中,可能希望能夠統一地捕獲和處理異常,免得異常處理分佈在代碼各處

我們可以使用spring mvc提供的全局異常捕獲來實現這樣的功能

首先我們新建一個專門複雜異常處理的工程


com.lzw.exception.exception包裏是我們自定義的Exception

package com.lzw.exceptions.exception;

public class BookingExpiredException extends Exception {

	/**
	 * 
	 */
	private static final long serialVersionUID = 573537091646842099L;

}

com.lzw.exceptions.handler包裏面是我們對異常的處理

package com.lzw.exceptions.handler;

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

import com.lzw.exceptions.exception.BookingExpiredException;
import com.lzw.exceptions.exception.BookingNoSeatsException;

public class BookingExceptionHandler {
	
	@ExceptionHandler(value = BookingNoSeatsException.class)
	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR, reason = "no seats")
	@ResponseBody
	public void handleNoSeatsException(BookingNoSeatsException exception) {
		System.out.println("BookingNoSeatsException!");
	}
	
	@ExceptionHandler(value = BookingExpiredException.class)
	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR, reason = "booking expired")
	@ResponseBody
	public void handleExpiredException(BookingExpiredException exception) {
		System.out.println("BookingExpiredException!");
	}
}

com.lzw.exceptions.resolver包裏面的類負責對異常進行捕獲

package com.lzw.exceptions.resolver;

import java.lang.reflect.Method;

import org.springframework.core.Ordered;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.annotation.ExceptionHandlerMethodResolver;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod;

public class BookingExceptionHandlerResolver extends
		ExceptionHandlerExceptionResolver {

	private Object handler;
	private ExceptionHandlerMethodResolver methodResolver;

	public BookingExceptionHandlerResolver() {
		setOrder(Ordered.HIGHEST_PRECEDENCE);
	}

	public void setExceptionHandler(final Object handler) {
		this.handler = handler;
		this.methodResolver = new ExceptionHandlerMethodResolver(
				handler.getClass());
	}

	protected ServletInvocableHandlerMethod getExceptionHandlerMethod(
			final HandlerMethod handlerMethod, final Exception exception) {
		ServletInvocableHandlerMethod result = super.getExceptionHandlerMethod(
				handlerMethod, exception);
		if (result != null) {
			return result;
		}
		Method method = this.methodResolver.resolveMethod(exception);
		return (method != null) ? new ServletInvocableHandlerMethod(
				this.handler, method) : null;
	};
}

ExceptionHandlerExceptionResolver是spring mvc默認的異常處理器,我們可以通過繼承它來實現自己的處理邏輯

例如上面,我們繼承並實現了自己的BookingExceptionHandlerResolver,注入自己的異常處理器(BookingExceptionHandler),重寫了getExceptionHandlerMethod,使得異常發生時能從BookingExceptionHandler裏面取得處理該異常的處理方法


當業務代碼拋出異常的時候,如果所在的Controller沒有對異常進行處理,那麼異常就會拋出到Spring Mvc,Spring Mvc會在各個ExceptionHandlerExceptionResolver類(或子類)裏面查找能夠處理該異常的handler,然後在handler裏面找到處理那種異常的方法並執行


編寫好以上類後,我們通過把ExceptionHandlerExceptionResolver給聲明爲bean

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

	<bean class="com.lzw.exceptions.resolver.BookingExceptionHandlerResolver">
		<property name="exceptionHandler">
			<bean class="com.lzw.exceptions.handler.BookingExceptionHandler" />
		</property>
		<property name="messageConverters">
			<list>
				<bean
					class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
			</list>
		</property>
	</bean>

	<bean class="com.lzw.exceptions.resolver.PayExceptionHandlerResolver">
		<property name="exceptionHandler">
			<bean class="com.lzw.exceptions.handler.PayExceptionHandler" />
		</property>
		<property name="messageConverters">
			<list>
				<bean
					class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
			</list>
		</property>
	</bean>

</beans>

這樣最後把整個工程打成jar包,給其他工程使用


下面新建一個代表業務的工程

把之前的Exception工程通過maven給依賴進來


然後在Spring Mvc配置文件中引入Exception工程的配置文件

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

	<context:component-scan base-package="com.lzw.business" />
	<mvc:annotation-driven />

	<import resource="classpath:com/lzw/exceptions/exceptions.xml"/>
	
</beans>

最後看看Mvc的Controller

package com.lzw.business;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.lzw.exceptions.exception.BookingExpiredException;
import com.lzw.exceptions.exception.BookingNoSeatsException;
import com.lzw.exceptions.exception.PayNoMoneyException;
import com.lzw.exceptions.exception.PayTimeoutException;


@Controller
public class Test {
	
	@RequestMapping(value = "/testbooknoseats")
	public void TestBookingNoSeats() throws BookingNoSeatsException {
		throw new BookingNoSeatsException();
	}
	
	@RequestMapping(value = "/testbookexpired")
	public void TestBookingExpired() throws BookingExpiredException {
		throw new BookingExpiredException();
	}
	
	@RequestMapping(value = "/paynomoney")
	public void TestPayNoMoney() throws PayNoMoneyException {
		throw new PayNoMoneyException();
	}
	
	@RequestMapping(value = "/paytimeout")
	public void TestPayTimeout() throws PayTimeoutException {
		throw new PayTimeoutException();
	}
}

測試一下

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章