原理

  • @ControllerAdvice + @ExceptionHandler 统一处理应用级别的异常
  • 自定义ErrorController 处理容器级别的异常,例如:404异常
  • 捕获NoHandlerFoundException 异常处理404异常

统一返回格式

package com.github.mouday.common;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * 统一返回格式
 */
public class JsonResult implements Serializable {

    private String msg;

    private Integer code;

    private Object data;


    private JsonResult(Object data, String msg, Integer code) {
        this.data = data;
        this.msg = msg;
        this.code = code;
    }


    public static JsonResult success(Object data) {
        return new JsonResult(data, "success", 0);
    }

    public static JsonResult error() {
        return new JsonResult(null, "error", -1);
    }

    public static JsonResult error(String msg) {
        return new JsonResult(null, msg, -1);
    }

    public static JsonResult error(String msg, Integer code) {
        return new JsonResult(null, msg, code);
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Map<String, Object> toMap() {
        Map<String, Object> map = new HashMap<>();
        map.put("msg", this.msg);
        map.put("code", this.code);
        map.put("data", this.data);
        return map;
    }
}

统一异常处理

package com.github.mouday.common;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 统一异常处理
 * 参考
 * https://www.jianshu.com/p/3998ea8b53a8
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public JsonResult exceptionHandler(Throwable error) {
        return JsonResult.error(error.getMessage(), -1);
    }
}

自定义ErrorController 处理404异常

package com.github.mouday.controller;

import com.github.mouday.common.JsonResult;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
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 javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * 处理404异常
 * <p>
 * 参考
 * https://www.cnblogs.com/54chensongxia/archive/2020/11/20/14007696.html
 * https://blog.csdn.net/qq_38571892/article/details/123395165
 */
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class CustomErrorController extends BasicErrorController {

    public CustomErrorController() {
        super(new DefaultErrorAttributes(), new ErrorProperties());
    }

    /**
     * 覆盖默认的JSON响应
     */
    @Override
    @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, getErrorAttributeOptions(request, MediaType.ALL));

        String message = (String) body.get("error");

        Map<String, Object> result = JsonResult.error(message).toMap();

        return new ResponseEntity<>(result, status);
    }
}

现在,所有接口的返回格式就统一了

{
  "msg": "服务端运行时异常",
  "code": -1,
  "data": null
}

捕获NoHandlerFoundException 处理404异常

@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理404异常
     * @param error
     * @return
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseBody
    public JsonResult noHandlerFoundExceptionHandler(NoHandlerFoundException error) {
        return JsonResult.error(error.getMessage(), -1);
    }
}

application.yml 需要如下配置

spring:
  mvc:
    throw-exception-if-no-handler-found: true
  web:
    resources:
      add-mappings: false

完整代码:https://github.com/mouday/spring-boot-demo

参考
Spring Boot优雅地处理404异常
SpringBoot 统一异常处理(附核心工具类-ErrorInfoBuilder)
Spring Boot之异常处理

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐