当前位置: 首页 > news >正文

淘客优惠券网站建设如何快速建设自适应网站

淘客优惠券网站建设,如何快速建设自适应网站,工作计划表,cms系统推荐https://www.bilibili.com/video/BV1sS411c7Mo 文章目录 一、全局异常处理器的类型1-1、实现方式一1-2、实现方式二 二、全局异常拦截点2-1、入口2-2、全局异常拦截器是如何注入到 DispatcherServlet 的 三、ControllerAdvice 如何解析、执行3-1、解析3-2、执行 四、其它4-1、设…https://www.bilibili.com/video/BV1sS411c7Mo 文章目录 一、全局异常处理器的类型1-1、实现方式一1-2、实现方式二 二、全局异常拦截点2-1、入口2-2、全局异常拦截器是如何注入到 DispatcherServlet 的 三、ControllerAdvice 如何解析、执行3-1、解析3-2、执行 四、其它4-1、设置HTTP状态码4-2、异常处理器排序4-3、所谓全局异常 最近在做系统升级的时候引发了一个BUG原本系统是有一个异常处理器A引入了某个底包中也带了一个异常处理器B最终走了底包的异常处理器B。 A对于异常的时候会返回HTTP状态码为500B对于异常处理器返回的HTTP状态码为200前端基于HTTP状态码进行提示的就出了问题 本篇文章我们就来讨论一下在JavaWeb中的全局异常处理器是何时何地如何执行的。 在进行学习之前需要先知道HTTP执行流程SpringMVC执行流程 一、全局异常处理器的类型 全局异常处理器的父接口是 HandlerExceptionResolver简单来说就是实现或间接实现它的类就叫全局异常处理器。 package org.springframework.web.servlet;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.lang.Nullable;public interface HandlerExceptionResolver {NullableModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Nullable Object handler, Exception ex); }HandlerExceptionResolver 的继承关系图 1-1、实现方式一 SpringBoot项目最大的特点就是注解在SpringBoot项目中全局异常拦截的注解是ControllerAdvice RestControllerAdvice ControllerAdvice ResponseBody 使用 ControllerAdvice的类最终会生成 ExceptionHandlerExceptionResolver 1-2、实现方式二 重写 doResolveHandlerMethodException 方法然后注册当前的bean public class ExceptionHandler extends AbstractHandlerMethodExceptionResolver {private final static Logger logger LoggerFactory.getLogger(ExceptionHandler.class);Overrideprotected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, Exception ex) {return new ModelAndView();} }二、全局异常拦截点 2-1、入口 org.springframework.web.servlet.DispatcherServlet#doDispatch 这个方法就是SpringMVC的执行流程的核心代码了下面是简化代码 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest request;HandlerExecutionChain mappedHandler null;boolean multipartRequestParsed false;WebAsyncManager asyncManager WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv null;Exception dispatchException null;try {// ...mv ha.handle(processedRequest, response, mappedHandler.getHandler());// ....}catch (Exception ex) {dispatchException ex;}catch (Throwable err) {dispatchException new NestedServletException(Handler dispatch failed, err);}// 异常处理的入口processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {// ....}catch (Throwable err) {// ....}finally {// ... } }org.springframework.web.servlet.DispatcherServlet#processDispatchResult private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,Nullable HandlerExecutionChain mappedHandler, Nullable ModelAndView mv,Nullable Exception exception) throws Exception {boolean errorView false;if (exception ! null) {Object handler (mappedHandler ! null ? mappedHandler.getHandler() : null);// 异常处理mv processHandlerException(request, response, handler, exception);errorView (mv ! null);}// ... }org.springframework.web.servlet.DispatcherServlet#processHandlerException protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,Nullable Object handler, Exception ex) throws Exception {// Success and error responses may use different content typesrequest.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);// Check registered HandlerExceptionResolvers...ModelAndView exMv null;if (this.handlerExceptionResolvers ! null) {// 遍历循环所有的拦截器来尝试处理这个异常拦截器已经按照 order 排好序了for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {exMv resolver.resolveException(request, response, handler, ex);// 只有返回了 ModelAndView 才结束不然一直往下走if (exMv ! null) {break;}}}// ...// 如果没有全局异常处理器 可以处理这个异常 就继续抛出去throw ex; }2-2、全局异常拦截器是如何注入到 DispatcherServlet 的 上面看到是从 handlerExceptionResolvers 从获取所有的异常处理器它是一个list Nullable private ListHandlerExceptionResolver handlerExceptionResolvers;在DispatcherServlet里面有一个onRefresh方法它是重写的父类FrameworkServlet的在初始化ServletBean的时候会被调用一次它里面会做很多初始化的操作其中一个就是获取容器里面的全局异常拦截器 一层层看上去其实是 Servlet接口的 init方法触发的 Override protected void onRefresh(ApplicationContext context) {initStrategies(context); }protected void initStrategies(ApplicationContext context) {// ...initHandlerExceptionResolvers(context);// ... }找到bean容器里面的所有异常拦截器把它存在 handlerExceptionResolvers 里面并排序 private void initHandlerExceptionResolvers(ApplicationContext context) {this.handlerExceptionResolvers null;if (this.detectAllHandlerExceptionResolvers) {// 从bean容器里面找到所有的 HandlerExceptionResolverMapString, HandlerExceptionResolver matchingBeans BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerExceptionResolvers new ArrayList(matchingBeans.values());// 排序AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);}}// ... }三、ControllerAdvice 如何解析、执行 3-1、解析 在springframework 中有这样一个类 ExceptionHandlerExceptionResolver package org.springframework.web.servlet.mvc.method.annotation;public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolverimplements ApplicationContextAware, InitializingBean {// ... }⚠️可以回到【全局异常处理器的类型】的图看看ExceptionHandlerExceptionResolver其实就是全局异常处理器HandlerExceptionResolver的子类 它实现了 InitializingBean重写了afterPropertiesSet这个方法会在bean初始化完之后执行 Override public void afterPropertiesSet() {// Do this first, it may add ResponseBodyAdvice beansinitExceptionHandlerAdviceCache();// ... }initExceptionHandlerAdviceCache 会把所有使用了ControllerAdvice 的bean找到并把它存在自己的参数里面 private final MapControllerAdviceBean, ExceptionHandlerMethodResolver exceptionHandlerAdviceCache new LinkedHashMap();private void initExceptionHandlerAdviceCache() {if (getApplicationContext() null) {return;}// 找到所有使用了 ControllerAdvice 的beanListControllerAdviceBean adviceBeans ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());for (ControllerAdviceBean adviceBean : adviceBeans) {Class? beanType adviceBean.getBeanType();if (beanType null) {throw new IllegalStateException(Unresolvable type for ControllerAdviceBean: adviceBean);}// 解析全部的 ExceptionHandler 注解ExceptionHandlerMethodResolver resolver new ExceptionHandlerMethodResolver(beanType);if (resolver.hasExceptionMappings()) {// 存入当前的类参数里面this.exceptionHandlerAdviceCache.put(adviceBean, resolver);}if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {this.responseBodyAdvice.add(adviceBean);}}// ... }org.springframework.web.method.ControllerAdviceBean#findAnnotatedBeans public static ListControllerAdviceBean findAnnotatedBeans(ApplicationContext context) {ListableBeanFactory beanFactory context;if (context instanceof ConfigurableApplicationContext) {// Use internal BeanFactory for potential downcast to ConfigurableBeanFactory abovebeanFactory ((ConfigurableApplicationContext) context).getBeanFactory();}ListControllerAdviceBean adviceBeans new ArrayList();// 遍历所有的beanfor (String name : BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Object.class)) {if (!ScopedProxyUtils.isScopedTarget(name)) {// 找到符合的beanControllerAdvice controllerAdvice beanFactory.findAnnotationOnBean(name, ControllerAdvice.class);if (controllerAdvice ! null) {// 存起来adviceBeans.add(new ControllerAdviceBean(name, beanFactory, controllerAdvice));}}}// 排序OrderComparator.sort(adviceBeans);return adviceBeans; }配合ControllerAdvice 注解的通常是 ExceptionHandler 它用来制定具体的异常把所有的 ExceptionHandler都存入了 mappedMethods 中org.springframework.web.method.annotation.ExceptionHandlerMethodResolver#ExceptionHandlerMethodResolver public ExceptionHandlerMethodResolver(Class? handlerType) {for (Method method : MethodIntrospector.selectMethods(handlerType, EXCEPTION_HANDLER_METHODS)) {for (Class? extends Throwable exceptionType : detectExceptionMappings(method)) {addExceptionMapping(exceptionType, method);}} } private void addExceptionMapping(Class? extends Throwable exceptionType, Method method) {Method oldMethod this.mappedMethods.put(exceptionType, method);if (oldMethod ! null !oldMethod.equals(method)) {throw new IllegalStateException(Ambiguous ExceptionHandler method mapped for [ exceptionType ]: { oldMethod , method });} }至此ControllerAdvice的解析完成 生成了一个ExceptionHandlerExceptionResolver它通过多级实现了 HandlerExceptionResolver所有使用ControllerAdvice的类都存在了 exceptionHandlerAdviceCache 中所有使用 ExceptionHandler 的方法否存在了mappedMethods 中 3-2、执行 从【2-1】得知执行异常处理器的时候是执行 HandlerExceptionResolver.resolveException方法它只有这一个方法从【3-1】得知所有使用 ControllerAdvice 注解的类都被存在了ExceptionHandlerExceptionResolver 中从【1】得知ExceptionHandlerExceptionResolver的继承关系如下图 一层层去看调用关系最终会执行的是 这个很简单直接去看即可org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#doResolveHandlerMethodException 执行过程就是循环exceptionHandlerAdviceCache中的每一个全局拦截器再循环每个拦截器里面的mappedMethods看哪个可以匹配上就执行哪个 四、其它 4-1、设置HTTP状态码 大多数情况下我们会自定义返回值code比如未鉴权返回给前端HTTP状态码是200code为401但在某些情况下也会直接返回HTTP状态码401可以使用 ResponseStatus ResponseStatus(HttpStatus.UNAUTHORIZED) ExceptionHandler(Exception.class) public ResultObj bizExceptionHandler(Exception e) {log.info(全局异常拦截, e);return ResultObj.success(); }4-2、异常处理器排序 springframework 里面提供了一个Ordered 接口实现它重写里面 getOrder 方法就可以进行排序了 4-3、所谓全局异常 并不是系统任何异常都会被它所拦截因为我们已经知道它的执行点是在MVC的流程中所以就只有HTTP异常才会被拦截处理
http://www.w-s-a.com/news/563347/

相关文章:

  • 四川省建设厅官网信息查询平台北京seo关键词优化外包
  • 网站建设响应式是什么意思wordpress弹窗打开网页
  • 做美工需要参考的网站漳州做网站的公司
  • 用源码建设网站关于网站开发的自我评价
  • 网站设计师图片自助建站编辑器
  • 网站建设的常用技术有哪些深圳建筑工地招工
  • 做软装找图片的网站wordpress 替代
  • 制作网站的后台公众号做视频网站会封吗
  • 广西企业建站邯郸景区网站制作
  • 开发商城网站多少钱城厢区建设局网站
  • 网站外链多的危害天水市建设局网站
  • 网站接入商学交互设计网站
  • 目前最新的网站后台架构技术综述什么网站可以做名片
  • 成都建站长沙做网站美工的公司
  • 湖南省住房与城乡建设厅网站平顶山网站关键词优化
  • 购物网站前台功能模块汕头网站设计电话
  • 网站你懂我意思正能量免费wordpress菜单底部导航代码
  • 一个主机可以建设多少个网站山东高端网站建设
  • 长沙网站建设搭建网络营销做得好的公司
  • 如何做网站的后台管理石家庄seo关键词排名
  • 给自己公司做个网站山东做外贸网站的公司
  • 张家港网站建设培训江苏省建设工程网站系统
  • html个人网站桂林建站
  • 湛江网站优化快速排名wordpress文章页面宽度
  • 自己建网站怎么弄唯品会一家专门做特卖的网站
  • 做文化传播公司网站做搜狗pc网站点
  • 免费的黄冈网站有哪些平台可以聊天呢要查询一个网站在什么公司做的推广怎么查
  • 凡客建站登录入口网站建设先进部门评选标准
  • 响应式设计 手机网站政务中心建设网站
  • 如何做卖衣服的网站网站登录接口怎么做