您的位置:首页 > 编程语言 > Java开发

Spring MVC异常统一处理的三种方式

2017-11-15 18:07 519 查看
Spring 统一异常处理有 3 种方式,分别为:

使用 @ ExceptionHandler 注解

实现 HandlerExceptionResolver 接口

使用 @controlleradvice 注解

使用 @ ExceptionHandler 注解

使用该注解有一个不好的地方就是:_进行异常处理的方法必须与出错的方法在同一个Controller里面。使用如下:

@Controller
public class GlobalController {

/**
* 用于处理异常的
* @return
*/
@ExceptionHandler({MyException.class})
public String exception(MyException e) {
System.out.println(e.getMessage());
e.printStackTrace();
return "exception";
}

@RequestMapping("test")
public void test() {
throw new MyException("出错了!");
}
}


可以看到,这种方式最大的缺陷就是不能全局控制异常。每个类都要写一遍。

实现 HandlerExceptionResolver 接口

这种方式可以进行全局的异常控制。例如:

@Component
public class ExceptionTest implements HandlerExceptionResolver{

/**
* TODO 简单描述该方法的实现功能(可选).
* @see org.springframework.web.servlet.HandlerExceptionResolver#resolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
*/
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
System.out.println("This is exception handler method!");
return null;
}
}


使用 @ControllerAdvice 注解

上文说到 @ ExceptionHandler 需要进行异常处理的方法必须与出错的方法在同一个Controller里面。那么当代码加入了 @ControllerAdvice,则不需要必须在同一个 controller 中了。这也是 Spring 3.2 带来的新特性。 也就是说,@controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。

那么,在实际中,就可以使用 @controlleradvice + @ ExceptionHandler。

@ControllerAdvice
@ResponseBody
public class WebExceptionHandle {
private static Logger logger = LoggerFactory.getLogger(WebExceptionHandle.class);
/**
* 400 - Bad Request
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class)
public ServiceResponse handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
logger.error("参数解析失败", e);
return ServiceResponseHandle.failed("could_not_read_json");
}

/**
* 405 - Method Not Allowed
*/
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public ServiceResponse handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
logger.error("不支持当前请求方法", e);
return ServiceResponseHandle.failed("request_method_not_supported");
}

/**
* 415 - Unsupported Media Type
*/
@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
public ServiceResponse handleHttpMediaTypeNotSupportedException(Exception e) {
logger.error("不支持当前媒体类型", e);
return ServiceResponseHandle.failed("content_type_not_supported");
}

/**
* 500 - Internal Server Error
*/
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(Exception.class)
public ServiceResponse handleException(Exception e) {
if (e instanceof BusinessException){
return ServiceResponseHandle.failed("BUSINESS_ERROR", e.getMessage());
}

logger.error("服务运行异常", e);
e.printStackTrace();
return ServiceResponseHandle.failed("server_error");
}
}


继承 ResponseEntityExceptionHandler 类来实现针对 Rest 接口 的全局异常捕获,并且可以返回自定义格式:

@Slf4j
@ControllerAdvice
public class ExceptionHandlerBean  extends ResponseEntityExceptionHandler {

/**
* 数据找不到异常
* @param ex
* @param request
* @return
* @throws IOException
*/
@ExceptionHandler({DataNotFoundException.class})
public ResponseEntity<Object> handleDataNotFoundException(RuntimeException ex, WebRequest request) throws IOException {
return getResponseEntity(ex,request,ReturnStatusCode.DataNotFoundException);
}

/**
* 根据各种异常构建 ResponseEntity 实体. 服务于以上各种异常
* @param ex
* @param request
* @param specificException
* @return
*/
private ResponseEntity<Object> getResponseEntity(RuntimeException ex, WebRequest request, ReturnStatusCode specificException) {

ReturnTemplate returnTemplate = new ReturnTemplate();
returnTemplate.setStatusCode(specificException);
returnTemplate.setErrorMsg(ex.getMessage());

return handleExceptionInternal(ex, returnTemplate,
new HttpHeaders(), HttpStatus.OK, request);
}

}


以上就是 Spring 处理程序统一异常的三种方式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: