1. 程式人生 > >Springboot自定義錯誤頁面(4xx/5xx)及異常集中處理

Springboot自定義錯誤頁面(4xx/5xx)及異常集中處理

自定義異常頁面(4xx,5xx)

  • Springboot 1.4.0 版本以下
    自定義一個實現EmbeddedServletContainerCustomizer介面的Component,在該例項中進行自定義ErrorPage配置。
    示例程式碼如下:
@Component
public class CustomizationBean implements EmbeddedServletContainerCustomizer {
    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        Set<ErrorPage> errorPages = new
HashSet<>(); errorPages.add(new ErrorPage(HttpStatus.NOT_FOUND, "/error/404")); errorPages.add(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500")); errorPages.add(new ErrorPage(Throwable.class, "/error/500")); container.setErrorPages(errorPages); } }
  • Springboot 1.4.0 版本以上
    通過實現ErrorPageRegistrar
    介面定義錯誤頁面,該方式定義的錯誤頁面等價於傳統專案中在web.xml中配置的error-page。
    示例如下:
 @Component
public class ErrorConfiguration implements ErrorPageRegistrar {

    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        ErrorPage[] errorPages = new ErrorPage[]{
                new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"
), new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500"), new ErrorPage(Throwable.class, "/error/500") }; registry.addErrorPages(errorPages); } }

ErrorPage通過HttpStatus或者Throwable 以及自定義的一個錯誤展示路徑,發生對應的錯誤時通過forward的方式請求指定的path。

PS:ErrorPageRegistrar,ErrorPageRegistry,ErrorPage在springboot 2.0.0版本更新後變更了包路徑,2.0.0以前的包路徑為:org.springframework.boot.web.servlet,2.0.0更新後變更為:org.springframework.boot.web.server

Controller異常集中處理

Controller的異常集中處理可以通過定義一個ControllerAdvice來處理,配合@ExceptionHandler指定針對不同異常做不同處理。
示例如下:

@ControllerAdvice
public class GlobalExceptionHandler {
    private Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    /**
     * 捕獲具體指定外的所有異常
     *
     * @param ex
     * @param request
     * @param response
     */
    @ExceptionHandler(value = Exception.class)
    private void handle(Exception ex, HttpServletRequest request, HttpServletResponse response) {
        LOGGER.error("***** GlobalException Handle Start *****");
        LOGGER.error("Exception:{}", ex.toString());
        LOGGER.error("Message:{}", ex.getMessage());
        LOGGER.error("Request Url:{}", request.getRequestURL());
        Enumeration enumeration = request.getParameterNames();
        LOGGER.error("Parameters:");
        while (enumeration.hasMoreElements()) {
            String name = enumeration.nextElement().toString();
            LOGGER.error("[{}]:[{}]", name, request.getParameter(name));
        }
        StackTraceElement[] error = ex.getStackTrace();
        LOGGER.error("StackTrace:");
        for (StackTraceElement stackTraceElement : error) {
            LOGGER.error("{}", stackTraceElement.toString());
        }
        LOGGER.error("***** GlobalException Handle End *****");
    }


}

@ExceptionHandler註解定義

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
    Class<? extends Throwable>[] value() default {};
}

該示例程式碼指定的異常為Exception.class,即表示所有Exception及子類異常都可以處理,通過檢視@ExceptionHandler註解我們可以知道該註解支援Throwable的所有子類,包括ExceptionError,並且可以同時指定多個異常或錯誤。