netty springmvc_springmvc源码架构解析之@ExceptionHandler

说在前面

前期回顾

sharding-jdbc源码解析 更新完毕

spring源码解析 更新完毕

spring-mvc源码解析 更新完毕

spring-tx源码解析 更新完毕

spring-boot源码解析 更新完毕

rocketmq源码解析 更新完毕

dubbbo源码解析 更新完毕

netty源码解析 更新完毕

spring源码架构更新完毕

springmvc源码架构更新中

springboot源码架构计划中

github https://github.com/tianheframe

sharding-jdbc源码解析 更新完毕

rocketmq源码解析 更新完毕

seata 源码解析 更新完毕

dubbo 源码解析 更新完毕

netty 源码解析 更新完毕

源码解析

org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver org.springframe .web.servlet的实现。HandlerExceptionResolver接口,它通过ExceptionHandler注释处理异常。此异常解析器在org.springframework.web.servlet.DispatcherServlet中默认启用。

private final Map, Map, Method>> exceptionHandlerCache =      new ConcurrentHashMap, Map, Method>>(64);

exceptionHandlerCache

  private WebArgumentResolver[] customArgumentResolvers;

customArgumentResolvers

private HttpMessageConverter>[] messageConverters =      new HttpMessageConverter>[] {new ByteArrayHttpMessageConverter(), new StringHttpMessageConverter(),      new SourceHttpMessageConverter(),      new org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter()};

messageConverters

public void setCustomArgumentResolver(WebArgumentResolver argumentResolver) {    this.customArgumentResolvers = new WebArgumentResolver[]{argumentResolver};  }

设置用于特殊方法参数类型的自定义参数解析器。这样的自定义ArgumentResolver将首先起作用,有机会在标准的参数处理起作用之前解析一个参数值。

public void setCustomArgumentResolvers(WebArgumentResolver[] argumentResolvers) {    this.customArgumentResolvers = argumentResolvers;  }

设置一个或多个用于特殊方法参数类型的自定义参数解析器。任何这样的自定义ArgumentResolver都将首先起作用,有机会在标准的参数处理起作用之前解析一个参数值。

public void setMessageConverters(HttpMessageConverter>[] messageConverters) {    this.messageConverters = messageConverters;  }

设置要使用的消息正文转换器。这些转换器用于将请求和响应转换为HTTP请求和响应。

  @Override  protected ModelAndView doResolveException(      HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {    if (handler != null) {//      找到异常handler的方法      Method handlerMethod = findBestExceptionHandlerMethod(handler, ex);      if (handlerMethod != null) {        ServletWebRequest webRequest = new ServletWebRequest(request, response);        try {//          解析handler参数          Object[] args = resolveHandlerArguments(handlerMethod, handler, webRequest, ex);          if (logger.isDebugEnabled()) {            logger.debug("Invoking request handler method: " + handlerMethod);          }//          执行方法          Object retVal = doInvokeMethod(handlerMethod, handler, args);//          获得modelAndView          return getModelAndView(handlerMethod, retVal, webRequest);        }        catch (Exception invocationEx) {          logger.error("Invoking request method resulted in exception : " + handlerMethod, invocationEx);        }      }    }    return null;  }

解析异常返回modelAndView,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver#getModelAndView 获得modelAndView

  private ModelAndView getModelAndView(Method handlerMethod, Object returnValue, ServletWebRequest webRequest)      throws Exception {    ResponseStatus responseStatus = AnnotatedElementUtils.findMergedAnnotation(handlerMethod, ResponseStatus.class);    if (responseStatus != null) {      HttpStatus statusCode = responseStatus.code();      String reason = responseStatus.reason();      if (!StringUtils.hasText(reason)) {        webRequest.getResponse().setStatus(statusCode.value());      }      else {        webRequest.getResponse().sendError(statusCode.value(), reason);      }    }    if (returnValue != null && AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {//      执行@ResponseBody      return handleResponseBody(returnValue, webRequest);    }    if (returnValue instanceof ModelAndView) {      return (ModelAndView) returnValue;    }    else if (returnValue instanceof Model) {      return new ModelAndView().addAllObjects(((Model) returnValue).asMap());    }    else if (returnValue instanceof Map) {      return new ModelAndView().addAllObjects((Map<String, Object>) returnValue);    }    else if (returnValue instanceof View) {      return new ModelAndView((View) returnValue);    }    else if (returnValue instanceof String) {      return new ModelAndView((String) returnValue);    }    else if (returnValue == null) {      return new ModelAndView();    }    else {      throw new IllegalArgumentException("Invalid handler method return value: " + returnValue);    }  }
  protected Listextends Throwable>> getHandledExceptions(Method method) {    Listextends Throwable>> result =     ExceptionHandler exceptionHandler = AnnotationUtils.findAnnotation(method, ExceptionHandler.class);    if (exceptionHandler != null) {      if (!ObjectUtils.isEmpty(exceptionHandler.value())) {        result.addAll(Arrays.asList(exceptionHandler.value()));      }      else {        for (Class> param : method.getParameterTypes()) {          if (Throwable.class.isAssignableFrom(param)) {            result.add((Class extends Throwable>) param);          }        }      }    }    return result;  }

返回由给定方法处理的所有异常类。默认实现在注释中查找异常,或者(如果注释元素为空)方法参数中列出的任何异常(如果方法使用@ExceptionHandler进行注释)。

protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWebRequest webRequest,      Exception thrownException) throws Exception {    // Invoke custom argument resolvers if present...    if (this.customArgumentResolvers != null) {      for (WebArgumentResolver argumentResolver : this.customArgumentResolvers) {        Object value = argumentResolver.resolveArgument(methodParameter, webRequest);        if (value != WebArgumentResolver.UNRESOLVED) {          return value;        }      }    }    // Resolution of standard parameter types...    Class> paramType = methodParameter.getParameterType();    Object value = resolveStandardArgument(paramType, webRequest, thrownException);    if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) {      throw new IllegalStateException(          "Standard argument type [" + paramType.getName() + "] resolved to incompatible value of type [" +              (value != null ? value.getClass() : null) +              "]. Consider declaring the argument type in a less specific fashion.");    }    return value;  }

解析常用方法参数。首先委托给注册的argumentResolvers,然后检查resolveStandardArgument。org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver#resolveStandardArgument 解析标准方法参数。默认实现处理NativeWebRequest、ServletRequest、ServletResponse、HttpSession、主体、语言环境、请求InputStream、请求阅读器、响应OutputStream、响应写入器和给定的thrownException。

protected Object resolveStandardArgument(Class> parameterType, NativeWebRequest webRequest,      Exception thrownException) throws Exception {    if (parameterType.isInstance(thrownException)) {      return thrownException;    }    else if (WebRequest.class.isAssignableFrom(parameterType)) {      return webRequest;    }    HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);    HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);    if (ServletRequest.class.isAssignableFrom(parameterType)) {      return request;    }    else if (ServletResponse.class.isAssignableFrom(parameterType)) {      return response;    }    else if (HttpSession.class.isAssignableFrom(parameterType)) {      return request.getSession();    }    else if (Principal.class.isAssignableFrom(parameterType)) {      return request.getUserPrincipal();    }    else if (Locale.class == parameterType) {      return RequestContextUtils.getLocale(request);    }    else if (InputStream.class.isAssignableFrom(parameterType)) {      return request.getInputStream();    }    else if (Reader.class.isAssignableFrom(parameterType)) {      return request.getReader();    }    else if (OutputStream.class.isAssignableFrom(parameterType)) {      return response.getOutputStream();    }    else if (Writer.class.isAssignableFrom(parameterType)) {      return response.getWriter();    }    else {      return WebArgumentResolver.UNRESOLVED;    }  }

说在最后

本次解析仅代表个人观点,仅供参考。

1c2e878758bd076c580969ee884b6fcf.gif

扫码进入技术微信群

34996293b72c228a056d2065f067925b.png 9931eee1a7192a96a0f193ce836c8585.png 23f4edcad7cb50a301faa0d7fdcfd2cc.png钉钉技术群

14d44b9e6d981370ef697e15ff3ee901.png

qq技术群

4c39e3bb02506ab20790284bec8af050.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值