《SpringBoot从菜鸟到老鸟》之SpringBoot 如何配置全局的异常捕获
SpringBoot 如何配置全局的异常捕获
SpringBoot中自带的异常捕获机制返回的默认页面比较丑,对用户来说不够人性化。
所以这篇文章来讲解SpringBoot钟自定义全局异常捕获。
主要讲解三种异常捕获形式:
页面跳转异常
ajax异常
统一返回异常的形式
分别来看三种形式的全局异常捕获:
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 如何配置全局的异常捕获相关推荐
- SpringBoot配置全局的异常捕获
需要以下两个类配合完成: IoExceptionHandler.java(异常助手类) IMoocJSONResult.java(实体类) package com.blog.pojo;import o ...
- springboot怎么返回404_深度分析:SpringBoot异常捕获与封装处理,看完你学会了吗?...
简介 日常开发过程中,难免有的程序会因为某些原因抛出异常,而这些异常一般都是利用try ,catch的方式处理异常或者throw,throws的方式抛出异常不管.这种方法对于程序员来说处理也比较麻烦, ...
- springboot redis 刷新时间_「SpringBoot实战」SpringCache + Redis实现数据缓存
关注我的微信公众号:后端技术漫谈 不定期推送关于后端开发.爬虫.算法题.数据结构方面的原创技术文章,以及生活中的逸闻趣事. 我目前是一名后端开发工程师.主要关注后端开发,数据安全,网络爬虫,物联网,边 ...
- springboot 自动装配_Java互联网架构-SpringBoot自动装配核心源码剖析
欢迎关注头条号:java小马哥 周一至周日早九点半!下午三点半!精品技术文章准时送上!!! 精品学习资料获取通道,参见文末 用了差不多两年的SpringBoot了,可以说对SpringBoot已经很熟 ...
- SpringBoot系列三:SpringBoot基本概念(统一父 pom 管理、SpringBoot 代码测试、启动注解分析、配置访问路径、使用内置对象、项目打包发布)...
声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.了解SpringBoot的基本概念 2.具体内容 在之前所建立的 SpringBoot 项目只是根据官方文档实现的一个基础程 ...
- springboot学习笔记:12.解决springboot打成可执行jar在linux上启动慢的问题
springboot学习笔记:12.解决springboot打成可执行jar在linux上启动慢的问题 参考文章: (1)springboot学习笔记:12.解决springboot打成可执行jar在 ...
- springboot获取resources路径_Docker构建SpringBoot应用
1.基于Dockerfile构建SpringBoot镜像 1.1准备工作 将SpringBoot项目通过maven打成jar包: mvn clean package 1.2使用Dockerfile构建 ...
- onresize事件会被多次触发_玩转SpringBoot之通过事件机制参与SpringBoot应用的启动过程...
生命周期和事件监听 一个应用的启动过程和关闭过程是归属到"生命周期"这个概念的范畴. 典型的设计是在启动和关闭过程中会触发一系列的"事件",我们只要监听这些事件 ...
- SpringBoot | 第一章:第一个SpringBoot应用
2019独角兽企业重金招聘Python工程师标准>>> SpringBoot | 第一章:第一个SpringBoot应用 springboot简单介绍 概述 随着动态语言的流行(Ru ...
最新文章
- 浅析2007年商业智能领域上演的收购大戏
- Spring整合Hibernate
- MappedByteBuffer VS FileChannel 孰强孰弱?
- 洛谷P4742(tarjan缩点+拓扑DP)
- SAP Cloud for Customer前台发送到后台的HTTP请求,遇到错误该怎么分析
- python的特性是_python的特性
- QuickMan 手记 - Activiti 环境搭建
- Unity Failed executing external process for 'Bake Runtime' job
- NVIDIA SMI 无法与 nvidia driver 通信
- CATransition 动画处理视图切换
- javascript之querySelector和querySelectorAll
- (转)一个百倍股的坠落:那个曾经满大街的ESPRIT是如何衰败的
- radius源码下载
- win10 linux 无法下载,更新win10后不能安装ubuntu的解决方法
- 太极root权限_太极框架免root版下载
- 计算机 管理 mmc 注册表,win10注册表编辑器没有mmc怎么办_win10恢复注册表mmc文件夹的方法-win7之家...
- VC++计算正反坐标方向角
- 山东省一个区和天津市一个区,名字一模一样!
- 0001-Flink安装---Flink安装(Standlone模式)
- 氢燃料电池发动机性能测试
热门文章
- 转:如何用gcc编译生成动态链接库*.so文件 动态库
- halcon gen_region_hline 绘制霍夫变换提取直线
- HALCON示例程序novelty_detection_dyn_threshold.hdev纱网缺陷检测
- 机器人网首页应用实例工业自动化 EtherCAT 技术在库卡机器人控制系统上的应用
- C++定义隐式转换函数,将类转换为内部的一个成员变量
- jq js json 转字符串_JS中JSON对象和String之间的互转及处理技巧
- mysql 文件描述符_MySQL没有发布临时文件描述符
- ai钢笔工具怎么描线_骨灰级的AI钢笔工具运用技巧
- windows系统查找文件-通配符的使用
- PowerDesigner的文章