SpringBoot中自带的异常捕获机制返回的默认页面比较丑,对用户来说不够人性化。所以这篇文章来讲解SpringBoot钟自定义全局异常捕获。
本文的源码已经上传GitHub:https://github.com/haozz1994/exceptiondemo
主要讲解三种异常捕获形式:

  • 页面跳转异常
  • ajax异常
  • 统一返回异常的形式

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

1.页面跳转异常

首先新建一个异常:

package com.haozz.exceptiondemo.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;/*** @author haozz* @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.haozz.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 haozz* @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:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head><meta charset="UTF-8"><title>程序员迷路了</title>
</head>
<body><h1 style="color:red">程序员迷路了:</h1><div th:text="${url}"></div><div th:text="${exception.message}"></div>
</body>
</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.haozz.thymeleafdemo.utils;import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;import javax.servlet.http.HttpServletRequest;/*** @author haozz* @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调试可以更清楚的看到程序的执行过程。

SpringBoot配置全局异常捕获相关推荐

  1. SpringBoot(6) SpringBoot配置全局异常

    SpringBoot(6) SpringBoot配置全局异常 参考文章: (1)SpringBoot(6) SpringBoot配置全局异常 (2)https://www.cnblogs.com/pl ...

  2. Spring Boot配置全局异常捕获

    1 SpringBoot配置全局的异常捕获 项目的说明 配置thymeleaf作为视图模板 ExceptionController.java模拟测试用 MyAjaxExceptionHandler.j ...

  3. springBoot配置全局异常处理器

    一.自定义自己的异常类MyException.java public class MyException extends RuntimeException {private int code;publ ...

  4. java报错空指针异常_springboot全局异常捕获,真香

    全局异常捕获 什么是异常?程序在启动或者运行时没有按照预期的执行,在执行途中发生某种未知的错误,导致程序非正常停止或者报错. 在我们的程序中,肯定会伴随着很多的异常,启动时:空对象.找不到数据库.用户 ...

  5. Java 捕获 mybatis异常_3 springboot集成mybatis和全局异常捕获

    mybatis有两种方式,一种是基于XML,一种是基于注解 springboot集成mybatis 首先先创建表,这里都简化了 DROP TABLE IF EXISTS `user`; CREATE ...

  6. springboot上传文件过大,全局异常捕获,客户端没有返回值

    springboot上传文件过大,全局异常捕获,客户端没有返回值 参考文章: (1)springboot上传文件过大,全局异常捕获,客户端没有返回值 (2)https://www.cnblogs.co ...

  7. SpringBoot框架搭建(redis多数据源+数据库多数据源+全局异常捕获)

    java骨架 目录结构 ├── mvnw ├── mvnw.cmd ├── pom.xml ├── README.md ├── src/ 源文件目录 │ ├── main │ │ ├── java │ ...

  8. SpringBoot 自定义全局异常处理器

    SpringBoot自定义全局异常处理器 一.maven依赖 二.GlobalExceptionHandler.java 三.ResponseStandard.java 四.logback.xml 五 ...

  9. spring boot: GlobalDefaultExceptionHandler方法内的友好错误提示,全局异常捕获

    spring boot: GlobalDefaultExceptionHandler方法内的友好错误提示,全局异常捕获 当你的某个控制器内的某个方法报错,基本上回显示出java错误代码,非常不友好,这 ...

最新文章

  1. 宏基因组分析技术研讨会-2019年最后一期
  2. 微信搜索谁把你删除了
  3. 【千字分析】剑指 Offer 47. 礼物的最大价值
  4. 这名程序员28岁就退休了。。。
  5. Linux内核分析 02
  6. linux监控命令执行,你可能不知道的 即时监控 Linux 使用者执行指令的三种方法...
  7. 本地项目怎么推送到码云_如何将本地项目放到码云(gitee)上
  8. 解析xml文件的几种技术
  9. Python 进阶 —— 使用 map reduce
  10. 初中计算机考试知识,初中信息技术学业考试《基础知识复习提纲》
  11. Linux学习总结(1)——Linux命令大全完整版
  12. 推荐比较好的广告联盟之BloggerAds-部落格行销,来自台湾的CPM博客赚钱联盟
  13. 基于CNN的动态手势识别:Real-time Hand Gesture Detection and Classification Using Convolutional Neural Networks
  14. 唐山大地震:接近尸体
  15. MATLAB实现在不同Es/N0情况下,QPSK、16QAM、64QAM误码率结果仿真图(包含软硬判决)
  16. VIM如何将全部内容复制并粘贴到外部
  17. OCTA数据集的交叉验证划分为训练集和测试机
  18. 以一举三的京东数据爬取(已经分配好各个方法,修改几行代码即可应用其他网站)并以json文件保存
  19. 企业微信应用程序开发WeChatAPI
  20. Java培训后找工作可以拿到多少钱?

热门文章

  1. bit、Byte、bps、Bps、pps、Gbps的详细说明及换算
  2. 若依(ruoyi)框架关闭当前标签页
  3. (一)权限管理系统介绍
  4. 新媒体工作者必备常识
  5. babel5升级到babel6总结
  6. java验证11位手机号_JAVA怎样用数组实现输入手机号码为11位
  7. 《古月ROS探索总结》学习笔记1
  8. 基于Java的长整数加减法算法设计
  9. 流放之路进去后显示无法连接登入服务器,流放之路此账号目前无法登录游戏
  10. java之父那一年出生_黄小戈哪一年出生 起底其详细资料背景曝真实年龄多少