You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot升级后REST服务错误响应异常及白标页问题求助

问题根源与解决方案

核心问题1:ErrorMessage构造函数未初始化字段

你的ErrorMessage类中的两个构造函数都是空实现,没有给类的成员变量赋值。比如调用new ErrorMessage("404", e.getMessage(), stackTrace)时,statusCode、message等字段完全没被设置,最终序列化后自然全是默认值(int类型为0,引用类型为null)。

修复构造函数

修改ErrorMessage的构造函数,确保参数正确映射到成员变量:

import java.util.Date;

public class ErrorMessage {

    private int statusCode;
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
    private Date timestamp;

    private String message;
    private String path;
    private String error;

    // 针对404场景的构造函数,补充必要字段赋值
    public ErrorMessage(int statusCode, Date timestamp, String message, String path, String error) {
        this.statusCode = statusCode;
        this.timestamp = timestamp;
        this.message = message;
        this.path = path;
        this.error = error;
    }

    // 兼容原有调用的构造函数,补充赋值逻辑
    public ErrorMessage(int value, Date date, String message, String resourceNotFound) {
        this.statusCode = value;
        this.timestamp = date;
        this.message = message;
        this.error = resourceNotFound;
    }

    public ErrorMessage(String status, String message, String stackTrace) {
        this.statusCode = Integer.parseInt(status);
        this.message = message;
        this.error = stackTrace;
        this.timestamp = new Date(); // 自动生成当前时间戳
    }

    // 原有getter/setter保留
    public int getStatusCode() { return statusCode; }
    public void setStatusCode(int statusCode) { this.statusCode = statusCode; }
    public Date getTimestamp() { return timestamp; }
    public void setTimestamp(Date timestamp) { this.timestamp = timestamp; }
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }
    public String getPath() { return path; }
    public void setPath(String path) { this.path = path; }
    public String getError() { return error; }
    public void setError(String error) { this.error = error; }
}

核心问题2:全局异常处理器的缺陷

你的ValidationExceptionHandler存在以下问题:

  • 方法参数使用Exception而非CustomDataNotFoundException,不够精准
  • 未获取当前请求的路径(path字段)
  • 未设置timestamp字段
  • Spring Boot升级后,默认内容协商机制会根据浏览器Accept头返回HTML白标页,而非JSON

修复全局异常处理器

改用@RestControllerAdvice(等同于@ControllerAdvice + @ResponseBody,确保返回JSON),同时补充路径和时间戳的获取:

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;

@RestControllerAdvice
public class ValidationExceptionHandler {

    @ExceptionHandler(CustomDataNotFoundException.class)
    public ResponseEntity<ErrorMessage> handleCustomDataNotFoundExceptions(
            CustomDataNotFoundException e, HttpServletRequest request
    ) {
        HttpStatus status = HttpStatus.NOT_FOUND;

        // 转换堆栈信息为字符串
        StringWriter stringWriter = new StringWriter();
        PrintWriter printWriter = new PrintWriter(stringWriter);
        e.printStackTrace(printWriter);
        String stackTrace = stringWriter.toString();

        // 构造正确的ErrorMessage对象
        ErrorMessage errorMessage = new ErrorMessage(
                status.value(),
                new Date(),
                e.getMessage(),
                request.getRequestURI(),
                stackTrace
        );

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

核心问题3:Controller逻辑错误

你的Controller代码中存在永远为false的条件判断:

if (system.isEmpty() && !system.isEmpty()) {
    // 这段代码永远不会执行
}

这个逻辑矛盾,需要根据实际业务需求修正,比如改为if (system == null || system.isEmpty()),否则相关的异常抛出逻辑永远不会触发。

额外配置:强制所有异常返回JSON(可选)

如果希望浏览器请求时也强制返回JSON而非白标页,可以添加以下配置类,覆盖Spring Boot默认错误处理:

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import jakarta.servlet.http.HttpServletRequest;
import java.util.Date;

@RestController
public class CustomErrorController implements ErrorController {

    @RequestMapping("/error")
    public ResponseEntity<ErrorMessage> handleError(HttpServletRequest request) {
        Object statusObj = request.getAttribute("jakarta.servlet.error.status_code");
        int statusCode = statusObj != null ? Integer.parseInt(statusObj.toString()) : HttpStatus.INTERNAL_SERVER_ERROR.value();
        String message = (String) request.getAttribute("jakarta.servlet.error.message");
        String path = (String) request.getAttribute("jakarta.servlet.error.request_uri");

        ErrorMessage errorMessage = new ErrorMessage(
                statusCode,
                new Date(),
                message != null ? message : "An unexpected error occurred",
                path,
                ""
        );

        return new ResponseEntity<>(errorMessage, HttpStatus.valueOf(statusCode));
    }
}

内容的提问来源于stack exchange,提问作者Rose

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 08:50:10