问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

springboot异常处理机制?

发布网友 发布时间:2024-09-07 01:05

我来回答

1个回答

热心网友 时间:2024-09-28 06:06

springboot的四种拦截机制

当我们在某些情况下需要对客户端发送来的请求进行拦截分析的时候,就需要用到拦截机制,比如,我们需要对一个请求进行计时,又或者需要知道当前请求需要进入哪个控制器,哪一个方法,该请求的参数是什么等等场景下都需要用到拦截机制来处理。下面,我们来讲解一下SpringBoot的几种拦截方式以及如何使用它们来处理一定的场景需求。

过滤器(filter)

拦截器(interceptor)

全局异常处理器(ControllerAdvice)

切片(aspect)

如上图所示,当一个请求发送来的时候,filter在最外层,也最先拦截到请求,接下来就是interceptor,依次是ControllerAdvice(处理controller层异常)、aspect,最后才进入controller层去处理请求。相应的,当controller内部发生错误,抛出异常的时候,aspect最先接收到该异常,如果不对抛出的异常继续处理继续往外抛的话依次会抛到ControllerAdvice、interceptor、filter。

请求的顺序:从先到后经过FilterInterceptorControllerAdviceAspect–Controller。

过滤器(filter)可以拦截发送请求的状态码以及信息,拦截器(interceptor)除了可以拦截filter可以拦截的,还可以得到当前请求进入了哪一个controller,以及映射到哪一个方法,切片(aspect),它具有上面的所有功能外,还可以得到当前请求的参数的值。全局异常处理器(ControllerAdvice)只是用于处理controller层抛出的异常

Springboot的Filter,HandlerInterceptor,Aspect与异常处理

不知你在Springboot应用开发中有没有遇到过这样的情况,http请求进来却没有到达指定的controller就返回响应了,这是有可能在哪里拦截了呢。

答案是Filter,HandlerInterceptor,Aspect都有可能拦截,下面简单分析一下它们几个。

要说清它们关系得加上异常处理,在Springboot开发中默认的异常处理有三层,分别有ErrorPage,ErrorController,RestControllerAdvice,一次请求的调用链路简化图如下

①DispatcherServlet是Spring框架定义的Servlet,在Tomcat中作为默认的Servlet,是联通Tomcat和Spring的关键节点,负责分发http请求到对应的Controller中处理。

②请求建立socket链接后,先经过Tomcat的数个valve,开始进入Filter,再到HandlerInterceptor,Aspect,最后才到达Controller的,而相应的返回路径正好相反,先从Controller,最后到Filter。

③当在HandlerInterceptor和Aspect发生异常时,如果我们定义了@RestControllerAdvice和@ExceptionHandler,那么会在DispatcherServlet处理中,把异常交给我们定义的方法来处理。如果没有定义则往上抛异常。

④如果没有定义@ExceptionHandler或者Filter中发生异常时,将会在StandardHostValve中寻找匹配的ErrorPage,默认情况下,会将请求交给定义了/error路径的Controller处理,在Springboot中,默认会交给BasicErrorController处理,

因为是在StandardHostValve发起的链路,所以Filter,HandlerInterceptor,Aspect都会重新走一遍,但是有一点不同的是,这条链路只会调用类型为error的Filter,所以我们自定义的Filter不会重新调用。

⑤如果前面两道防线都失守了,或者③的异常处理链路中再次发生异常,那么将会在ErrorReportValve中处理异常,这时候处理异常比较简单粗暴,直接读取匹配的html文件,如果没有找到html文件,就会拼接一个固定样式的html报文响应回去。

SpringBoot集成SpringSecurity-异常处理(三)

源码地址:

当我们登录失败的时候,SpringSecurity帮我们跳转到了/login?errorURL,奇怪的是不管是控制台还是网页上都没有打印错误信息。

这是因为首先/login?error是SpringSecurity默认的失败URL,其次如果你不自己处理这个异常,这个异常时不会被处理的。

我们先来列举下一些SpringSecurity中常见的异常:

SpringSecurity的异常处理是在过滤器中进行的,我们在AbastrctAuthenticationProcessingFilter中找到了对Authentication的处理:

至此SpringSecurity完成了异常处理,总结下流程:

–AbstractAuthenticationProcessingFilter.doFilter()

–AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication()

–SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure()

–SimpleUrlAuthenticationFailureHandler.saveException()

上面通过源码看着挺复杂,但真正处理起来SpringSecurity为我们提供了方便的方式,我们只需要指定错误的url,然后在该方法中对异常进行处理即可。

首先我们修改CustomUserDetailsServiceloadUserByUsername()方法的返回值:

细心的同学再完成上面功能是会发现,当我们输入的用户名不存在时,不会抛出UserNameNotFoundException,而是抛出BadCredentialsException这个异常,如果有需要区分用户名不存在和密码错误的,可参考。

Springboot全局异常处理

从spring3.2开始,新增了@ControllerAdvice注解,可以用于定义@ExceptionHandler,并应用到配置了@RequestMapping的控制器中。

如果这接口是给第三方调用那是不行的,至此大致能了解到为啥需要对异常进行全局捕获了。

原理也很简单,SpringBoot默认提供了程序出错的结果映射路径/error。这个/error请求会在BasicErrorController中处理,其内部是通过判断请求头中的Accept的内容是否为text/html来区分请求是来自客户端浏览器(浏览器通常默认自动发送请求头内容Accept:text/html)还是客户端接口的调用,以此来决定返回页面视图还是JSON消息内容。

浏览器端访问的话,任何错误SpringBoot返回的都是一个WhitelabelErrorPage的错误页面,这个很不友好,所以我们可以自定义下错误页面。

这样运行的时候,请求一个不存在的页面或服务端处理发生异常时,展示的自定义错误界面。

SpringBoot提供的ErrorController是一种全局性的容错机制。此外,你还可以用@ControllerAdvice注解和@ExceptionHandler注解实现对指定异常的特殊处理。

这里介绍两种情况:

局部异常主要用到的是@ExceptionHandler注解,此注解注解到类的方法上,当此注解里定义的异常抛出时,此方法会被执行。如果@ExceptionHandler所在的类是@Controller,则此方法只作用在此类。如果@ExceptionHandler所在的类带有@ControllerAdvice注解,则此方法会作用在全局。

在spring3.2中,新增了@ControllerAdvice注解,可以用于定义@ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有@RequestMapping中。

简单的说,进入Controller层的错误才会由@ControllerAdvice处理,拦截器抛出的错误以及访问错误地址的情况@ControllerAdvice处理不了,由SpringBoot默认的异常处理机制处理。

我们实际开发中,如果是要实现RESTfulAPI,那么默认的JSON错误信息就不是我们想要的,这时候就需要统一一下JSON格式,所以需要封装一下。

此类在common的项目,要暴露出去给依赖的项目使用,在文件src\main\resources\META-INF\spring.factories中添加最后一行

可以被全局异常捕捉并处理成json

访问接口,如果无数据,则输出异常信息

{"data":"packageid为:BZ-20200107000005的indexpackage无记录","flag":false,"code":null,"msg":"未查到数据"}

全局异常类可以用@RestControllerAdvice,替代@ControllerAdvice,因为这里返回的主要是json格式,这样可以少写一个@ResponseBody。

springboot怎么取消同意的异常处理

使用ErrorController类来实现。

系统默认的错误处理类为BasicErrorController,将会显示如上的错误页面。

这里编写一个自己的错误处理类,上面默认的处理类将不会起作用。

getErrorPath()返回的路径服务器将会重定向到该路径对应的处理类,本例中为error方法。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
武汉民政职业学院地址在哪里 全国有哪些民政学院 武汉民政学院 北京哪些区较好 北京哪个区环境好 北京海淀区属于什么档次 北京市哪个区最好 北京哪个区房子最好 递延是什么意思通俗 婚后是不是一定要自己买房子才可以结婚呢? 随州华师附小改名了吗 马化腾区块链作品有哪些,马化腾创建了什么平台 如何把C盘设为系统引导盘呢? 语文让我如此美丽作文450字 乘客表情图乘客表情图 - 引PS狂潮 仿制生产假药罪的成立条件是什么 暗喻是什么意思举个例子造句 ...声音还是很好听的娃娃音,由于这个经常被男生欺负,比如她读课文... 姐姐会读课文。姐姐读得很有感情。合成一句加上一个关联关联词?_百度... 高考志愿填完多久能查到录取 高考志愿填报后多久知道录取结果? 魅力和威力的区别? 2024高考志愿填报完多久可以知道录取结果 如何查询 想象有魅力 高考志愿填完多久可以知道录取结果 2024高考报完志愿后多久出录取结果 如何查询录取状态 原告在开庭前需要准备什么材料 4200米等于多少千米 4200大写是多少? 婴儿房间能喷灭蚊剂吗 springboot如何整合springsecurity过滤器? springboot也已经学完了,突然觉得自己又不会写项目了,怎 新手机自己贴了膜吗? 华为手机自带膜要换吗 洗洁精加什么等于洗衣液 车前草泡水喝能降尿酸吗 车前草可以治痛风吗?一分钟告诉你问题真相!教你如何正确预防痛风!_百度... 唐山皮影起源于何时的滦州? 月子里可以吃车前草吗 车前草可以治前列腺炎吗 一条网线接交换机怎么连接两个电脑,只有一个能上网 ...TD 8820猫,加一台16口交换机,要两台机上网,怎么接线和设置_百度知 ... ...几个视频然后手机就卡屏不动了 然后它就自动重启是怎么回事?_百度... 一根宽带主线用交换机分成两根,一个连路由器,一根宽带连接,怎么能都... 贵阳到西安到沈阳多少公里_沈阳飞往贵阳航班的费用 沈阳到贵阳途径哪些城市_沈阳飞往贵阳航班的费用 贵阳有直达沈阳的飞机吗 贵州市离沈阳市多远,沈阳贵州自驾旅游攻略 小班生活活动筛子教案 家中的电风扇润滑油可以用什么代替?