[六字真言]4.叭.SpringMVC异常痛苦

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

在学过的三阶段的时候,我们对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官方手册

来自为知笔记(Wiz)

时间: 2024-10-13 20:15:25

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

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

最近在讲课的时候,遇到了关于上传文件过大的时候浏览器无法响应的问题,配置了捕获异常,有的学生浏览器好使,有的学生浏览器不好用!莫名其妙! MaxUploadSizeExceededException进入了无限的死循环,╮(╯▽╰)╭ 悲催! 为什么呢? 配置上传信息 在springmvc的核心配置文件配置如下信息 <!-- 5.配置上传 --> <bean id="multipartResolver" class="org.springframework.w

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

幻世当空 恩怨休怀 舍悟离迷 六尘不改 且怒且悲且狂哉! 最近一直在循环的一首歌! 丰富自己,比取悦他人更有力量.种下梧桐树,引得凤凰来.你若盛开,蝴蝶自来! 言归正传! 言归正传! 不要去大包大揽 人懒就是动力,我上课的时候为了图省事,经常利用 Exception 捕捉所有潜在的异常这里更正一下,这样的思想不对的,人的能力和经历是有限的,不要让他成为万能的! publicvoid update(User user){ try{ // 假设场景 //…抛出 IOException 的代码调用 /

诚念六字真言的一点体悟

六字真言: 嗡(ong)嘛(ma)呢(ni)呗(bei)咪(mei)吽(hong) 中文的发音有多种,但其实这并不重要,按自己的感觉和喜欢的念就行, 念这个,其实我也没有什么正式规矩怎样怎样的念,有时候心念或听乐曲上的. 后来偶有做恶梦,在梦中我竟然也能念起,然后便恐惧退散了!~ 呵呵,这不管是心理作用还是其他什么,总觉得应该是不错的,毕竟此咒含有诸佛无尽的加持和慈悲,是诸佛 慈悲和智慧的音声显现,此咒即是观世音菩萨的微妙本心! 嗡嘛呢呗咪吽

[六字真言]3.呢.异常的谎言,你要相信多少次?

"嘛,呢",梵文意为"如意宝",表示"宝部心",又叫嘛呢宝,其实就是有"聚宝"的意思! 现在的社会现在的人,都是喜欢虚的假的,不喜欢真的诚的,谁虚伪谁高人一等,谁真诚谁傻瓜一个,这句话很现实的,会做的不如会说的. 这就是现实,真情可贵,用心陪醉,虚伪面对,从容领会,我就是永远都学不会 不知道最近心是怎么样了,周围发生了一些固有的定律,其实知道,只是不说!有的时候感觉大家都是聪明人,但是都在做不聪明的事情! 重复多次的"

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

A Guide to Proper Error Handling in JavaScript 这是关于JavaScript中异常处理的故事.如果你相信 墨菲定律 ,那么任何事情都可能出错,不,一定会出错!这篇文章中我们来看下JavaScript中的出错处理.文章会覆盖异常处理使用的正反例,然后看下ajax的异步处理. JavaScript的事件驱动机制让JavaScript更加丰富,浏览器好比就是一个事件驱动的机器,错误也是一种事件.当一个错误发生时,一个事件就在某个点抛出.理论上,有人会说错误

SpringMVC异常_Could not resolve view with name &#39;javascripts/jquery-2.1.4&#39; in servlet with name &#39;springMVC&#39;

今天在编写代码的时候,自己页面中的按钮都无法点击,CSS样式也无法加载出来,查看之前的Spring MVC 的配置文件也是都正常,查看后台,发现如下错误 严重: Servlet.service() for servlet [springMVC] in context with path [/spring-idap-web] threw exception [Could not resolve view with name 'javascripts/jquery-2.1.4' in servlet

JVM【第六回】:【OutOfMemoryError异常之虚拟机栈和本地方法栈溢出】

由于在HotSpot虚拟机中并不区分虚拟机栈和本地方法栈,因此对于HotSpot来说,-Xoss参数(设置本地方法栈大小)虽然存在,但实际上是无效的,栈容量只由-Xss参数设定.关于虚拟机栈和本地方法栈,在Java规范中描述了两种异常: 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常. 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常. 在下面的代码中,如果将范围限制于单线程中的操作,尝试下面两种方法均无法让

社群运营之裂变六字诀

裂变带来的低成本.快速获客这件事,可以说是社群鸭运营及微信群生态最吸引创业者的能力.随着创业者不断地尝试.微信不断地调整,越来越多东西被逐渐明确,是时候做第一层的梳理了. 比如,想要大裂变,理解和用好这"六"个字就好,它们是:拼.帮.砍.送.比.换,见实称之为"裂变六字诀". 第一个字是"拼",拼单的拼.用户可以呼朋引伴,一起拼一件更低价格的商品. 第二个字是"帮".帮忙的帮.用户在体验产品的过程中需要帮助随时向好友求助. 第

SpringMVC异常的使用

1.创建一个异常类,需要extend RuntimeException,继承父类中所有的方法 2.局部异常,仅能处理这个Controller中的异常 在Controller中添加异常处理方法 @ExceptionHandler(value={UserException.class}) public String handlerExceString(UserException e,HttpServletRequest req){  req.setAttribute("e", e);  r