• 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。

  • 相关阅读:
    Charles抓包工具
    JQuery 实现表单验证,所有验证通过方可提交
    卡巴斯基注册信息清除
    Nginx 404 Not Found 解决办法
    php mysql 多表查询之子查询语句
    搜狗拼音、QQ拼音输入法、2345拼音输入法、百度输入法 、手心输入法对比。(个人体会)
    Notepad++使用-如何导出/导入配置文件
    深蓝词库转换2.4版发布,支持最新的搜狗用户词库备份bin格式
    网站更换服务器,百度站长后台抓取诊断时间
    阿里云代金券领取
  • 原文地址:https://www.cnblogs.com/BonnieWss/p/11656214.html
Copyright © 2020-2023  润新知