在Spring Boot中抛出ResponseStatusException时,响应中不包含异常信息

51

我的Spring Boot应用程序提供以下REST控制器:

@RestController
@RequestMapping("/api/verify")
public class VerificationController {

    final VerificationService verificationService;

    Logger logger = LoggerFactory.getLogger(VerificationController.class);

    public VerificationController(VerificationService verificationService) {
        this.verificationService = verificationService;
    }

    @GetMapping
    public void verify(
            @RequestParam(value = "s1") String s1,
            @RequestParam(value = "s2") String s2) {     
        try {
            verificationService.validateFormat(s1, s2);
        } catch (InvalidFormatException e) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage());
        }
    }
}

如果validateFormat()抛出InvalidFormatException,客户端会收到 HTTP 400 响应,这是正确的。但默认的 JSON 响应体看起来像这样:

{
    "timestamp": "2020-06-18T21:31:34.911+00:00",
    "status": 400,
    "error": "Bad Request",
    "message": "",
    "path": "/api/verify"
}

即使我像这样硬编码,message 值始终为空:

throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "some string");

这是异常类:

public class InvalidFormatException extends RuntimeException {

    public InvalidFormatException(String s1, String s2) {
        super(String.format("Invalid format: [s1: %s, s2: %s]", s1, s2));
    }
}

1
你确定没有自定义拦截器吗?Spring ExceptionHandler 没有将时间戳转换为日期格式(它将以毫秒为单位)。正如我们在你的响应中看到的那样。 - Kumar V
@KumarV 我不知道有什么问题。我使用了Spring Intializr和IntelliJ,这个工具完成了大部分的设置。我该如何找到这个问题的原因? - Robert Strauch
你正在使用哪个版本的Spring Boot? - Kumar V
将您的版本降级至2.1.x并尝试一下,以确保它是否与最新的引导程序版本有关。 - Kumar V
我能想到的另一个原因是,Spring 可能会因为其他原因而抛出 BAD_REQUEST 状态,而不是从你的异常处理块中抛出。在控制器中使用断点进行调试,以确保实际执行了 validateFormat() 方法,或者使用其他状态代码抛出 ResponseStatusException。 - Kumar V
显示剩余2条评论
2个回答

92
这种行为在Spring Boot 2.3中发生了变化,并且是故意的。有关详细信息,请参见 发行说明
application.properties文件中设置server.error.include-message=always可以解决此问题。

7

server.error.include-message=always设置会披露内部异常的信息,这可能在生产环境中会造成问题。

另一种方法是使用ExceptionHandler。在这里,您可以控制传递给客户端的内容:

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(ResponseStatusException.class)
    public ResponseEntity<String> handleBadRequestException(ResponseStatusException ex) {
        // if you want you can do some extra processing with message and status of an exception 
        // or you can return it without any processing like this:
        return new ResponseEntity<>(ex.getMessage(), ex.getStatus());
    }
}

1
在生产环境中暴露异常信息通常是不好的。我很惊讶更多的人没有考虑到这一点。 - teuber789

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接