spring boot error handling

参考: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。

猜你喜欢

转载自www.cnblogs.com/BonnieWss/p/11656214.html