全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-18 6 分钟 ✍️ juanwangdev

Spring MVC 返回JSON格式错误信息

RESTful API开发中,统一JSON格式的错误响应是前后端协作的基础。

统一响应结构设计

Java
public class ErrorResponse {
    private int code;
    private String message;
    private String path;
    private Long timestamp;
    private Object data;

    // 构造器
    public ErrorResponse(int code, String message, String path) {
        this.code = code;
        this.message = message;
        this.path = path;
        this.timestamp = System.currentTimeMillis();
    }

    // 静态工厂方法
    public static ErrorResponse of(int code, String message, String path) {
        return new ErrorResponse(code, message, path);
    }

    public static ErrorResponse badRequest(String message, String path) {
        return new ErrorResponse(400, message, path);
    }

    public static ErrorResponse unauthorized(String message, String path) {
        return new ErrorResponse(401, message, path);
    }

    public static ErrorResponse forbidden(String message, String path) {
        return new ErrorResponse(403, message, path);
    }

    public static ErrorResponse notFound(String message, String path) {
        return new ErrorResponse(404, message, path);
    }

    public static ErrorResponse internalError(String message, String path) {
        return new ErrorResponse(500, message, path);
    }

    // getter/setter省略
}

全局异常处理器实现

Java
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleException(Exception e, HttpServletRequest request) {
        ErrorResponse error = ErrorResponse.internalError(
            e.getMessage(),
            request.getRequestURI()
        );
        return ResponseEntity.status(500).body(error);
    }

    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException e, HttpServletRequest request) {
        ErrorResponse error = new ErrorResponse(500, e.getMessage(), request.getRequestURI());
        return ResponseEntity.status(500).body(error);
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<ErrorResponse> handleIllegalArgument(IllegalArgumentException e, HttpServletRequest request) {
        ErrorResponse error = ErrorResponse.badRequest(
            e.getMessage(),
            request.getRequestURI()
        );
        return ResponseEntity.badRequest().body(error);
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseEntity<ErrorResponse> handleMethodNotSupported(
            HttpRequestMethodNotSupportedException e,
            HttpServletRequest request) {
        ErrorResponse error = new ErrorResponse(405, "不支持的请求方法: " + e.getMethod(), request.getRequestURI());
        return ResponseEntity.status(405).body(error);
    }

    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public ResponseEntity<ErrorResponse> handleMediaTypeNotSupported(
            HttpMediaTypeNotSupportedException e,
            HttpServletRequest request) {
        ErrorResponse error = new ErrorResponse(415, "不支持的媒体类型: " + e.getContentType(), request.getRequestURI());
        return ResponseEntity.status(415).body(error);
    }
}

参数校验异常处理

Java
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationException(
        MethodArgumentNotValidException e,
        HttpServletRequest request) {

    List<Map<String, String>> errors = e.getBindingResult()
        .getFieldErrors()
        .stream()
        .map(error -> {
            Map<String, String> err = new HashMap<>();
            err.put("field", error.getField());
            err.put("message", error.getDefaultMessage());
            return err;
        })
        .collect(Collectors.toList());

    ErrorResponse error = ErrorResponse.badRequest("参数校验失败", request.getRequestURI());
    error.setData(errors);

    return ResponseEntity.badRequest().body(error);
}

@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<ErrorResponse> handleConstraintViolation(
        ConstraintViolationException e,
        HttpServletRequest request) {

    List<Map<String, String>> errors = e.getConstraintViolations()
        .stream()
        .map(violation -> {
            Map<String, String> err = new HashMap<>();
            err.put("property", violation.getPropertyPath().toString());
            err.put("message", violation.getMessage());
            return err;
        })
        .collect(Collectors.toList());

    ErrorResponse error = ErrorResponse.badRequest("参数校验失败", request.getRequestURI());
    error.setData(errors);

    return ResponseEntity.badRequest().body(error);
}

响应示例

成功响应:

JSON
{
    "code": 200,
    "message": "success",
    "path": "/api/users/1",
    "timestamp": 1716000000000,
    "data": {
        "id": 1,
        "name": "张三"
    }
}

错误响应:

JSON
{
    "code": 400,
    "message": "参数校验失败",
    "path": "/api/users",
    "timestamp": 1716000000000,
    "data": [
        {
            "field": "username",
            "message": "用户名不能为空"
        },
        {
            "field": "email",
            "message": "邮箱格式不正确"
        }
    ]
}

结合枚举定义错误码

Java
public enum ErrorCode {
    SUCCESS(200, "操作成功"),
    BAD_REQUEST(400, "请求参数错误"),
    UNAUTHORIZED(401, "未授权访问"),
    FORBIDDEN(403, "禁止访问"),
    NOT_FOUND(404, "资源不存在"),
    INTERNAL_ERROR(500, "服务器内部错误");

    private final int code;
    private final String message;

    ErrorCode(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public int getCode() { return code; }
    public String getMessage() { return message; }
}

生产环境建议返回通用错误信息,避免暴露敏感的异常堆栈信息。

要点总结

  • 设计统一的ErrorResponse结构,包含code、message、path、timestamp
  • 使用@RestControllerAdvice实现全局异常处理
  • 参数校验异常需提取字段错误信息
  • 使用枚举管理错误码,提高可维护性
  • 生产环境注意隐藏敏感异常信息

📝 发现内容有误?点击此处直接编辑

← 上一篇 Spring MVC 自定义异常类
下一篇 → Spring MVC afterCompletion方法详解
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库