春季引导休息ResponseEntity响应

时间:2017-11-15 15:26:47

标签: spring rest spring-boot

春季引导休息相当新,并且对使用该服务处理客户端响应的方式和最佳方式有疑问。目前,我有以下控制器代码来处理在数据库查询中找不到记录的情况:

@PreAuthorize("hasAuthority('ROLE_USER')")
@GetMapping("distance/{id}")
public ResponseEntity<?> getDistanceById(@PathVariable("id") Integer id) {
    log.info("getDistanceById");
    Distance distance = distanceService.getDistanceById(id);
    if (distance == null){
        return new ResponseEntity<CustomErrorMsg>(new CustomErrorMsg("Distance ID " + id + " Not Found"),HttpStatus.NOT_FOUND);
    }
    return new ResponseEntity<Distance>(distance, HttpStatus.OK);
}

其中CustomErrorMsg是一个在其构造函数中设置String的简单类。

这是最好的方法吗?基于ControllerAdvice的类会更好吗?提出这个问题是因为上面的代码在未经许可的情况下被cient调用时发送了预期的403响应。想了解它是如何发生的,以及它是否可以用于NOT FOUND条件。

2 个答案:

答案 0 :(得分:0)

“未找到资源”是一个众所周知的用例,您不必为ResponseEntity或ControllerAdvice“烦恼”。您只需使用ResourceNotFoundException

@PreAuthorize("hasRole('USER')")
@GetMapping("distance/{id}")
public Distance getDistanceById(@PathVariable("id") Integer id) {
    log.info("getDistanceById");
    Distance distance = distanceService.getDistanceById(id);
    if (distance == null) {
        throw new ResourceNotFoundException("Distance ID " + id + " Not Found");
    }

    return distance;
}

ResponseEntity<?>声明为返回类型是正确的,但不会传达太多信息,因为您将实际数据和错误消息放在同一级别上。如果像我一样,您更喜欢使用ResponseEntity静态构建器,请转到:

@PreAuthorize("hasRole('USER')")
@GetMapping("distance/{id}")
public ResponseEntity<Distance> getDistanceById(@PathVariable("id") Integer id) {
    log.info("getDistanceById");
    Distance distance = distanceService.getDistanceById(id);
    if (distance == null){
        throw new ResourceNotFoundException("Distance ID " + id + " Not Found");
    }

    return new ResponseEntity.ok(distance);
}

同样,你感兴趣的是一个距离(你的代码可能位于一个名为DistanceController的类中),所以我们不要强调什么时候找不到它。

现在,关于HTTP状态。 如果您请求权限不足的/distance/<id>,您将获得访问拒绝(403 Forbidden),这与未知资源(404 Not Found)不同 - 即抛出ResourceNotFoundException时返回的状态。

此处,首先检查访问请求的URL的权限。如果用户通过权限不足进行身份验证,则会收到403错误。它不是,你可以自由地去获取所请求的资源(200),除非它不存在(404)。

答案 1 :(得分:0)

我建议使用RestControllerAdvice带注释的类(例如名为GlobalExceptionHandler)来处理错误情况。当distance为null时,您需要更改getDistanceById方法以抛出自定义异常。您需要向GlobalExceptionHandler添加一个方法,该方法将处理您的自定义异常。然后您可以将代码更改为以下内容:

@PreAuthorize("hasAuthority('ROLE_USER')")
@GetMapping("distance/{id}")
public ResponseEntity<Distance> getDistanceById(@PathVariable("id") Integer id) {
    log.info("getDistanceById");
    return ResponseEntity.ok(distanceService.getDistanceById(id));
}