zoukankan      html  css  js  c++  java
  • spring boot 错误处理机制

    参考:https://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#boot-features-error-handling

    spring boot 提供了默认的/error路径,并展示一个全局的错误页面。 以下几种方式用来自定义错误处理:

    (1)实现 ErrorController 接口或者继承BasicErrorController类

    BasicErrorController类如下:

    package org.springframework.boot.autoconfigure.web.servlet.error;
    
    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.boot.autoconfigure.web.ErrorProperties;
    import org.springframework.boot.autoconfigure.web.ErrorProperties.IncludeStacktrace;
    import org.springframework.boot.web.servlet.error.ErrorAttributes;
    import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Controller;
    import org.springframework.util.Assert;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.servlet.ModelAndView;
    
    /**
     * Basic global error {@link Controller}, rendering {@link ErrorAttributes}. More specific
     * errors can be handled either using Spring MVC abstractions (e.g.
     * {@code @ExceptionHandler}) or by adding servlet
     * {@link AbstractServletWebServerFactory#setErrorPages server error pages}.
     *
     * @author Dave Syer
     * @author Phillip Webb
     * @author Michael Stummvoll
     * @author Stephane Nicoll
     * @see ErrorAttributes
     * @see ErrorProperties
     */
    @Controller
    @RequestMapping("${server.error.path:${error.path:/error}}")
    public class BasicErrorController extends AbstractErrorController {
    
        private final ErrorProperties errorProperties;
    
        /**
         * Create a new {@link BasicErrorController} instance.
         * @param errorAttributes the error attributes
         * @param errorProperties configuration properties
         */
        public BasicErrorController(ErrorAttributes errorAttributes,
                ErrorProperties errorProperties) {
            this(errorAttributes, errorProperties, Collections.emptyList());
        }
    
        /**
         * Create a new {@link BasicErrorController} instance.
         * @param errorAttributes the error attributes
         * @param errorProperties configuration properties
         * @param errorViewResolvers error view resolvers
         */
        public BasicErrorController(ErrorAttributes errorAttributes,
                ErrorProperties errorProperties, List<ErrorViewResolver> errorViewResolvers) {
            super(errorAttributes, errorViewResolvers);
            Assert.notNull(errorProperties, "ErrorProperties must not be null");
            this.errorProperties = errorProperties;
        }
    
        @Override
        public String getErrorPath() {
            return this.errorProperties.getPath();
        }
      
      
      //当为网页请求时返回error页面 @RequestMapping(produces
    = "text/html") public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes( request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView != null) ? modelAndView : new ModelAndView("error", model); }   
      //当为其他请求时,返回ResponseEntity @RequestMapping @ResponseBody
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = getStatus(request); return new ResponseEntity<>(body, status); } /** * Determine if the stacktrace attribute should be included. * @param request the source request * @param produces the media type produced (or {@code MediaType.ALL}) * @return if the stacktrace attribute should be included */ protected boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) { IncludeStacktrace include = getErrorProperties().getIncludeStacktrace(); if (include == IncludeStacktrace.ALWAYS) { return true; } if (include == IncludeStacktrace.ON_TRACE_PARAM) { return getTraceParameter(request); } return false; } /** * Provide access to the error properties. * @return the error properties */ protected ErrorProperties getErrorProperties() { return this.errorProperties; } }

    通过errorHtml和error方法来处理异常。这两个方法中都有一个关键的方法getErrorAttributes,这个方法是其父类AbstractErrorController的方法,代码如下:

    public abstract class AbstractErrorController implements ErrorController {
    
        private final ErrorAttributes errorAttributes;
        
        protected Map<String, Object> getErrorAttributes(HttpServletRequest request,boolean includeStackTrace) {
          WebRequest webRequest = new ServletWebRequest(request);
          return this.errorAttributes.getErrorAttributes(webRequest, includeStackTrace);
        }
      ... }

    可以看出,上述方法调用的其实是ErrorAttributes的getErrorAttributes方法,所以可以直接实现ErrorAttributes 接口,即第二种方法。

    (2)实现ErrorAttributes 接口或者继承DefaultErrorAttributes类

    继承DefaultErrorAttributes类并重写的getErrorAttributes方法

    (3)使用@ControllerAdvice注解

    例如:

    @ControllerAdvice(basePackageClasses = FooController.class)
    public class FooControllerAdvice extends ResponseEntityExceptionHandler {
    
        @ExceptionHandler(YourException.class)
        @ResponseBody
        ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
            HttpStatus status = getStatus(request);
            return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
        }
    
        private HttpStatus getStatus(HttpServletRequest request) {
            Integer statusCode = (Integer) reques通过e("javax.servlet.error.status_code");
            if (statusCode == null) {
                return HttpStatus.INTERNAL_SERVER_ERROR;
            }
            return HttpStatus.valueOf(statusCode);
        }
    
    }

    如果和FooControllerAdvice 在同一个包下的controller类抛出YourException异常,那么就会返回CustomErrorType类型的json。

  • 相关阅读:
    CentOS 7拨号上网(ADSL & PPPoE)
    linux使用nmcli重新生成网卡配置文件
    Linux 内存缓存占用过大,Centos7设置定时清除buff/cache的脚本
    部署redis6.0 常见问题
    ssh 升级导致的hadoop 主备切换失败
    配置zookeeper的 ACL权限
    sqoop 创建跟mysql相同表结构的hive表报错
    vim中显示不可见字符
    supervisor 使用
    使用hive streaming 统计Wordcount
  • 原文地址:https://www.cnblogs.com/BonnieWss/p/11656214.html
Copyright © 2011-2022 走看看