SpringBoot错误页配置及项目全局错误处理

解决俩个问题:

1> 用户体验:当我们请求路径写错时,浏览器显示一个"Whitelabel Error Page",对用户来说体验不友好。

2> 错误码分类:当浏览器请求出现异常时,有时不仅仅是400/404/500..还有Exception异常,对程序员来说不容易识别错误,此                             时考虑增加全局错误处理。

一 解决用户体验问题

以编程方式配置嵌入式servlet容器,可以通过注册实现 WebServerFactoryCustomizer 接口的Spring bean,该接口可以直接修改servlet容器配置。例如:

  • 网络设置:传入HTTP请求的侦听端口(server.port),要绑定的接口地址server.address,等等。
  • 会话设置:会话是持久性(server.servlet.session.persistence),会话超时(server.servlet.session.timeout),会话数据(server.servlet.session.store-dir)的位置以及会话cookie配置(server.servlet.session.cookie.*)。
  • 错误管理:错误页面的位置(server.error.path

首先创建一个错误页控制类:MyErrorPageController.java

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MyErrorPageController {

    @RequestMapping("error-404")
    public String toPage404(){
        return "error/error-404";
    }
    @RequestMapping("error-400")
    public String toPage400(){
        return "error/error-400";
    }
    @RequestMapping("error-500")
    public String toPage500(){
        return "error/error-500";
    }

}

然后创建错误页类:MyErrorPageConfig.java

package com.example.demo.config;

import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;

@Configuration
public class MyErrorPageConfig {

    /**
     * 以编程方式配置嵌入式servlet容器,可以通过注册实现该 WebServerFactoryCustomizer 接口的Spring bean
     * TomcatServletWebServerFactory,JettyServletWebServerFactory并且UndertowServletWebServerFactory 是专用变体,
            ConfigurableServletWebServerFactory分别为Tomcat,Jetty和Undertow提供了额外的自定义setter方法。
     * @return
     */
    @Bean
    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
        return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
            @Override
            public void customize(ConfigurableWebServerFactory factory) {
                // 对嵌入式servlet容器的配置
                // factory.setPort(8081);
                /* 注意:new ErrorPage(stat, path);中path必须是页面名称,并且必须“/”开始。
                    底层调用了String.java中如下方法:
                    public boolean startsWith(String prefix) {
                        return startsWith(prefix, 0);
                    }*/
                ErrorPage errorPage400 = new ErrorPage(HttpStatus.BAD_REQUEST,
                        "/error-400");
                ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND,
                        "/error-404");
                ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR,
                        "/error-500");
                factory.addErrorPages(errorPage400, errorPage404,
                        errorPage500);
            }
        };
    }
}
最后创建相关的页面:error/error-404.html/error/error-400.html/error/error-500.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>愿世界没有Bug</title>
</head>
<body>
<h1>对不起遇到了错误400</h1>
</body>
</html>

其他页面雷同

接下来验证我们的错误页:输入错误的访问路径,F12查看请求过程及页面展示!

成功!!!

二 解决错误码分类问题

首先定义一个错误的对象信息:ErrorInfo.java

package com.example.demo.bean;
public class ErrorInfo {
    // 错误类别码
    public Integer code;
    // 错误信息
    public String message;
    // 映射路径
    public String url;
    // get/set方法省略
}

然后创建一个控制层切面错误处理类:GlobalExceptionHandler.java

package com.example.demo.advice;

import com.example.demo.bean.ErrorInfo;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;

@ControllerAdvice // 作为一个控制层的切面处理
// @RestControllerAdvice // Rest风格,作为一个控制层的切面处理
public class GlobalExceptionHandler {

    private static final String DEFAULT_ERROR_VIEW = "error"; // 定义错误显示页,error.html
    private static final Integer INIT_ERROR_CODE = 500; // 定义初始错误码

    @ExceptionHandler(value = Exception.class) // 所有的异常都是Exception子类
    public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) {
        ModelAndView mv = new ModelAndView(DEFAULT_ERROR_VIEW);
        Integer errorCode = INIT_ERROR_CODE;
        // 可以自己定制错误分类对象信息
        ErrorInfo errorInfo = new ErrorInfo();
        // 对错误类型进行分类
        String header = request.getHeader("content-type");
        if(header != null && header.contains("json")){
            errorCode = 300; // json异常
        } else if (e instanceof ArithmeticException) {
            errorCode = 100; // 算术异常
        } else if (e instanceof NullPointerException) {
            errorCode = 200; // 空指针异常
        } else {
            errorCode = 999; // 其他异常
        }
        // 对错误码进行判断
        switch (errorCode) {
            case 100:
                errorInfo.setCode(errorCode); // 将错误码传递过去
                break;
            case 200:
                errorInfo.setCode(errorCode); // 将错误码传递过去
                break;
            case 300:
                errorInfo.setCode(errorCode); // 将错误码传递过去
                break;
            case 500:
                errorInfo.setCode(INIT_ERROR_CODE);  // 将错误码传递过去
                break;
            case 999:
                errorInfo.setCode(INIT_ERROR_CODE);  // 将错误码传递过去
                break;
            default:
                errorInfo.setCode(1000); // 将错误码传递过去
                break;
        }
        errorInfo.setMessage(e.getMessage());// 将异常对象传递过去
        errorInfo.setUrl(request.getRequestURL().toString());// 获得请求的路径
        mv.addObject("errorInfo", errorInfo);
        mv.setViewName("error/"+DEFAULT_ERROR_VIEW);
        return mv;
    }

}

最后创建错误页面:error/error.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>愿世界没有Bug</title>
</head>
<body>
<h1>Sorry,异常了(自定义)</h1>
<div>
    <p th:text="'错误码:' + ${errorInfo.code}"/>
    <p th:text="'映射路径:' + ${errorInfo.url}"/>
    <p th:text="'错误信息:' + ${errorInfo.message}"/>
</div>
</body>
</html>

搞定,接下来看一下结果:首先搞一个算术异常,输入访问路径->http://localhost/mul?param=0

@RequestMapping(value = "/mul")
    public int mulParam(int param) {
        return 9/param;
    }

访问结果如下图:

如此可以将所有异常信息展示出来,或是后台搞到数据库中,查找问题时,根据错误码,错误信息精准定位问题。不需要程序员对所有的Exception都了解。上手简单,排难精准。

猜你喜欢

转载自blog.csdn.net/csdn_0911/article/details/82794426