SpringBoot 如何配置全局的异常捕获

SpringBoot中自带的异常捕获机制返回的默认页面比较丑,对用户来说不够人性化。

所以这篇文章来讲解SpringBoot钟自定义全局异常捕获。

主要讲解三种异常捕获形式

  1. 页面跳转异常

  2. ajax异常

  3. 统一返回异常的形式

分别来看三种形式的全局异常捕获:

1.页面跳转异常

首先新建一个异常:

package com.topjavaer.exceptiondemo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;/*** @author javaHuang* @date 2018/6/19 16:57* @description*/
@Controller
@RequestMapping(value = "/err")
public class ErrorCtrl {@RequestMapping(value = "/error")public String error(){int a = 1/0;return "abcdefg";}
}

浏览器请求,会得到SpringBoot默认的异常页面:

新建异常处理工具类MyExceptionHandler:

package com.topjaver.exceptiondemo.utils;import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** @author javaHuang* @date 2018/6/19 17:16* @description*/
@ControllerAdvice
public class MyExceptionHandler {public static final String ERROR_VIEW = "my_error";@ExceptionHandler(value = Exception.class)//指定拦截的异常public Object errorHandler(HttpServletRequest request, HttpServletResponse response,Exception e) throws Exception{e.printStackTrace();//打印异常信息ModelAndView mv = new ModelAndView();mv.addObject("exception",e);mv.addObject("url",request.getRequestURL());//发生异常的路径mv.setViewName(ERROR_VIEW);//指定发生异常之后跳转页面return mv;}
}

这里我们使用了@ControllerAdvice标注,可以将其理解为增强型控制器,想要了解关于其更多信息请自行百度。

@ExceptionHandler标注用于指定需要拦截的异常。

其余的代码没有需要过多解释的,目的就是在系统中发生了指定的异常时,进行捕获,并返回指定的异常处理路径。我们在resources/templates下新建my_error.html:

这里有一点需要强调:我之前新建的异常跳转页面取名为error.html,这样会报错EL1008L:

org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'timestamp' cannot be found on object of type 'java.util.HashMap...

后来在这篇帖子中找到了解决办法:http://makaidong.com/FlyAway2013/104144_12644765.html,我的理解是,SpringBoot中有默认的异常跳转路径(可能命名为error),而且其中有timestamp的属性,而当我们发生异常指定其跳转至error.html时,系统会以为是要跳转至默认的异常处理路径,就会去加载timestamp属性,这时当然是加载不到的,因为我们并没有设置这个属性。

所以,这里最好不要将自定义的异常跳转路径命名为error。

我们再在浏览器中请求err/error:

得到了我们想要的结果,小伙们可以打断点看一下。当然这个只是一个测试页面,并不美观。正式环境中当然会有专业的美工和前端来设计报错页面。

2.ajax异常

如果出现ajax异常而不捕获的话,就会一直loading,用户体验更加不好。所以ajax请求也需要处理。

我们首先要将之前创建的MyExceptionHandler类删除掉,避免其产生影响(只需要将类头部的@ControllerAdvice标注和方法头部的@ExceptionHandler标注注释掉即可)

然后新建ajax形式的异常处理工具类,命名为MyAjaxExceptionHandler

package com.topjavaer.thymeleafdemo.utils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;/*** @author javaHuang* @date 2018/6/19 18:41* @description*/
@RestControllerAdvice
public class MyAjaxExceptionHandler {@ExceptionHandler(value = Exception.class)public CommonRspVo defaultErrorHandler(HttpServletRequest request,Exception e)throws Exception{e.printStackTrace();CommonRspVo rsp = new CommonRspVo("555",e.getMessage());return rsp;}
}

这里和之前页面跳转异常的不同在于类头部的标注换成了@RestControllerAdvice,其他的地方基本一致。在这里,当ajax异常发生时,我使用了一个简单的包装类返回信息给前台。

在ErrorCtrl中新增两个方法:

    //跳转到发生ajax异常页面@RequestMapping("/ajaxerror")public String ajaxerror(){return "thymeleaf/ajaxerror";}//发生ajax异常@RequestMapping("/getAjaxerror")public int getAjaxerror(){int a = 1/0;return a;}

其中ajaxerror方法用于跳转到前台,getAjaxerror方法用于接收前台ajax请求并制造异常。我们新建ajaxerror.html及ajaxerror.js:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.springframework.org/schema/mvc">
<head><meta charset="UTF-8"><title>Title</title><script type="text/javascript" th:src="@{/js/jquery.min.js}"></script>
</head>
<body><h1>测试ajax错误异常</h1><script type="text/javascript" th:src="@{/js/ajaxerror.js}"></script>
</body>
</html>$.ajax({url:"/err/getAjaxerror",type:"POST",async:false,success:function(data){debugger;if(data.code == "200"){alert("success!");}else {alert("发生异常:"+ data.message);}},error:function(){alert("error");}
})

在浏览器中发起请求,跳转至ajaxerror.html页面,立即向后台发起ajax请求,并发生1/0异常,这时会被自定义的MyAjaxExceptionHandler捕获到,然后将异常信息等返回前台。

3.统一异常处理

web页面跳转和ajax异常的统一异常处理也是非常简单的,主要就是整合一下前两步的思路。可以判断前端请求request是否是ajax请求,然后采取不同的措施。

我们还是使用第一步中使用的MyExceptionHandler异常处理助手类,将之前写好的errorHandler方法注释掉,并在其中添加如下两个方法:

@ExceptionHandler(value = Exception.class)
public Object errorHandler(HttpServletRequest request,HttpServletResponse response,Exception e)throws Exception{e.printStackTrace();if(isAjax(request)){//是ajax请求CommonRspVo rsp = new CommonRspVo("555",e.getMessage());return rsp;}else{//不是ajax请求ModelAndView mv = new ModelAndView();mv.addObject("exception",e);mv.addObject("url",request.getRequestURL());//发生异常的路径mv.setViewName(ERROR_VIEW);//指定发生异常之后跳转页面return mv;}}private boolean isAjax(HttpServletRequest request){//判断request是否是ajax请求return (request.getHeader("X-Requested-With") != null&& "XMLHttpRequest".equals( request.getHeader("X-Requested-With").toString()) );}

其中,isAjax方法用于判断HttpServletRequest是否是ajax请求。

这里需要注意的一点是,我们需要将MyExceptionHandler类头部的@ControllerAdvice标注修改为@RestControllerAdvice,否则在进行ajax异常捕获之后会报出TemplateInputException

我们可以根据之前的err/error和err/ajaxerror路径分别进行页面跳转异常和ajax异常的测试,通过dubug调试可以更清楚的看到程序的执行过程。

IT技术分享社区

个人博客网站:https://programmerblog.xyz

文章推荐程序员效率:画流程图常用的工具程序员效率:整理常用的在线笔记软件远程办公:常用的远程协助软件,你都知道吗?51单片机程序下载、ISP及串口基础知识硬件:断路器、接触器、继电器基础知识

《SpringBoot从菜鸟到老鸟》之SpringBoot 如何配置全局的异常捕获相关推荐

  1. SpringBoot配置全局的异常捕获

    需要以下两个类配合完成: IoExceptionHandler.java(异常助手类) IMoocJSONResult.java(实体类) package com.blog.pojo;import o ...

  2. springboot怎么返回404_深度分析:SpringBoot异常捕获与封装处理,看完你学会了吗?...

    简介 日常开发过程中,难免有的程序会因为某些原因抛出异常,而这些异常一般都是利用try ,catch的方式处理异常或者throw,throws的方式抛出异常不管.这种方法对于程序员来说处理也比较麻烦, ...

  3. springboot redis 刷新时间_「SpringBoot实战」SpringCache + Redis实现数据缓存

    关注我的微信公众号:后端技术漫谈 不定期推送关于后端开发.爬虫.算法题.数据结构方面的原创技术文章,以及生活中的逸闻趣事. 我目前是一名后端开发工程师.主要关注后端开发,数据安全,网络爬虫,物联网,边 ...

  4. springboot 自动装配_Java互联网架构-SpringBoot自动装配核心源码剖析

    欢迎关注头条号:java小马哥 周一至周日早九点半!下午三点半!精品技术文章准时送上!!! 精品学习资料获取通道,参见文末 用了差不多两年的SpringBoot了,可以说对SpringBoot已经很熟 ...

  5. SpringBoot系列三:SpringBoot基本概念(统一父 pom 管理、SpringBoot 代码测试、启动注解分析、配置访问路径、使用内置对象、项目打包发布)...

    声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.了解SpringBoot的基本概念 2.具体内容 在之前所建立的 SpringBoot 项目只是根据官方文档实现的一个基础程 ...

  6. springboot学习笔记:12.解决springboot打成可执行jar在linux上启动慢的问题

    springboot学习笔记:12.解决springboot打成可执行jar在linux上启动慢的问题 参考文章: (1)springboot学习笔记:12.解决springboot打成可执行jar在 ...

  7. springboot获取resources路径_Docker构建SpringBoot应用

    1.基于Dockerfile构建SpringBoot镜像 1.1准备工作 将SpringBoot项目通过maven打成jar包: mvn clean package 1.2使用Dockerfile构建 ...

  8. onresize事件会被多次触发_玩转SpringBoot之通过事件机制参与SpringBoot应用的启动过程...

    生命周期和事件监听 一个应用的启动过程和关闭过程是归属到"生命周期"这个概念的范畴. 典型的设计是在启动和关闭过程中会触发一系列的"事件",我们只要监听这些事件 ...

  9. SpringBoot | 第一章:第一个SpringBoot应用

    2019独角兽企业重金招聘Python工程师标准>>> SpringBoot | 第一章:第一个SpringBoot应用 springboot简单介绍 概述 随着动态语言的流行(Ru ...

最新文章

  1. 浅析2007年商业智能领域上演的收购大戏
  2. Spring整合Hibernate
  3. MappedByteBuffer VS FileChannel 孰强孰弱?
  4. 洛谷P4742(tarjan缩点+拓扑DP)
  5. SAP Cloud for Customer前台发送到后台的HTTP请求,遇到错误该怎么分析
  6. python的特性是_python的特性
  7. QuickMan 手记 - Activiti 环境搭建
  8. Unity Failed executing external process for 'Bake Runtime' job
  9. NVIDIA SMI 无法与 nvidia driver 通信
  10. CATransition 动画处理视图切换
  11. javascript之querySelector和querySelectorAll
  12. (转)一个百倍股的坠落:那个曾经满大街的ESPRIT是如何衰败的
  13. radius源码下载
  14. win10 linux 无法下载,更新win10后不能安装ubuntu的解决方法
  15. 太极root权限_太极框架免root版下载
  16. 计算机 管理 mmc 注册表,win10注册表编辑器没有mmc怎么办_win10恢复注册表mmc文件夹的方法-win7之家...
  17. VC++计算正反坐标方向角
  18. 山东省一个区和天津市一个区,名字一模一样!
  19. 0001-Flink安装---Flink安装(Standlone模式)
  20. 氢燃料电池发动机性能测试

热门文章

  1. 转:如何用gcc编译生成动态链接库*.so文件 动态库
  2. halcon gen_region_hline 绘制霍夫变换提取直线
  3. HALCON示例程序novelty_detection_dyn_threshold.hdev纱网缺陷检测
  4. 机器人网首页应用实例工业自动化 EtherCAT 技术在库卡机器人控制系统上的应用
  5. C++定义隐式转换函数,将类转换为内部的一个成员变量
  6. jq js json 转字符串_JS中JSON对象和String之间的互转及处理技巧
  7. mysql 文件描述符_MySQL没有发布临时文件描述符
  8. ai钢笔工具怎么描线_骨灰级的AI钢笔工具运用技巧
  9. windows系统查找文件-通配符的使用
  10. PowerDesigner的文章