Spring ContollerAdvice 没有将正文添加到返回的错误中

Spring ContollerAdvice does not add body to returned error

我是 spring 的新手,我正在尝试了解全局异常处理。我想在这里实现的是当使用不存在的主键发出请求时,我想 return 一个 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);
    }
}

这些是我的自定义异常和 respondBody

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);
        }
    }
}

问题出在 return new ResponseEntity<>(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);
}