SpringBoot BasicExceptionController(ErrorController)全局异常处理(处理404、500错误、Filter过滤器报错)

需要掌握:
https://www.malaoshi.top/show_1IX74ajxo0V5.html

说明

BasicExceptionController 功能非常强大,是SpringBoot默认处理异常方式,在没有配置任何异常处理时,当访问controlle抛出异常时,就是使用该方式处理异常的

也是SpringBoot 兜底 的处理异常方式,当 静态资源不存在时、过滤器抛错,都可以使用该方式处理异常

与 @ControllerAdvice、@RestControllerAdvice的区别

@ControllerAdvice、@RestControllerAdvice 只能处理 Controller 抛出的异常

当 过滤器抛错 ,该注解将无法处理

当 资源不存在时(404错误),使用该注解能处理,比较麻烦

应用场景

如果前端程序员,请求api时把接口地址写错了,就会得到一个404错误,如下:

{
  "timestamp": 1492063521109,
  "status": 404,
  "error": "Not Found",
  "message": "No message available",
  "path": "/rest11/auth"
}

虽然也清晰明了,但与 统一的返回格式不一致

一般统一返回json格式如下:

{
  "code": 404,
  "msg": "Not Found"
}

源码

BasicExceptionController 实现 ErrorController 接口

BasicExceptionController 部分源码 如下:

// 必须有 @Controller
@Controller
// 默认路由是 /error,也就是说不能再有controller使用该路由
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {

    // 浏览器发来请求,就执行该方法,返回 html 页面
    @RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
    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);
    }
    // ajax、客户度发请求,就执行该方法,返回json字符串
    @RequestMapping
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        HttpStatus status = getStatus(request);
        if (status == HttpStatus.NO_CONTENT) {
            return new ResponseEntity<>(status);
        }
        Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
        return new ResponseEntity<>(body, status);
    }

实现

静态资源不存在时、过滤器抛错,都可以使用该方式处理异常

package top.malaoshi.netdisk.config;

import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping({"${server.error.path:${error.path:/error}}"})
public class MyBasicErrorController extends BasicErrorController   {


    public MyBasicErrorController(ServerProperties serverProperties) {
        super(new DefaultErrorAttributes(), serverProperties.getError());
    }


    @Override
    public String getErrorPath() {
        return null;
    }
    @RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        //请求的状态
        HttpStatus status = getStatus(request);
        response.setStatus(getStatus(request).value());
        Map<String, Object> model = getErrorAttributes(request,isIncludeStackTrace(request, MediaType.TEXT_HTML));
        ModelAndView modelAndView = resolveErrorView(request, response, status, model);
        //指定自定义的视图
        return (modelAndView == null ? new ModelAndView("error", model) : modelAndView);
    }
    @Override
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {

        HttpStatus status = getStatus(request);
        Map<String, Object> map = new HashMap<String, Object>(16);
        Map<String, Object> originalMsgMap = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
        String path = (String)originalMsgMap.get("path");
        String error = (String)originalMsgMap.get("error");
        String message = (String)originalMsgMap.get("message");

        String msg = null;
        if(status.value() == 500){
            msg = message;
        }else{ // 如果404等异常,message是空的
            msg = error;
        }
        map.put("code", status.value());
        map.put("msg", msg);
        return new ResponseEntity<Map<String, Object>>(map, status);
    }

}

参考:
https://www.jianshu.com/p/ec932d6091c1
https://www.cnblogs.com/54chensongxia/p/14007696.html
https://blog.csdn.net/m1090760001/article/details/105454399
https://blog.csdn.net/java_chegnxuyuan/article/details/100941768


原文出处:/show_1IX74bxq8UGC.html