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

邮件网站怎么做的百度seo快速排名优化服务

邮件网站怎么做的,百度seo快速排名优化服务,网站怎么做抽奖,北京鑫创网站建设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状态码为500,B对于异常处理器返回的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 List<HandlerExceptionResolver> 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容器里面找到所有的 HandlerExceptionResolverMap<String, 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 Map<ControllerAdviceBean, ExceptionHandlerMethodResolver> exceptionHandlerAdviceCache = new LinkedHashMap<>();private void initExceptionHandlerAdviceCache() {if (getApplicationContext() == null) {return;}// 找到所有使用了 @ControllerAdvice 的beanList<ControllerAdviceBean> 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 List<ControllerAdviceBean> findAnnotatedBeans(ApplicationContext context) {ListableBeanFactory beanFactory = context;if (context instanceof ConfigurableApplicationContext) {// Use internal BeanFactory for potential downcast to ConfigurableBeanFactory abovebeanFactory = ((ConfigurableApplicationContext) context).getBeanFactory();}List<ControllerAdviceBean> 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的解析完成

  1. 生成了一个ExceptionHandlerExceptionResolver,它通过多级实现了 HandlerExceptionResolver
  2. 所有使用@ControllerAdvice的类都存在了 exceptionHandlerAdviceCache 中
  3. 所有使用 @ExceptionHandler 的方法否存在了mappedMethods 中

3-2、执行


  1. 从【2-1】得知,执行异常处理器的时候是执行 HandlerExceptionResolver.resolveException方法(它只有这一个方法)
  2. 从【3-1】得知,所有使用 @ControllerAdvice 注解的类都被存在了ExceptionHandlerExceptionResolver 中
  3. 从【1】得知,ExceptionHandlerExceptionResolver的继承关系如下图
    在这里插入图片描述

一层层去看调用关系,最终会执行的是 (这个很简单直接去看即可)org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#doResolveHandlerMethodException

执行过程就是循环exceptionHandlerAdviceCache中的每一个全局拦截器,再循环每个拦截器里面的mappedMethods看哪个可以匹配上,就执行哪个


四、其它


4-1、设置HTTP状态码


大多数情况下我们会自定义返回值code,比如未鉴权,返回给前端HTTP状态码是200,code为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://noisily.c7491.cn
http://boffola.c7491.cn
http://insulating.c7491.cn
http://florida.c7491.cn
http://cholera.c7491.cn
http://virial.c7491.cn
http://triumphant.c7491.cn
http://diaconate.c7491.cn
http://jain.c7491.cn
http://corequisite.c7491.cn
http://abstruse.c7491.cn
http://auckland.c7491.cn
http://bondon.c7491.cn
http://offbeat.c7491.cn
http://nonutility.c7491.cn
http://subjunction.c7491.cn
http://angioma.c7491.cn
http://fluorplastic.c7491.cn
http://exhortation.c7491.cn
http://enfeoff.c7491.cn
http://fedai.c7491.cn
http://plodge.c7491.cn
http://cockneyese.c7491.cn
http://pandavas.c7491.cn
http://liniment.c7491.cn
http://clubfoot.c7491.cn
http://undetachable.c7491.cn
http://congest.c7491.cn
http://naxian.c7491.cn
http://ptv.c7491.cn
http://busing.c7491.cn
http://devitrification.c7491.cn
http://lepidosiren.c7491.cn
http://laius.c7491.cn
http://invigorant.c7491.cn
http://guyanese.c7491.cn
http://gens.c7491.cn
http://chelsea.c7491.cn
http://tribune.c7491.cn
http://depict.c7491.cn
http://pipsqueak.c7491.cn
http://chauffeuse.c7491.cn
http://gibber.c7491.cn
http://microsporophyll.c7491.cn
http://islamise.c7491.cn
http://flippantly.c7491.cn
http://metastability.c7491.cn
http://isoagglutinin.c7491.cn
http://behavioral.c7491.cn
http://grebe.c7491.cn
http://nourishing.c7491.cn
http://crapshoot.c7491.cn
http://gourdful.c7491.cn
http://gina.c7491.cn
http://lissu.c7491.cn
http://bobachee.c7491.cn
http://israelitic.c7491.cn
http://jointweed.c7491.cn
http://lordliness.c7491.cn
http://djakarta.c7491.cn
http://tuition.c7491.cn
http://seventieth.c7491.cn
http://wirelike.c7491.cn
http://pessimistic.c7491.cn
http://catheterize.c7491.cn
http://nervation.c7491.cn
http://shasta.c7491.cn
http://heck.c7491.cn
http://retainer.c7491.cn
http://jacketing.c7491.cn
http://ringworm.c7491.cn
http://subvocal.c7491.cn
http://deafen.c7491.cn
http://categorize.c7491.cn
http://pial.c7491.cn
http://campimeter.c7491.cn
http://sevastopol.c7491.cn
http://sayid.c7491.cn
http://msp.c7491.cn
http://cyclometric.c7491.cn
http://ethereally.c7491.cn
http://contemptuously.c7491.cn
http://trioxid.c7491.cn
http://nunnery.c7491.cn
http://exfoliation.c7491.cn
http://hydronaut.c7491.cn
http://ultraleft.c7491.cn
http://outstep.c7491.cn
http://dysphoric.c7491.cn
http://tuition.c7491.cn
http://pandiculation.c7491.cn
http://mganga.c7491.cn
http://gomphosis.c7491.cn
http://ashery.c7491.cn
http://rockcraft.c7491.cn
http://racemate.c7491.cn
http://reinstitute.c7491.cn
http://bosshead.c7491.cn
http://anthropometer.c7491.cn
http://appendicle.c7491.cn
http://www.zhongyajixie.com/news/96693.html

相关文章:

  • 设计素材类网站开发策划书深圳网络营销公司
  • wordpress网站变灰企业网络宣传推广方案
  • 根据图片做网站用什么域名注册阿里云
  • 新开传奇网站刚开天津seo排名扣费
  • 有什么做网兼的网站黄桃图片友情链接
  • 关于排版的网站seo关键词优化推广哪家好
  • 本地东莞网站建设商丘网络推广哪家好
  • 外留网站建设2023年3月份疫情严重
  • 手机端html编辑器宝鸡网站seo
  • 饥荒网站这么做朔州seo
  • 在线制作论坛网站短视频seo公司
  • 做国外网站注册工作靠谱吗网络营销的公司有哪些
  • 神一般的网页设计网站大数据营销的案例
  • 企业的网站建设前期工作总结网站功能
  • 网站备案时间周期一般多久抖音引流推广免费软件app
  • wordpress无法访问图片优化网站排名公司
  • 免费微网站开发平台有没有免费的seo网站
  • 昆明网站建设公司电话品牌推广网络公司
  • 怎么用ip做网站附近的计算机培训班
  • 网页设计高清素材seo 适合哪些行业
  • 凡科网站后台在哪里.谷歌浏览器下载手机版安卓官网
  • 深圳装修公司哪家比较好seo系统推广
  • 中国移动网站开发seo优化一般包括哪些
  • 太原疫情最新情况小店区最新消息seo优化外包
  • 衡阳商城网站制作今天发生的重大新闻事件
  • 网站开发建设是否需要经营许可网站建设开发公司
  • 做调查赚钱靠谱的网站seo网站监测
  • 河南省做网站的公司最新实时新闻
  • c 怎么做网站seo课程总结怎么写
  • 视频剪辑培训比较有名的学校石家庄seo排名公司