SpringBoot异常处理机制
再看源码之前总结阐述下原理,Spring通过@ControllerAdvice和@ExceptionHandler两个注解来让用户可以自定义进行异常处理。实际在运行中是通过在DispatchServlet的doDispatch方法中进行异常捕捉,再通过我们的自定义异常来反射执行返回结果。
通常我们在项目中进行全局的异常处理都会使用@ControllerAdvice注解,找到ControllerAdviceBean类,
![](https://img.haomeiwen.com/i15200323/ee413d49c8a9ccc2.jpg)
可以在该类的注释上找到findAnnotatedBeans方法,可以看到该方法就是将Spring容器中被@ControllerAdvice标注的类生成ControllerAdviceBean。(由于@ControllerAdvice注解上带有@Component所以该类已经被注入进容器),
![](https://img.haomeiwen.com/i15200323/769c260e74380d0c.jpg)
我们继续寻找,可以找到ExceptionHandlerExceptionResolver类的initExceptionHandlerAdviceCache()方法调用了之前提到的findAnnotatedBeans方法。
![](https://img.haomeiwen.com/i15200323/e50104b0afebbf76.jpg)
而initExceptionHandlerAdviceCache()方法中可以看到它将ControllerAdviceBean和ExceptionHandlerMethodResolver存到了exceptionHandlerAdviceCache缓存中。ExceptionHandlerMethodResolver是新创建的,在其构造函数中可以找到detectExceptionMappings()方法将该类所有的@ExceptionHandler标注的方法放入该类缓存(若没有@ExceptionHandler标注的方法会扫描该类参数是异常的方法)。
![](https://img.haomeiwen.com/i15200323/6582e8462840333c.jpg)
之前可以看到initExceptionHandlerAdviceCache()方法会扫描所有的@ControllerAdvice标注的类,该方法是ExceptionHandlerExceptionResolver的afterPropertiesSet()调用的,也就是说该类在被初始化的时候就会init。而ExceptionHandlerExceptionResolver类是由WebMvcConfigurationSupport类注入进的。
之前主要讲了被@ControllerAdvice标注的注解如何添加到缓存中,之后来看看是如何生效的。看到DispatcherServer的doDispatch()(SpringMvc的请求转发处理类)里的processDispatchResult()(当捕获到异常会将异常传入该方法)
![](https://img.haomeiwen.com/i15200323/c946492abeee7ebd.jpg)
之后其实就是调用到ServletInvocableHandlerMethod.invokeAndHandle()。
在调用之前我们可以看到doResolveHandlerMethodException.getExceptionHandlerMethod();
![](https://img.haomeiwen.com/i15200323/f0d04636f1fa1d3f.jpg)
该方法通过getMappedMethod()从之前讲到的mappedMethods缓存中取到处理方法。
![](https://img.haomeiwen.com/i15200323/6e43ca221b4e2f7c.jpg)
![](https://img.haomeiwen.com/i15200323/1cc3535796fbde4c.jpg)
之后进行封装返回处理类。最后通过处理类(ServletInvocableHandlerMethod)的invokeAndHandle来反射调用实际的异常处理方法。
我们在项目中的日志处理一般使用的都是Spring自带的日志机制,通过前端传输TransactionId来确定某一调用链路的全程日志。
前后端分离日志处理
我结合我们当前项目来分析下日志处理机制。我们是通过SpringCloud Sleuth来进行日志收集的,将增量日志通过kafka记录到es上。之后我们可以通过ocean平台(类似kibana,实际是对kibana的封装,内部使用)来查找问题(traceId查找怎个调用链路的日志,由于是整合平台,这边的traceId是由后台生成的而不是前端传递)。使用切面来拦截所有controller和client端调用的日志,记录入参出参等信息。
![](https://img.haomeiwen.com/i15200323/9041aa673c014086.jpg)
![](https://img.haomeiwen.com/i15200323/b83a1a1586c4f437.jpg)
![](https://img.haomeiwen.com/i15200323/27a035cc5c2080a6.jpg)
跨域的含义: 浏览器的同源策略,是由浏览器提供的安全保证。前端可通过jsonp来进行跨域访问。而后端可以设置“Access-Control-Allow-Origin”来进行跨域允许。
activiti工作流的工作原理没有看过。
网友评论