这里就总结工作中用到的自定义异常处理器两类方式:
1 、实现HandlerExceptionResolver
定义两个异常类:业务异常(BusException)、空指针异常(NullException)继承自RuntimeException
package com.demo.exception;
/**
* 业务异常
* @author Administrator
*
*/
public class BusException extends RuntimeException {
/**错误码*/
private String errorCode;
public BusException(String errorCode) {
this(errorCode, null, null);
}
public BusException(String errorCode, String message) {
this(errorCode, message, null);
}
public BusException(String errorCode, Throwable cause) {
this(errorCode, null, cause);
}
public BusException(String errorCode, String message, Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
@Override
public String getMessage() {
return super.getMessage();
}
}
package com.demo.exception;
/**
* 空指针异常
* @author Administrator
*
*/
public class NullException extends RuntimeException{
private String errorCode;
public NullException(String errorCode) {
this(errorCode, null, null);
}
public NullException(String errorCode, String message) {
this(errorCode, message, null);
}
public NullException(String errorCode, Throwable cause) {
this(errorCode, null, cause);
}
public NullException(String errorCode, String message, Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
@Override
public String getMessage() {
return super.getMessage();
}
}
定义异常的常量code:
package com.demo.exception;
public class ErrorCodeConstants {
public static final String NULL_ERROR = "01";
public static final String BUSINESS_ERROR = "02";
}
定义异常的处理器:
package com.demo.exception;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import com.demo.exception2.BusinessException;
/**
* 异常处理器
* @author kxl
*
*/
public class ErrorCodeExceptionHanler implements HandlerExceptionResolver {
public ModelAndView resolveException(HttpServletRequest req, HttpServletResponse resp, Object obj,
Exception ex) {
ModelAndView mv = new ModelAndView();
respJson(resp, ex);
return mv;
}
//将异常信息写回
void respJson(HttpServletResponse httpServletResponse, Exception ex) {
try {
Map map = new HashMap();
String errCode=null;
String errMsg=ex.getMessage();
if (ex instanceof NullException) {
errCode=((NullException)ex).getErrorCode();
}
if (ex instanceof BusException) {
errCode=((BusException)ex).getErrorCode();
}
map.put("errorCode", errCode);
map.put("errorMsg", errMsg);
httpServletResponse.addHeader("Content-Type", "application/json;chaset=UTF-8");
httpServletResponse.getOutputStream().write(JSON.toJSONBytes(map));
} catch (IOException e) {
e.printStackTrace();
}
}
}
springmvc的配置文件如下:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.demo" />
<mvc:annotation-driven>
mvc:annotation-driven>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
bean>
<bean id="handlerExceptionResolver" class="com.demo.exception.ErrorCodeExceptionHanler"/>
beans>
测试的controller:
package com.demo.exception;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@RequestMapping("/test")
public String test(@RequestParam Integer id){
if (id==null) {
throw new BusException(ErrorCodeConstants.NULL_ERROR,"参数为空");
}
if (id==0) {
throw new BusException(ErrorCodeConstants.BUSINESS_ERROR,"业务异常");
}
return null;
}
}
分别使用下面的测试url测试异常:
http://localhost:8087/test?id=0
响应:
{
"errorCode": "02",
"errorMsg": "业务异常"
}
http://localhost:8087/test?id=
响应:
{
"errorCode": "01",
"errorMsg": "参数为空"
}
2 、使用@ControllerAdvice@ExceptionHandler的全局异常处理器
定义3个异常类:业务异常(BussinessException)、数据库操作异常(DBException)、Http访问异常(HttpExcetpion)均继承自RuntimeException。
package com.demo.exception2;
/**
*业务异常
*/
public class BusinessException extends RuntimeException {
private String errCode;//错误码
public BusinessException() {
super();
}
public BusinessException(String errCode, Throwable cause) {
super(cause);
this.errCode = errCode;
}
public BusinessException(String errCode) {
super();
this.errCode = errCode;
}
public String getErrCode() {
return errCode;
}
}
package com.demo.exception2;
/**
* 数据库操作异常
* @author Administrator
*
*/
public class DBException extends RuntimeException {
private String errCode;
public DBException() {
super();
}
public DBException(String errCode, Throwable cause) {
super(cause);
this.errCode = errCode;
}
public DBException(String errCode) {
super();
this.errCode = errCode;
}
public String getErrCode() {
return errCode;
}
}
package com.demo.exception2;
/**
* http相关异常
* @author Administrator
*
*/
public class HttpException extends RuntimeException {
private String errCode;
public HttpException() {
super();
}
public HttpException(String errCode, Throwable cause) {
super(cause);
this.errCode = errCode;
}
public HttpException(String errCode) {
super();
this.errCode = errCode;
}
public String getErrCode() {
return errCode;
}
}
定义异常码类:
package com.demo.exception2;
/**
* 异常码
* @author Administrator
*
*/
public class ErroCodeConstants {
public static String BS_0="0000";//业务异常1
public static String BS_1="0001";//业务异常2
public static String HTTP_403="403";//http 异常1
public static String HTTP_404="404";//http 异常2
public static String DB_0="2000"; //db操作异常1
public static String DB_1="2001"; //db操作异常2
}
定义异常国际化文件resultCode.properties:
0000=业务异常1
0000=业务异常2
403=http访问异常403
404=http访问异常404
2000=数据库操作异常1
2001=数据库操作异常2
定义通用异常返回体:
package com.demo.exception2;
public class GenericResp {
// 请求的url
private String reqUrl;
// 错误码
private String code;
// 错误消息
private String message;
public GenericResp() {
super();
}
public GenericResp(String reqUrl, String code, String message) {
super();
this.reqUrl = reqUrl;
this.code = code;
this.message = message;
}
public String getReqUrl() {
return reqUrl;
}
public void setReqUrl(String reqUrl) {
this.reqUrl = reqUrl;
}
public String getCode() {
return code;
}
public String getMessage() {
return message;
}
public void setCode(String code) {
this.code = code;
}
public void setMessage(String message) {
this.message = message;
}
}
定义异常处理器:
package com.demo.exception2;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 自定义异常处理器
* @author kxl
*
*/
@ControllerAdvice
public class CustomExceptionHandler {
@Autowired
protected MessageSource messageSource;
/**
* 处理BusinessException
* @param request
* @param ex
* @return
*/
@ExceptionHandler(BusinessException.class)
@ResponseBody
public GenericResp handleBusinessException(HttpServletRequest request, BusinessException ex) {
GenericResp resp = null;
String url = request.getRequestURI();
String code = ex.getErrCode();
String msg = getExceptionMsg(code, ex, messageSource);;
resp = new GenericResp(url, code,msg);
return resp;
}
/**
* 处理DBException
* @param request
* @param ex
* @return
*/
@ExceptionHandler(DBException.class)
@ResponseBody
public GenericResp handleDBException(HttpServletRequest request, DBException ex) {
GenericResp resp = null;
String url = request.getRequestURI();
String code = ex.getErrCode();
String msg = getExceptionMsg(code, ex, messageSource);;
resp = new GenericResp(url, code,msg);
return resp;
}
/**
* 处理HttpException
* @param request
* @param ex
* @return
*/
@ExceptionHandler(HttpException.class)
@ResponseBody
public GenericResp HttpException(HttpServletRequest request, HttpException ex) {
GenericResp resp = null;
String url = request.getRequestURI();
String code = ex.getErrCode();
String msg = getExceptionMsg(code, ex, messageSource);;
resp = new GenericResp(url, code,msg);
return resp;
}
/**
* 获取异常消息
* @param code
* @param ex
* @param messageSource
* @return
*/
public static String getExceptionMsg(String code, Throwable ex, MessageSource messageSource) {
String msg = "";
try {
msg = messageSource.getMessage(code, null, LocaleContextHolder.getLocale());
}
catch (NoSuchMessageException e) {
}
if (StringUtils.isEmpty(msg)) {
msg=ex.getMessage();
}
return msg;
}
}
springmvc配置:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.demo" />
<mvc:annotation-driven>
mvc:annotation-driven>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<value>i18n/resultCodevalue>
property>
bean>
beans>
测试controller:
package com.demo.exception2;
import java.math.BigDecimal;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class TestController2 {
@ResponseBody
@RequestMapping(value="/test2",produces=MediaType.APPLICATION_JSON_VALUE)
public int test(Integer id){
if (id==null) {
throw new BusinessException(ErroCodeConstants.BS_0);
}
if (id==0) {
throw new BusinessException(ErroCodeConstants.BS_1);
}
if (id==403) {
throw new HttpException(ErroCodeConstants.HTTP_403);
}
if (id==404) {
throw new HttpException(ErroCodeConstants.HTTP_404);
}
if (id==2000) {
throw new DBException(ErroCodeConstants.DB_0);
}
if (id==2001) {
throw new DBException(ErroCodeConstants.DB_1);
}
return new Integer(1);
}
}
访问以下url测试异常:
业务异常测试:
http://localhost:8087/test2?id=
响应:
{
"reqUrl": "/test2",
"code": "0000",
"message": "业务异常2"
}
http://localhost:8087/test2?id=0
{
"reqUrl": "/test2",
"code": "0001",
"message": "业务异常2"
}
http异常测试:
http://localhost:8087/test2?id=403
{
"reqUrl": "/test2",
"code": "403",
"message": "http访问异常403"
}
http://localhost:8087/test2?id=404
{
"reqUrl": "/test2",
"code": "404",
"message": "http访问异常404"
}
数据库异常测试:
http://localhost:8087/test2?id=2000
{
"reqUrl": "/test2",
"code": "2000",
"message": "数据库操作异常1"
}
http://localhost:8087/test2?id=2001
{
"reqUrl": "/test2",
"code": "2001",
"message": "数据库操作异常2"
}