spring boot 默认异常处理的实现

 更新时间:2019年04月14日 16:15:19   作者:鲸冬香  
这篇文章主要介绍了spring boot 默认异常处理的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

本周在看陈杰写的自定义异常的微信异常时,使用的是自定义异常状态码和信息,在出错时将他抛出,并用@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页面:

<html>
<body>
<h1>Whitelabel Error Page</h1>
<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>
<div id='created'>Sat Apr 13 21:34:34 CST 2019</div>
<div>There was an unexpected error (type=Internal Server Error, status=500).</div>
<div>No message available</div>
</body>
</html>

仔细查看两者发起的请求不同,在浏览器发起请求信息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好心帮你默认请求异常,但是却给你带来了麻烦,感觉还是自己理解的不够多,学习路还远着呢。

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

相关文章

  • Struts2学习手册之文件上传基础教程

    Struts2学习手册之文件上传基础教程

    Struts2提供的文件上传下载机制十分简便,使得我们写很少的代码,下面这篇文章主要给大家介绍了关于Struts2学习手册之文件上传的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-05-05
  • 如何使用jakarta.json进行json序列化和反序列化

    如何使用jakarta.json进行json序列化和反序列化

    java里,json框架何其多,常见的有jackson、fastjson、gson等,本文重点介绍如何使用jakarta.json进行json序列化和反序列化,需要的朋友可以参考下,
    2024-07-07
  • springboot打印接口调用日志的实例

    springboot打印接口调用日志的实例

    这篇文章主要介绍了springboot打印接口调用日志的实例,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • Java利用递归算法实现查询斐波那契数

    Java利用递归算法实现查询斐波那契数

    今天小编就为大家分享一篇关于Java利用递归算法实现查询斐波那契数,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • SpringBoot给类进行赋初值的四种方式

    SpringBoot给类进行赋初值的四种方式

    这篇文章主要介绍了springboot给类进行赋初值的四种方式,并通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-08-08
  • J2EE基础之EJB全面了解

    J2EE基础之EJB全面了解

    下面小编就为大家带来一篇J2EE基础之EJB全面了解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-07-07
  • Spring Native项目实战(体验79毫秒启动springboot应用)

    Spring Native项目实战(体验79毫秒启动springboot应用)

    Spring Native是Spring提供的、制作native image的技术方案,本篇主要内容是开发springboot应用再构建为native image的方法,通过Spring Native项目实战让大家体验79毫秒启动springboot应用,感兴趣的朋友跟随小编一起看看吧
    2021-05-05
  • Lombok注解-@SneakyThrows的使用

    Lombok注解-@SneakyThrows的使用

    这篇文章主要介绍了Lombok注解-@SneakyThrows的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 最简单的在IntelliJ IDEA导入一个本地项目教程(图文)

    最简单的在IntelliJ IDEA导入一个本地项目教程(图文)

    这篇文章主要介绍了最简单的在IntelliJ IDEA导入一个本地项目教程(图文),文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Knife4j的请求示例当中有很多空白行的问题解决办法

    Knife4j的请求示例当中有很多空白行的问题解决办法

    这篇文章主要介绍了Knife4j的请求示例当中有很多空白行的问题解决办法,按正常来说不应该有上方的空白,当然如果只是查看我也不至于非要解决他,主要是假如接口是json传参,调试界面都没办法修改参数,遇到同样问题的同学可以参考阅读本文
    2024-09-09

最新评论