本周在看陈杰写的自定义异常的微信异常时,使用的是自定义异常状态码和信息,在出错时将他抛出,并用@ExceptionHandler注解定义一个全局异常处理器,根据异常的内容向前台发送状态码和信息,处理异常的代码如下图:

//处理微信登录的异常

@ExceptionHandler(value = WechatLoginException.class)

public String WechatLoginExceptionHandler(HttpServletRequest request, HttpServletResponse response, WechatLoginException e){

logger.error("微信登录异常:---Host {} invokes url {} ERROR: {}", request.getRemoteHost(), request.getRequestURL(), e.getMessage());

response.setStatus(e.getCode());

return e.getMessage();

}

在这里我看的时候有点疑惑,将状态码写入响应,而信息却直接返回了,询问陈杰,前台果然没有接受到e.getMessage()的信息,我上网搜索了一下,推荐他使用response.sendError(code, message)这个方法来返回异常的信息,但是这么一试之后却遭到了奇怪的问题.

莫名的拦截器

项目配置了一个拦截器,专门用来对用户进行验证是否登录的,这个是前提.在使用response.setStatus()方法时,前台能正确的接受到传入的状态码,而使用response.sendError()时,前台却接受到的一直是401用户未登录的状态码,打了断点进行调试,分别在拦截器,跑出异常的方法,处理异常的方法打上断点,测试使用response.setStatus()和response.sendError()方法来查看执行顺序,结果让我感到惊奇:

使用response.setStatus()执行顺序:

使用response.sendError()执行顺序:

出现了令人惊奇两点:

1.setStatus()请求时没有经过拦截器

2.sendError()在异常处理完毕后经过了一次拦截器

查看注册拦截器配置,解决了第一个问题的疑惑:

public void addInterceptors(InterceptorRegistry registry) {

// 添加拦截器,去除对登录的拦截

registry.addInterceptor(authInterceptor)

.excludePathPatterns("/user/login")

.excludePathPatterns("/user/wechatLogin");

}

这个异常是用户登录时抛出的,在注册时将登录路径给忽略了,因为我们只是拦截未登录的请求,而请求登录的请求不应该拦截,这是正确的,但第二点却怎么也不明白,本应忽略拦截的请求,为什么换了sendError()方法后,却在异常处理完毕后经过了异常拦截器?

springboot的默认异常处理

对比两个方法的不同:setStatus()只是改了一下状态吗,而sendError()还有请求错误的意味,于是猜想是不是请求错误才会出现这种情况,将方法直接改为throw new RuntimeException()(没有处理异常),发现拦截器拦截的请求的url居然是一个/error的url.

这个/error的url并未在项目中定义过任何的控制器中,也从未发起这样的请求,上网一查询,原来这是Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异常内容.

但是我们的拦截器把这个请求拦截了(并且这个请求没有携带正确的cookie),所以直接就返回了401错误,response中也没有我们定义的状态码和信息了.

json还是html

一切真相大白了,但忽然想到如果是浏览器发起的请求,服务器错误后springboot默认异常处理返回的是html,但是如果像我们前后台分离的请求,返回就不应该是html而是json的错误信息了,这个要怎么区分呢?

使用google插件发送请求,返回的body是这样的:

而用浏览器发起的请求返回的却是一个html页面:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sat Apr 13 21:34:34 CST 2019
There was an unexpected error (type=Internal Server Error, status=500).
No message available

仔细查看两者发起的请求不同,在浏览器发起请求信息requestheader上发现了Accept字段:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

顿时就明白了,在发送请求时spring-boot根据Accept字段来给你返回响应的内容,例如application/json返回json,text/html返回html,真是感叹spring-boot真是太周全了.

总结

spring-boot好心帮你默认请求异常,但是却给你带来了麻烦,感觉还是自己理解的不够多,学习路还远着呢。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

java默认异常处理_spring boot 默认异常处理的实现相关推荐

  1. springboot 上传异常捕获_Spring Boot 全局异常处理(下)

    可以搜索微信公众号[Jet 与编程]查看更多精彩文章 背景 在上篇[链接]中介绍了 Spring Boot 全局异常处理的一种方式,但那是一种全局性的容错机制,目的是把 Spring Boot 默认的 ...

  2. springboot项目层次结构_Spring Boot 默认的指标数据从哪来的?

    点击上方☝SpringForAll社区 轻松关注!及时获取有趣有料的技术文章 了解有关 Spring Boot 默认指标及其来源的更多信息. 您是否注意到 Spring Boot 和 Micromet ...

  3. java+swagger+侵入_Spring boot+Swagger配置无侵入式Restful接口(一)

    最近一直遇到有人问我spring boot +swagger怎么配置无侵入式的restful接口,这段时间一直很忙,没有时间,刚好星期六,趁着休息时间给大家写个demo,在这里我就粘贴一些步骤,具体的 ...

  4. springboot设置默认值_spring boot jpa存储数据的默认值为java的默认值

    问题描述 使用jpa的save方法保存数据后返回的实体类为java数据类型的默认值 问题出现的环境背景及自己尝试过哪些方法 环境背景: 用户新增功能,调用新增接口后根据返回对象的id去查询等级表的等级 ...

  5. springboot session默认失效时间_Spring Boot 整合 Redis,用起来真简单

    来源:http://rrd.me/epDTz Redis 是目前业界使用最广泛的内存数据存储.相比 Memcached,Redis 支持更丰富的数据结构,例如 hashes, lists, sets ...

  6. 学习java第一步_Spring Boot 学习第一步(搭建初步环境)

    学习一个东西的第一步是要学会如何迅速搭建起来一个可用的环境,也就是demo.这里我选择的开发环境是Eclipse, Maven + Spring Web 项目结构在Eclipse下面的实现 我们在这里 ...

  7. java不同环境_Spring Boot系列 – 5. 不同的环境使用不同的配置

    SpringBoot系列-5.不同的环境使用不同的配置数据库 spring boot中,可以通过在application.yml配置文件中,配置多个不同的profile, 实现在不同的环境(比如开发. ...

  8. java 邮件模板_Spring Boot 2发送邮件手把手图文教程

    点击上方 IT牧场 ,选择 置顶或者星标技术干货每日送达! 本文基于:Spring Boot 2.1.3,理论支持Spring Boot 2.x所有版本. 最近有童鞋问到笔者如何用Spring Boo ...

  9. redis 设置连接数配置修改 java 最大连接数_Spring Boot集成mysql与Redis

    上一篇文章:一分钟解决临时需求,设计一个可热部署的切面 在项目搭建初期,我们便集成了mysql数据库,但是在现代的分布式架构中,往往还需要一种更高访问性能的键值数据库Redis.mysql结合redi ...

最新文章

  1. 程序员毕业两年,如何在帝都购房上车?
  2. reverseinverse
  3. java备还原mysql_用java来备份还原mysql数据库
  4. 汇编语言——十种寻址方式
  5. python关键字列表的表达式,python 列表推导和生成器表达式的使用
  6. php 栈、 出栈、入栈
  7. api数据库管理_API管理平台如何增强您的数据科学项目
  8. 为何很多理财平台扣钱很快,但是提现的时候却很慢?
  9. 鸿蒙系统下拉菜单,鸿蒙的js开发部模式17:鸿蒙的系统能力的应用模块
  10. Android之实现多张图片点击预览(支持放缩)和滑动
  11. python中如何保存文件_如何在python中处理后保存文件?
  12. [Java2入门经典]第9章 访问文件和目录
  13. java动态录音_java实现动态录音,声卡有声音进来就自动录音
  14. 五个最佳RSS新闻阅读器
  15. Python 二次开发 AutoCAD 简介
  16. 数据库课程设计——人才市场管理系统、教学管理系统、产品销售管理系统、小区物业管理系统
  17. 用python做爬虫看图软件-RandomPicture
  18. 【Tools】Coverity代码静态检测工具
  19. 怎样在线改图片大小?教你如何在线裁剪图片
  20. android手机存储空间猛增,实测安卓升级到鸿蒙,可用内存增加半个G,存储空间增加6个G...

热门文章

  1. #2009. 「SCOI2015」小凸玩密室
  2. mongodb的安装与简单操作
  3. ubuntu安装Pillow
  4. 网络带宽与实际上传下载速度之间关系
  5. 你所能用到的数据结构(六)
  6. 操作文件的实用类,删除目录,清空目录,删除文件
  7. 关于Flex2的资料
  8. docker 容器的常用命令及配置
  9. python3.6新特性
  10. 定义化标签之文本元素