Spring ResponseStatusException 不返回原因

cun*_*haf 47 java rest error-handling spring-boot

我有一个非常简单的@RestController,我正在尝试设置自定义错误消息。但由于某种原因,message错误没有出现。

这是我的控制器:

@RestController
@RequestMapping("openPharmacy")
public class OpenPharmacyController {


    @PostMapping
    public String findNumberOfSurgeries(@RequestBody String skuLockRequest) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "This postcode is not valid");
    }

}
Run Code Online (Sandbox Code Playgroud)

这是我得到的回应:

{
    "timestamp": "2020-06-24T17:44:20.194+00:00",
    "status": 400,
    "error": "Bad Request",
    "message": "",
    "path": "/openPharmacy/"
}
Run Code Online (Sandbox Code Playgroud)

我正在传递一个 JSON,但我没有验证任何东西,我只是想设置自定义消息。如果我更改状态代码,我会在响应中看到它,但message始终为空。

为什么这不像预期的那样工作?这是一个如此简单的例子,我看不出可能遗漏了什么。当我调试代码时,我可以看到错误消息设置了所有字段。但出于某种原因,该消息从未在响应中设置。

np_*_*np_ 64

此答案由用户 Hassan 在对原始问题的评论中提供。我只是将其发布为答案,以提高可见度。

基本上,您需要做的就是添加server.error.include-message=always到您的 application.properties 文件,现在您的消息字段应该被填充。

这种行为在 Spring Boot 2.3 中有所改变,你可以在这里阅读:https : //github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#changes-to-the-default -错误页面内容

  • 我认为设置 `server.error.include-message=always` 可能是一个问题,因为它也会披露内部异常的消息(如 IllegalStateException)! (5认同)
  • @MarkusHettich我同意,这就是为什么你应该始终有一个异常处理程序来捕获异常,然后将错误消息转换为通用的 500 响应。 (3认同)
  • 我喜欢 Spring,但在我看来这是一个错误。 (2认同)

Dan*_*ong 9

对于那些担心使用已接受答案推荐的 application.properties 可能泄露敏感信息的人,我发现该属性还有其他可用选项server.error.include-message

设置server.error.include-message=always将始终包含引发异常的原因,即使该原因可能会暴露有关应用程序的敏感信息。

更好的选择是server.error.include-message=on-param,只有当您通过以下方式显式设置时,它才会包含一条消息ResponseStatusException

if (requestBody.someField == null) {
   throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "someField is required.");
}
Run Code Online (Sandbox Code Playgroud)


Oo.*_*.oO 5

我有同样的问题。如果我使用这个构造

throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Error in update");
Run Code Online (Sandbox Code Playgroud)

我的消息没有通过JSON. 对我来说,绕过它的唯一方法是创建GlobalExceptionHandler

package mypackage;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import java.util.Date;

@ControllerAdvice
public class GlobalExceptionHandler {
  @ExceptionHandler(NotFoundException.class)
  public ResponseEntity<ErrorDTO> generateNotFoundException(NotFoundException ex) {
    ErrorDTO errorDTO = new ErrorDTO();
    errorDTO.setMessage(ex.getMessage());
    errorDTO.setStatus(String.valueOf(ex.getStatus().value()));
    errorDTO.setTime(new Date().toString());

    return new ResponseEntity<ErrorDTO>(errorDTO, ex.getStatus());
  }
}
Run Code Online (Sandbox Code Playgroud)

我也创建了自己的Exception类型

package mypackage;

import org.springframework.http.HttpStatus;

public class NotFoundException extends RuntimeException {

  public NotFoundException(String message) {
    super(message);
  }

  public HttpStatus getStatus() {
    return HttpStatus.NOT_FOUND;
  }
}
Run Code Online (Sandbox Code Playgroud)

有了这个,我就可以从控制器抛出异常并且我得到了正确的结果JSON- 我想看到的消息。

@PutMapping("/data/{id}")
public DataEntity updateData(@RequestBody DataEntity data, @PathVariable int id) {
  throw new NotFoundException("Element not found");
}
Run Code Online (Sandbox Code Playgroud)

我已经向大家介绍ErrorDTO以及

package mypackage;

public class ErrorDTO {
  public String status;
  public String message;
  public String time;

  ...
  ...
  // getters and setters are here 
  ...
  ...
}
Run Code Online (Sandbox Code Playgroud)

更新

正如@Hassan 和@cunhaf 所提到的(在原始问题下的评论中),解决方案是

server.error.include-message=always
Run Code Online (Sandbox Code Playgroud)

ResponseStatusException. 尽管如此,GlobalExceptionHandler如果有人想通过异常传递更多信息,解决方案可能会更好。

源代码

示例可以在这里找到:全局异常处理程序

  • 谢谢,最适合的解决方案 (2认同)