调用 API 时如何逃避空值检查?
How can I escape null check when call a API?
当我在 Spring 中编写 RestController 时,我总是检查对象是否为 null。我怎样才能逃过这个检查?
在下面的示例中,有空检查和后来的 return notFound 或 Http 状态 404。所以我不想一直检查它。
@GetMapping(path = "/api/member/{member-id}")
public ResponseEntity<Member> getMemberById(@PathVariable(name="member-id", required=true) final Long memberId) {
final Member member = memberService.findById(memberId);
if (member != null) {
return ResponseEntity.ok(member);
}
return ResponseEntity.notFound().build();
}
很好。
或者,memberService.findById
可以 return 和 Optional<Member>
代替,然后您可以执行以下操作:
memberService.findById(memberId)
.map(it -> ResponseEntity.ok(member).build())
.orElse(ResponseEntity.notFound().build());
您还可以 "encode" 异常类型中的 return 类型,每当您在数据库 tier/layer 中搜索请求的资源时,如果不存在,您可以抛出它被翻译成 HTTP Not Found
下游的异常——在一些异常处理程序中。在那种情况下,您无需担心控制器中的不同 return 类型——但所有这些魔法也有一些缺点,例如,它不太清楚(对于新手)发生了什么只需检查代码,除非您已经研究了一段时间。
此外,如果您不想重复相同的 null
检查,您可以将其包装在 generic/common 方法中。
虽然您无法避免 null 检查本身,但您可以将其从 Controller 移出到服务中(同样,使用 Optional
)。如果您正在寻找处理负面响应场景的通用策略,我建议使用 Spring 的 RestControllerAdvice
注释,这将为您的所有 API 启用全局异常处理:
让我们首先将检查移至服务并引发自定义异常 MemberNotFoundException
以防未找到记录。
DefaultMemberService.java
public Member findById(final String memberId) {
Optional<Member> member = memberRepository.findById(memberId);
return member.orElseThrow(() -> new MemberNotFoundException("Invalid member Id"));
}
在控制器中,只需调用服务方法,然后return响应。
MemberController.java
@GetMapping(path = "/api/member/{member-id}")
public ResponseEntity<Member> getMemberById(@PathVariable(name="member-id", required=true) final Long memberId) {
return ResponseEntity.ok().body(memberService.findById(memberId));
}
如您所见,我们没有显式处理异常。相反,我们将通过将异常 class 映射到响应(错误消息、响应代码)来让 RestControllerAdvice
为我们做这件事:
ExceptionHandlerControllerAdvice.java
@RestControllerAdvice
public final class ExceptionHandlerControllerAdvice {
@ExceptionHandler({ MemberNotFoundException.class })
@ResponseStatus(HttpStatus.NOT_FOUND)
ResponseEntity<ErrorDto> handleRecordNotFound(MemberNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrorDto(ex.getMessage));
}
}
其中,ErrorDto
(简体)是:
public class ErrorDto {
private String message;
public ErrorDto(String msg) { this.message = msg; }
public String getMessage() { return this.message; }
}
当我在 Spring 中编写 RestController 时,我总是检查对象是否为 null。我怎样才能逃过这个检查?
在下面的示例中,有空检查和后来的 return notFound 或 Http 状态 404。所以我不想一直检查它。
@GetMapping(path = "/api/member/{member-id}")
public ResponseEntity<Member> getMemberById(@PathVariable(name="member-id", required=true) final Long memberId) {
final Member member = memberService.findById(memberId);
if (member != null) {
return ResponseEntity.ok(member);
}
return ResponseEntity.notFound().build();
}
很好。
或者,memberService.findById
可以 return 和 Optional<Member>
代替,然后您可以执行以下操作:
memberService.findById(memberId)
.map(it -> ResponseEntity.ok(member).build())
.orElse(ResponseEntity.notFound().build());
您还可以 "encode" 异常类型中的 return 类型,每当您在数据库 tier/layer 中搜索请求的资源时,如果不存在,您可以抛出它被翻译成 HTTP Not Found
下游的异常——在一些异常处理程序中。在那种情况下,您无需担心控制器中的不同 return 类型——但所有这些魔法也有一些缺点,例如,它不太清楚(对于新手)发生了什么只需检查代码,除非您已经研究了一段时间。
此外,如果您不想重复相同的 null
检查,您可以将其包装在 generic/common 方法中。
虽然您无法避免 null 检查本身,但您可以将其从 Controller 移出到服务中(同样,使用 Optional
)。如果您正在寻找处理负面响应场景的通用策略,我建议使用 Spring 的 RestControllerAdvice
注释,这将为您的所有 API 启用全局异常处理:
让我们首先将检查移至服务并引发自定义异常 MemberNotFoundException
以防未找到记录。
DefaultMemberService.java
public Member findById(final String memberId) {
Optional<Member> member = memberRepository.findById(memberId);
return member.orElseThrow(() -> new MemberNotFoundException("Invalid member Id"));
}
在控制器中,只需调用服务方法,然后return响应。
MemberController.java
@GetMapping(path = "/api/member/{member-id}")
public ResponseEntity<Member> getMemberById(@PathVariable(name="member-id", required=true) final Long memberId) {
return ResponseEntity.ok().body(memberService.findById(memberId));
}
如您所见,我们没有显式处理异常。相反,我们将通过将异常 class 映射到响应(错误消息、响应代码)来让 RestControllerAdvice
为我们做这件事:
ExceptionHandlerControllerAdvice.java
@RestControllerAdvice
public final class ExceptionHandlerControllerAdvice {
@ExceptionHandler({ MemberNotFoundException.class })
@ResponseStatus(HttpStatus.NOT_FOUND)
ResponseEntity<ErrorDto> handleRecordNotFound(MemberNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrorDto(ex.getMessage));
}
}
其中,ErrorDto
(简体)是:
public class ErrorDto {
private String message;
public ErrorDto(String msg) { this.message = msg; }
public String getMessage() { return this.message; }
}