【问题标题】:Spring ContollerAdvice does not add body to returned errorSpring ContollerAdvice 不会将正文添加到返回的错误中
【发布时间】:2021-09-07 22:01:55
【问题描述】:

我是 spring 新手,我正在尝试找出全局异常处理。我在这里想要实现的是,当使用不存在的主键发出请求时,我想返回一个 HTTP_NO_CONTENT,其正文包括时间戳和所述请求的给定 ID。

这是我的控制器建议

@ControllerAdvice
public class ControllerAdvisor {

    @ExceptionHandler(NoLevelFoundException.class)
    public ResponseEntity<ResponseBody> handleNoLevelFoundException( NoLevelFoundException ex) {
        ex.printStackTrace();

        ResponseBody error = new ResponseBody();
        error.setTime(Timestamp.from(Instant.now()));
        error.setMessage(ex.getMessage());

        return new ResponseEntity<>(error, HttpStatus.NO_CONTENT);
    }
}

这些是我的自定义异常和响应体

public class NoLevelFoundException extends RuntimeException{
    public NoLevelFoundException(int id) {
        super("No level with id " + id + " found!");
    }
}

public class ResponseBody {
    private Timestamp time;
    private String message;

    ...
}

当我通过邮递员向不存在的项目提出请求时,我会收到此信息。

return ResponseEntity.noContent().build(); 我仍然得到正确的状态码,但我找不到任何添加正文的方法。

我也试过这段代码

ResponseBody error = new ResponseBody();
error.setTime(Timestamp.from(Instant.now()));
error.setMessage(ex.getMessage());

return ResponseEntity.status(HttpStatus.NO_CONTENT).body(error);

使用这种样式,我明确添加了正文,但结果仍然相同。正确的 HTTP 状态,但正文为空。

#编辑

这就是我首先抛出错误的方式

第一个请求被 RestContorller 捕获

@RestController
@RequestMapping("/levels")
public class LevelRestApi {

    private ServiceLayer service;

    @Autowired
    public LevelRestApi(ServiceLayer service, LevelRepository repo) {
        this.service = service;
    }

    @GetMapping("/{stage}")
    public Level getLevel(@PathVariable int stage){
        return service.getLevel(stage);
    }
}

调用服务层检查项目是否存在。我在这里抛出错误。

@Service
public class AlienInvadersServiceLayer implements ServiceLayer {

    JpaRepository levelRepository;

    @Autowired
    public AlienInvadersServiceLayer(@Qualifier(value = "levelRepository") JpaRepository levelRepository) {
        this.levelRepository = levelRepository;
    }

    @Override
    public Level getLevel(int levelId) {
        Optional<Level> result = levelRepository.findById(levelId);
        if (result.isPresent()){
            return result.get();
        }
        else {
            throw new NoLevelFoundException(levelId);
        }
    }
}

【问题讨论】:

  • 您需要使用NoLevelFoundException 在您希望@ControllerAdvice 处理错误的地方抛出执行。分享你处理过的代码unexisting item
  • 或者使用@RestControllerAdvice而不是@ControllerAdvice
  • 我都试过了,但都没有。

标签: java spring-boot exception httprequest


【解决方案1】:

问题在于return new ResponseEntity&lt;&gt;(error, HttpStatus.NO_CONTENT); handleNoLevelFoundException 方法。

当您说NO_CONTENT 时,它只是清空您的响应正文并且确实有意义。 我建议改用HttpStatus.NOT_FOUND

所以你的代码应该是这样的

@ExceptionHandler(NoLevelFoundException.class)
public ResponseEntity<ResponseBody> handleNoLevelFoundException( NoLevelFoundException ex) {
    // other code
    return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}

【讨论】:

  • 感谢更改状态解决了问题。你认为在这种情况下 NOT_FOUND 是最好的响应吗,因为当我看到 NOT_FOUND 它通常意味着错误的 HTTP 地址。
  • 是的 NOT_FOUND 在您的情况下是正确的。 HttpStatus.NO_CONTENT 最适合 DELETE 请求,当您真的不期望在响应正文中时。
猜你喜欢
  • 2016-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 2015-01-10
  • 2021-05-30
  • 2016-03-23
  • 1970-01-01
相关资源
最近更新 更多