我有一个返回一个UserDto
对象的服务方法。但是,在某些情况下,对控制器的请求将返回HTTP状态(而不是200),但服务只能返回null
或UserDto
。
由于服务无法将错误消息传递回控制器,因此将一些业务逻辑移至控制器并直接调用存储库以返回更详细的错误消息是否是错误的做法?
答案 0 :(得分:5)
通过让服务抛出业务异常,您可以做得更好,然后控制器对此做出反应。例如,CustomerService可以抛出`CustomerNotFoundException',而控制器可以将其转换为适当的HTTP状态代码,如下所示:
@ExceptionHandler({ CustomerNotFoundException.class })
public ResponseEntity handleException(CustomerNotFoundException ex, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}
我建议不要将业务逻辑转移到控制器,因为控制器比域逻辑更多地是基础结构组件。另外,考虑添加另一个协议,例如二进制协议,该协议不会使用控制器层。您可能会错过验证或业务规则。
答案 1 :(得分:1)
您还可以使用Spring的@ControllerAdvice
处理此类情况,请看下面的代码。希望这可以帮助您将详细的错误消息返回给控制器。
@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class ApiExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(NoSuchUserException.class)
public ResponseEntity<Object> handleNoSuchPinCodeException(
NoSuchUserException ex) {
ApiError apiError = new ApiError(HttpStatus.NOT_FOUND);
apiError.setErrorMessage(ex.getMessage());
return buildResponseEntity(apiError);
}
private ResponseEntity<Object> buildResponseEntity(ApiError apiError) {
return new ResponseEntity<>(apiError, apiError.getStatus());
}
}
public class NoSuchUserException extends Exception{
public NoSuchUserException (String message) {
super(message);
}
}
public class ApiError {
private HttpStatus status;
private String errorMessage;
private ApiError() {
}
public ApiError(HttpStatus status) {
this();
this.status = status;
}
public ApiError(HttpStatus status, String errorMessage, Throwable ex) {
this();
this.status = status;
this.errorMessage = errorMessage;
}
public HttpStatus getStatus() {
return status;
}
public void setStatus(HttpStatus status) {
this.status = status;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}