Spring 统一异常处理有 3 种方式,分别为:

  1. 使用 @ ExceptionHandler 注解
  2. 实现 HandlerExceptionResolver 接口
  3. 使用 @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 注解

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

请确保此WebExceptionHandle 类能被扫描到并装载进 Spring 容器中。

 @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");
}

如果 @ExceptionHandler 注解中未声明要处理的异常类型,则默认为参数列表中的异常类型。所以还可以写成这样:

@ControllerAdvice
public class GlobalExceptionHandler { @ExceptionHandler()
@ResponseBody
String handleException(Exception e){
return "Exception Deal! " + e.getMessage();
}
}

参数对象就是 Controller 层抛出的异常对象!

继承 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 处理程序统一异常的三种方式。

参考资料

@ControllerAdvice + @ExceptionHandler 全局处理 Controller 层异常

Spring MVC异常统一处理的三种方式的更多相关文章

  1. springmvc 异常统一处理的三种方式详解

    1 描述  在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的.不可预知的异常需要处理.每个过程都单独处理异常,系统的代码耦 ...

  2. spring mvc配置datasource数据源的三种方式

    2.使用org.apache.commons.dbcp.BasicDataSource 说明:这是一种推荐说明的数据源配置方式,它真正使用了连接池技术 <bean id="dataSo ...

  3. 【Java Web开发学习】Spring MVC异常统一处理

    [Java Web开发学习]Spring MVC异常统一处理 文采有限,若有错误,欢迎留言指正. 转载:https://www.cnblogs.com/yangchongxing/p/9271900. ...

  4. spring mvc获取路径参数的几种方式 - 浅夏的个人空间 - 开源中国社区

    body { font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI ...

  5. Spring MVC中forward请求转发2种方式(带参数)

    Spring MVC中forward请求转发2种方式(带参数) http://www.51gjie.com/javaweb/956.html  

  6. spring mvc 异常统一处理方式

    springMVC提供的异常处理主要有两种方式: 一种是直接实现自己的HandlerExceptionResolver: 另一种是使用注解的方式实现一个专门用于处理异常的Controller——Exc ...

  7. Spring学习之实例化bean的三种方式

    实例化bean的三种方式 构造器实例化bean Person.java public class Person { private String name; private Integer age; ...

  8. 【spring Boot】spring boot获取资源文件的三种方式【两种情况下】

    首先声明一点,springboot获取资源文件,需要看是 1>从spring boot默认的application.properties资源文件中获取 2>还是从自定义的资源文件中获取 带 ...

  9. spring中创建bean对象的三种方式以及作用范围

    时间:2020/02/02 一.在spring的xml配置文件中创建bean对象的三种方式: 1.使用默认构造函数创建.在spring的配置文件中使用bean标签,配以id和class属性之后,且没有 ...

随机推荐

  1. [漏洞分析]thinkcmf 1.6.0版本从sql注入到任意代码执行

    0x00 前言 该漏洞源于某真实案例,虽然攻击没有用到该漏洞,但在分析攻击之后对该版本的cmf审计之后发现了,也算是有点机遇巧合的味道,我没去找漏洞,漏洞找上了我XD thinkcmf 已经非常久远了 ...

  2. BeautifulSoup库的使用方法

    from bs4 import BeautifulSoup import lxml html = ''' <html><head><title>The Dormou ...

  3. memcached协议解析

    本文转载自:http://www.ccvita.com/306.html 协议memcached 的客户端使用TCP链接与服务器通讯.(UDP接口也同样有效,参考后文的 “UDP协议” )一个运行中的 ...

  4. python 元组和字典中元素作为函数调用参数传递

    模式1.  def test1(*args): test3(*args) def test2(**kargs): test3(**kargs) def test3(a, b): print(a,b) ...

  5. db2调优

    系统上线两个月左右,请IBM工程师对数据库进行了一次调优,主要收获感觉有以下几点: 1,应用服务器一定要与数据库服务器分开 2,如果存在多个数据库,一定要硬盘分开(io忙) 3,每个数据库的数据与日志 ...

  6. Android Developers:传感器概述

    大 多数Android设备有内置的传感器,来测量运动,方向和各种环境条件.这些传感器能提供高精度和准确度的原始数据,如果你想监控设备三维运动或者位 置,或者你想监控设备周围的环境变化,是非常有用的.例 ...

  7. 20个有用的linux命令行技巧

    20 Unix Command Line Tricks – Part I http://www.cyberciti.biz/open-source/command-line-hacks/20-unix ...

  8. linux命令行下修改系统时间、时区

    date查看时间以及时区 图a是est时区,和HONGkong时间查了一个小时. # 保存设置$ sudo mv /etc/localtime /etc/localtime.old # 设置时区 $ ...

  9. 使用Python登录Github网站

    在下面的代码中, 展示了使用Python脚本登录Github的方法. 如果需要登录别的网站,那么请使用Chrome的Inspect的功能寻找到目标的object,对代码进行替换. 代码先登录了gith ...

  10. GIS中栅格数据结构的显示与计算

    在GIS中,根据数据存储的表现形式不同,通常将空间数据分为矢量数据和栅格数据.最简单的区别是:当栅格数据放大到一定程度时,就会呈现出我们熟悉的讨厌的"马赛克". 栅格数据存储 最简 ...