private void initResponseStatus() {
   ResponseStatus annot = getMethodAnnotation(ResponseStatus.class);
   if (annot != null) {
     this.responseStatus = annot.value();
     this.responseReason = annot.reason();
   }
 }
 @ExceptionHandler(Exception.class)
 public ResponseEntity handler(HttpServletRequest request, Exception e) {
   ResponseStatus responseStatus =
       AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class);
   if (responseStatus == null) {
     this.logError(request, e);
   } else {
     this.logWarning(request, e);
   }
   ErrorInfo errorInfo =
       responseStatus == null
           ? new ErrorInfo(e, request)
           : new ErrorInfo(responseStatus.value(), e, request);
   return status(errorInfo.getHttpStatus()).body(errorInfo);
 }
  /**
   * Template method that handles {@link ResponseStatus @ResponseStatus} annotation.
   *
   * <p>Default implementation send a response error using {@link
   * HttpServletResponse#sendError(int)} or {@link HttpServletResponse#sendError(int, String)} if
   * the annotation has a {@linkplain ResponseStatus#reason() reason} and then returns an empty
   * ModelAndView.
   *
   * @param responseStatus the annotation
   * @param request current HTTP request
   * @param response current HTTP response
   * @param handler the executed handler, or {@code null} if none chosen at the time of the
   *     exception (for example, if multipart resolution failed)
   * @param ex the exception that got thrown during handler execution or the exception that has the
   *     ResponseStatus annotation if found on the cause.
   * @return a corresponding ModelAndView to forward to, or {@code null} for default processing
   */
  protected ModelAndView resolveResponseStatus(
      ResponseStatus responseStatus,
      HttpServletRequest request,
      HttpServletResponse response,
      Object handler,
      Exception ex)
      throws Exception {

    int statusCode = responseStatus.value().value();
    String reason = responseStatus.reason();
    if (this.messageSource != null) {
      reason = this.messageSource.getMessage(reason, null, reason, LocaleContextHolder.getLocale());
    }
    if (!StringUtils.hasLength(reason)) {
      response.sendError(statusCode);
    } else {
      response.sendError(statusCode, reason);
    }
    return new ModelAndView();
  }
  private Operation parseMethod(Method method) {
    Operation operation = new Operation();

    RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
    Class<?> responseClass = null;
    List<String> produces = new ArrayList<String>();
    List<String> consumes = new ArrayList<String>();
    String responseContainer = null;
    String operationId = method.getName();
    Map<String, Property> defaultResponseHeaders = null;
    Set<Map<String, Object>> customExtensions = null;

    ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);

    if (apiOperation.hidden()) return null;
    if (!"".equals(apiOperation.nickname())) operationId = apiOperation.nickname();

    defaultResponseHeaders = parseResponseHeaders(apiOperation.responseHeaders());

    operation.summary(apiOperation.value()).description(apiOperation.notes());

    customExtensions = parseCustomExtensions(apiOperation.extensions());
    if (customExtensions != null) {
      for (Map<String, Object> extension : customExtensions) {
        if (extension != null) {
          for (Map.Entry<String, Object> map : extension.entrySet()) {
            operation.setVendorExtension(
                map.getKey().startsWith("x-") ? map.getKey() : "x-" + map.getKey(), map.getValue());
          }
        }
      }
    }

    if (apiOperation.response() != null && !Void.class.equals(apiOperation.response()))
      responseClass = apiOperation.response();
    if (!"".equals(apiOperation.responseContainer()))
      responseContainer = apiOperation.responseContainer();

    /// security
    if (apiOperation.authorizations() != null) {
      List<SecurityRequirement> securities = new ArrayList<SecurityRequirement>();
      for (Authorization auth : apiOperation.authorizations()) {
        if (auth.value() != null && !"".equals(auth.value())) {
          SecurityRequirement security = new SecurityRequirement();
          security.setName(auth.value());
          AuthorizationScope[] scopes = auth.scopes();
          for (AuthorizationScope scope : scopes) {
            if (scope.scope() != null && !"".equals(scope.scope())) {
              security.addScope(scope.scope());
            }
          }
          securities.add(security);
        }
      }
      if (securities.size() > 0) {
        for (SecurityRequirement sec : securities) operation.security(sec);
      }
    }

    if (responseClass == null) {
      // pick out response from method declaration
      LOG.info("picking up response class from method " + method);
      Type t = method.getGenericReturnType();
      responseClass = method.getReturnType();
      if (responseClass.equals(ResponseEntity.class)) {
        responseClass = getGenericSubtype(method.getReturnType(), method.getGenericReturnType());
      }
      if (!responseClass.equals(Void.class)
          && !"void".equals(responseClass.toString())
          && responseClass.getAnnotation(Api.class) == null) {
        LOG.info("reading model " + responseClass);
        Map<String, Model> models = ModelConverters.getInstance().readAll(t);
      }
    }
    if (responseClass != null
        && !responseClass.equals(Void.class)
        && !responseClass.equals(ResponseEntity.class)
        && responseClass.getAnnotation(Api.class) == null) {
      if (isPrimitive(responseClass)) {
        Property responseProperty = null;
        Property property = ModelConverters.getInstance().readAsProperty(responseClass);
        if (property != null) {
          if ("list".equalsIgnoreCase(responseContainer))
            responseProperty = new ArrayProperty(property);
          else if ("map".equalsIgnoreCase(responseContainer))
            responseProperty = new MapProperty(property);
          else responseProperty = property;
          operation.response(
              200,
              new Response()
                  .description("successful operation")
                  .schema(responseProperty)
                  .headers(defaultResponseHeaders));
        }
      } else if (!responseClass.equals(Void.class) && !"void".equals(responseClass.toString())) {
        Map<String, Model> models = ModelConverters.getInstance().read(responseClass);
        if (models.size() == 0) {
          Property pp = ModelConverters.getInstance().readAsProperty(responseClass);
          operation.response(
              200,
              new Response()
                  .description("successful operation")
                  .schema(pp)
                  .headers(defaultResponseHeaders));
        }
        for (String key : models.keySet()) {
          Property responseProperty = null;

          if ("list".equalsIgnoreCase(responseContainer))
            responseProperty = new ArrayProperty(new RefProperty().asDefault(key));
          else if ("map".equalsIgnoreCase(responseContainer))
            responseProperty = new MapProperty(new RefProperty().asDefault(key));
          else responseProperty = new RefProperty().asDefault(key);
          operation.response(
              200,
              new Response()
                  .description("successful operation")
                  .schema(responseProperty)
                  .headers(defaultResponseHeaders));
          swagger.model(key, models.get(key));
        }
        models = ModelConverters.getInstance().readAll(responseClass);
        for (String key : models.keySet()) {
          swagger.model(key, models.get(key));
        }
      }
    }

    operation.operationId(operationId);

    if (requestMapping.produces() != null) {
      for (String str : Arrays.asList(requestMapping.produces())) {
        if (!produces.contains(str)) {
          produces.add(str);
        }
      }
    }
    if (requestMapping.consumes() != null) {
      for (String str : Arrays.asList(requestMapping.consumes())) {
        if (!consumes.contains(str)) {
          consumes.add(str);
        }
      }
    }

    ApiResponses responseAnnotation = method.getAnnotation(ApiResponses.class);
    if (responseAnnotation != null) {
      updateApiResponse(operation, responseAnnotation);
    } else {
      ResponseStatus responseStatus = method.getAnnotation(ResponseStatus.class);
      if (responseStatus != null) {
        operation.response(
            responseStatus.value().value(), new Response().description(responseStatus.reason()));
      }
    }

    boolean isDeprecated = false;
    Deprecated annotation = method.getAnnotation(Deprecated.class);
    if (annotation != null) isDeprecated = true;

    boolean hidden = false;
    if (apiOperation != null) hidden = apiOperation.hidden();

    // process parameters
    Class[] parameterTypes = method.getParameterTypes();
    Type[] genericParameterTypes = method.getGenericParameterTypes();
    Annotation[][] paramAnnotations = method.getParameterAnnotations();
    // paramTypes = method.getParameterTypes
    // genericParamTypes = method.getGenericParameterTypes
    for (int i = 0; i < parameterTypes.length; i++) {
      Type type = genericParameterTypes[i];
      List<Annotation> annotations = Arrays.asList(paramAnnotations[i]);
      List<Parameter> parameters = getParameters(type, annotations);

      for (Parameter parameter : parameters) {
        operation.parameter(parameter);
      }
    }

    if (operation.getResponses() == null) {
      operation.defaultResponse(new Response().description("successful operation"));
    }

    // Process @ApiImplicitParams
    this.readImplicitParameters(method, operation);

    return operation;
  }
  protected ModelAndView doResolveHandlerMethodException(
      HttpServletRequest request,
      HttpServletResponse response,
      HandlerMethod handlerMethod,
      Exception exception) {

    if (handlerMethod == null) {
      return null;
    }

    Method method = handlerMethod.getMethod();

    if (method == null) {
      return null;
    }
    // 如果定义了@ExceptionHandler则返回相应的Map中的数据
    ModelAndView returnValue =
        super.doResolveHandlerMethodException(request, response, handlerMethod, exception);
    ResponseBody responseBodyAnn = AnnotationUtils.findAnnotation(method, ResponseBody.class);
    if (responseBodyAnn != null) {
      try {
        ResponseStatus responseStatusAnn =
            AnnotationUtils.findAnnotation(method, ResponseStatus.class);
        if (responseStatusAnn != null) { // 判断是否使用了@ResponseStatus
          HttpStatus responseStatus = responseStatusAnn.value();
          String reason = responseStatusAnn.reason();
          if (!StringUtils.hasText(reason)) {
            response.setStatus(responseStatus.value());
          } else {
            try {
              response.sendError(responseStatus.value(), reason);
            } catch (IOException e) {
            }
          }
        }

        if (exception instanceof ApiException) {
          ApiException apiException = (ApiException) exception;
          // response.setStatus(apiException.getCode());
          response.sendError(apiException.getCode(), apiException.getMessage());
          // handleResponseBody(apiException, request, response);
          return new ModelAndView();
        } else { // 如果不是自己定义好的异常就要记录日志
          String sessionId = request.getSession().getId();
          log.error("系统出错,sessionId=" + sessionId, exception);
        }

        // 如果没有找到@ExceptionHandler注解(controller中的方法出错时,有该注解的方法会被调用并返回数据)的处理方法或者没有返回值,
        // 又或者出错的方法没有标识@ResponseStatus注解
        if (returnValue == null) {
          ApiException res = new ApiException(ApiResponseUtil.STATUS.INTERNAL_SERVER_ERROR);
          handleResponseBody(res, request, response);
          return new ModelAndView();
        }
        return handleResponseError(returnValue, request, response);
      } catch (Exception e) {
        return null;
      }
    }

    if (null == returnValue) {
      returnValue = new ModelAndView();
      if (null == returnValue.getViewName()) {
        returnValue.setViewName(defaultErrorView);
      }
    }
    return returnValue;
  }