春季引导休息相当新,并且对使用该服务处理客户端响应的方式和最佳方式有疑问。目前,我有以下控制器代码来处理在数据库查询中找不到记录的情况:
@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条件。
答案 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));
}