“叭”,除畜生道劳役之苦;

在学过的三阶段的时候,我们对SpringMVC的异常处理,一直可以算是简单中透着暴力,不要不重视异常!真的很重要,不要让它处在尴尬的位置!

在二阶段或者说三阶段中,技术一方面其中我认为最关键的地方是MVC思想的理解,对MVC理解程度决定着你学习过程中的难易程度,虽然有点夸张!

例如,当我们产生了一个 非业务异常 ,或者 非本业务可以处理的其他业务异常 ,那么我们一般会一直往 上层抛 (或者适当包装后继续抛出)直到 控制层 [我们就是这么解决问题,不知道你是否还记得],之后,控制层进行异常日志记录然后响应用户错误页面和信息。

如果每个控制器都写一个异常处理未免也太多冗余了,好在强大的 Spring 给我们提供了很多种解决方案,这里介绍其中一种 @ControllerAdvice [个人认为目前最好的方案之一,XML方式的简单统一异常处理,这里就不说了]。

1. 为什么现在我才告诉你呢?

看该注解字面上的意思就是 控制器通知

Advice 是AOP中的概念,这里简单介绍下。

我们使用AOP切入某一目标方法,那么该方法在切面的角度看来可以有几个执行阶段:

  • 目标方法调用前(before)- 前置通知
  • 目标方法调用后(after)- 后置通知
  • 目标方法返回后(after return)- 返回通知
  • 目标方法调用前后(around)- 环绕通知
  • 目标方法抛出异常时(throw)- 异常通知

是否还记得每种通知的特点呢?呵呵!忘记了吧!

去看笔记或者PPT吧!!!

当执行到某个阶段的时候都会有不同阶段类型 Advice 发出,然后你可以根据不同阶段类型的通知对切入点进行一些 增强处理 了。

在不改动原来代码的基础上,增加新的功能!

看看如何声明@ControllerAdvice

  1. /**
  2. * 全局异常处理器
  3. * @author 胖先生
  4. *
  5. */
  6. @ControllerAdvice
  7. public class GlobalExceptionHandler {
  8. }

So Easy!标注完之后,该类就变成一个控制器通知处理器了,接着我们需要进行一些通知的处理。

解除痛苦

在该类中的方法上标注 @ExceptionHandler 可以将指定方法变成一个异常通知处理方法,处理的异常类型可使用参数指定。除了 @ExceptionHandler 之外还有其他的通知类型,具体可参阅官方文档,本文只以异常处理为例子,事实上运用最广泛的也就是异常处理而已了。

新增以下代码可以处理 HttpRequestMethodNotSupportedException (HTTP方法不支持):

  1. @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
  2. @ResponseBody
  3. public Result<String> httpRequestMethodNotSupportedExceptionHandler(HttpServletRequest req, Exception e) throws Exception{
  4. if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
  5. throw e;
  6. // Otherwise setup and send the user to a default error-view.
  7. // 这里你可以自由发挥,咱在这里给前端返回了一个错误提醒的Json
  8. Result<String> result = new Result<>(false);
  9. result.setError(HohistarExceptionReason.BIZ_10070);
  10. return result;
  11. }

新增以下代码可以处理 MethodArgumentNotValidException(Validator字段校验失败异常处理):

  1. @ExceptionHandler(MethodArgumentNotValidException.class)
  2. @ResponseBody
  3. public Result<String> methodArgumentNotValidExceptionHandler(HttpServletRequest req, MethodArgumentNotValidException e) throws Exception{
  4. if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
  5. throw e;
  6. BindingResult bindingResult = e.getBindingResult();
  7. // Otherwise setup and send the user to a default error-view.
  8. Result<String> result = new Result<>(false);
  9. FieldError firstError = bindingResult.getFieldErrors().get(0);
  10. result.setError(HohistarExceptionReason.BIZ_10074, firstError.getField(), firstError.getDefaultMessage());
  11. return result;
  12. }

如果要成功捕获 MethodArgumentNotValidException ,在控制器方法上就不能定义 BindingResult 参数接收校验结果,不然如果校验失败 Spring 是不会抛出 MethodArgumentNotValidException 异常的,自然而然在我们的 GlobalExceptionHandler 就无法处理了。

一个都不放过

如果你要捕获任何漏网之异常,你可以新增以下暴力的代码:

  1. @ExceptionHandler(value = Exception.class)
  2. @ResponseBody
  3. public Result<String> defaultExceptionHandler(HttpServletRequest req, Exception e) throws Exception {
  4. // If the exception is annotated with @ResponseStatus rethrow it and let
  5. // the framework handle it - like the OrderNotFoundException example
  6. // at the start of this post.
  7. // AnnotationUtils is a Spring Framework utility class.
  8. if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
  9. throw e;
  10. String throwClassName = e.getStackTrace()[0].getClassName();
  11. Logger logger = getLogger(throwClassName);
  12. logger.error("GlobalExceptionHandler catch a Server Exception: ", e);
  13. // Otherwise setup and send the user to a default error-view.
  14. Result<String> result = new Result<>(false);
  15. if(BeanUtils.isNotEmpty(this.defaultExceptionReason)){
  16. result.setError(HohistarExceptionReason.valueOf(this.defaultExceptionReason));
  17. } else {
  18. result.setError(HohistarExceptionReason.INTL_20001);
  19. }
  20. return result;
  21. }

GlobalExceptionHandler 中可以有多个 @ExceptionHandler 标注的方法,如果控制器中抛出了一个异常,而且没有匹配任何其他类型的异常处理方法,那么上方的方法将会被通知执行, 保证从控制器抛出的异常一定会受到处理

大部分代码来自官方文档:这里大部分摘抄Spring官方手册

[六字真言]4.叭.SpringMVC异常痛苦的更多相关文章

  1. [六字真言]6.吽.SpringMVC中上传大小异常填坑

    最近在讲课的时候,遇到了关于上传文件过大的时候浏览器无法响应的问题,配置了捕获异常,有的学生浏览器好使,有的学生浏览器不好用!莫名其妙! MaxUploadSizeExceededException进 ...

  2. [六字真言]2.嘛.异常定制和通用.md

    幻世当空 恩怨休怀 舍悟离迷 六尘不改 且怒且悲且狂哉! 最近一直在循环的一首歌! 丰富自己,比取悦他人更有力量.种下梧桐树,引得凤凰来.你若盛开,蝴蝶自来! 言归正传! 言归正传! 不要去大包大揽 ...

  3. [六字真言]5.咪.功力不足,学习前端JavaScript异常

    A Guide to Proper Error Handling in JavaScript 这是关于JavaScript中异常处理的故事.如果你相信 墨菲定律 ,那么任何事情都可能出错,不,一定会出 ...

  4. 七字真言解读TCP三次握手

    三次握手所谓的"三次握手"即对每次发送的数据量是怎样跟踪进行协商使的发送和接收同步,根据所接收到的数据量而确定的数据确认数及数据发送.接收完毕后何时撤消联系,并建立虚连接. 一.七 ...

  5. springMVC 异常

    springMVC  异常 0.依赖(不只是本次案例所需) <?xml version="1.0" encoding="UTF-8"?> <p ...

  6. SpringMVC异常的处理机制

    SpringMVC异常的处理机制 处理流程图 其本质还是把异常交给SpringMVC框架来处理 系统的dao.service.controller出现异常都通过throws Exception向上抛出 ...

  7. SpringMVC异常处理器

    本节内容: 异常处理思路 自定义异常类 自定义异常处理器 异常处理器配置 错误页面 异常测试 springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异 ...

  8. springMVC异常&&重定向&&转发

    SpringMVC核心技术---转发和重定向 当处理器对请求处理完毕后,向其他资源进行跳转时,有两种跳转方式:请求转发与重定向.而根据要跳转的资源类型,又可分为两类:跳转到页面与跳转到其他处理器.对于 ...

  9. SSM-SpringMVC-26:SpringMVC异常骇级之自定义异常注解版

     ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 注解的方法实现异常解析,话不多说,直接搞起,和以前一样的习惯,和上篇博客一样的代码放后面,不一样的在前面 案 ...

随机推荐

  1. 一个可以代替冗长switch-case的消息分发小框架

    在项目中,我需要维护一个应用层的字节流协议.这个协议的每条报文都是一个字节数组,数组的头两个字节表示消息的传送方向,第三.四个字节表示消息ID,也就是消息种类,再往后是消息内容.时间戳.校验码等……整 ...

  2. Boyer and Moore Fast majority vote algorithm(快速选举算法)

    问题来来自于leetcode上的一道题目,https://leetcode.com/problems/majority-element/,大意是是找出一个数组中,出现次数超过一个半的数字,要求是O(n ...

  3. Mvc4_mvc4跟mysql语法

    mvc4: 子页面:@section A{} 母页面:@RenderSection("A",false) false:别的页面没有定义为A的Section的话 也没事,layout ...

  4. OpenCV学习资源库

    整理了我所了解的有关OpenCV的学习笔记.原理分析.使用例程等相关的博文.排序不分先后,随机整理的.如果有好的资源,也欢迎介绍和分享. 1:OpenCV学习笔记 作者:CSDN数量:55篇博文网址: ...

  5. 关于java线程池的一丢丢

    线程池应用达到的目的 1.降低资源消耗:可以重复利用已创建的线程从而降低线程创建和销毁所带来的消耗. 2.提高响应速度:当任务到达时,不需要等线程创建就可以立即执行. 3.提高线程的可管理性:使用线程 ...

  6. c语言数字图像处理(二):图片放大与缩小-双线性内插法

    图像内插 假设一幅大小为500 * 500的图像扩大1.5倍到750 * 750,创建一个750 * 750 的网格,使其与原图像间隔相同,然后缩小至原图大小,在原图中寻找最接近的像素(或周围的像素) ...

  7. 【Beta阶段】第二次Scrum Meeting!

    每日任务内容: 本次会议为第二次Scrum Meeting会议~ 由于本次会议项目经理召开时间较晚,所以在公寓7层召开,所以女生没来…召开时间大家集会10分钟,经理与后端探讨20分钟. 队员 昨日完成 ...

  8. 《Linux内核分析》第二周学习小结 操作系统是如何工作的?

    郝智宇   无转载   <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.函数调用堆栈: 1.计算机是 ...

  9. 第二个Sprint冲刺第三天(燃尽图)

  10. 2013 C#单元测试

    首先安装Unit Test Generator. 点击拓展和更新——>联机搜索Unit Test Generator 新建项目 新建一个测试类  add函数 选定test 类名 ——>右键 ...