Spring Boot rest apis和Response status常见做法
Springboot rest apis and Response statusses common practices
我正在尝试构建我的第一个 spring 基于引导的 rest api 并且我正在尝试了解用于 return 404 的常见做法是什么没有找到。
首先,我不知道我是否应该考虑不寻找 "exceptional event" 资源,或者只是经常发生并且我的应用程序应该经常处理的事情。
我发现的大多数解决方案都建议使用带注释的异常,告诉处理程序在找不到资源的情况下 return 404。
例如:
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Resource not found")
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException() {
super();
}
public ResourceNotFoundException(String message, Throwable cause) {
super(message, cause);
}
public ResourceNotFoundException(String message) {
super(message);
}
public ResourceNotFoundException(Throwable cause) {
super(cause);
}
}
现在我想知道,考虑到我使用最简单的代码结构这一事实:
- 控制器
- 服务
- 存储库
我应该把它扔到哪里?在存储库级别?或者只是 return null 并在控制器级别抛出异常?那会更有效率还是只是一种不好的做法?
您应该在控制器中抛出异常。
假设您使用的是 spring 引导的最新版本,因此最佳做法是在服务中抛出异常,因为您是否可以找到实体。
@Service
public class EntityService {
@Autowired
private EntityRepository repository;
public Entity findById (Long id) {
return repository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException(String.format("Entity not found with id %d", id)));
}
}
您 return 错误的方式与您的 API 紧密相关,而您的服务代码应该 API 不可知。换句话说,如果您出于某种原因需要在 REST API 旁边添加 SOAP API,则服务代码应该能够为这两个 API 提供服务。因此,任何与 API 紧密耦合的东西都应该在实现 API 的层中处理,在本例中是您的控制器层。
在我目前的工作地点,我们检查控制器中是否存在正在处理的资源。由于我们使用 Hibernate,一旦从数据库中检索到实体,它就会在会话期间保留在会话缓存中,并且如果您选择不向下传递实体,则不会产生在服务层中进行第二次检索的额外成本到服务。
在SpringBoot中,org.springframework.data.rest.webmvc.ResourceNotFoundException绑定到404NOT_FOUND。因此,您不需要为 API 到 return 具有 404 http 状态代码的响应实现任何类型的异常处理程序。
最佳做法是将异常从服务抛出到控制器,并在 @RestControllerAdvice
class.
中使用适当的 HttpStatus 处理异常
例如
从服务 class 向控制器
抛出异常
@Service
public class ResourceServiceImpl implements ResourceService {
@Override
public void findById(String id) throws ResourceNotFoundException{
throw new ResourceNotFoundException("your_error_code", "msg");
}
}
ControllerAdvice class 示例来处理异常并发送响应 API 以及您的 HTTP 状态和您定义的 ErrorResponse class 对象 JSON。
@RestControllerAdvice
public class ErrorHandler {
@ExceptionHandler(value = { ResourceNotFoundException.class })
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public ErrorResponse handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
logger.error("Handling resource not found exception ", ex);
return new ErrorResponse(ex.getCode(), ex.getMessage());
}
}
ResponseEntityExceptionHandler is the default implementation of Spring for handling of various error .In order to customize the error, override the method.
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(value = { ResourceNotFoundException.class })
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public ErrorResponse handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
logger.error("Handling resource not found exception ", ex);
return new ErrorResponse(ex.getCode(), ex.getMessage());
}
}
我正在尝试构建我的第一个 spring 基于引导的 rest api 并且我正在尝试了解用于 return 404 的常见做法是什么没有找到。
首先,我不知道我是否应该考虑不寻找 "exceptional event" 资源,或者只是经常发生并且我的应用程序应该经常处理的事情。
我发现的大多数解决方案都建议使用带注释的异常,告诉处理程序在找不到资源的情况下 return 404。
例如:
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Resource not found")
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException() {
super();
}
public ResourceNotFoundException(String message, Throwable cause) {
super(message, cause);
}
public ResourceNotFoundException(String message) {
super(message);
}
public ResourceNotFoundException(Throwable cause) {
super(cause);
}
}
现在我想知道,考虑到我使用最简单的代码结构这一事实:
- 控制器
- 服务
- 存储库
我应该把它扔到哪里?在存储库级别?或者只是 return null 并在控制器级别抛出异常?那会更有效率还是只是一种不好的做法?
您应该在控制器中抛出异常。
假设您使用的是 spring 引导的最新版本,因此最佳做法是在服务中抛出异常,因为您是否可以找到实体。
@Service
public class EntityService {
@Autowired
private EntityRepository repository;
public Entity findById (Long id) {
return repository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException(String.format("Entity not found with id %d", id)));
}
}
您 return 错误的方式与您的 API 紧密相关,而您的服务代码应该 API 不可知。换句话说,如果您出于某种原因需要在 REST API 旁边添加 SOAP API,则服务代码应该能够为这两个 API 提供服务。因此,任何与 API 紧密耦合的东西都应该在实现 API 的层中处理,在本例中是您的控制器层。
在我目前的工作地点,我们检查控制器中是否存在正在处理的资源。由于我们使用 Hibernate,一旦从数据库中检索到实体,它就会在会话期间保留在会话缓存中,并且如果您选择不向下传递实体,则不会产生在服务层中进行第二次检索的额外成本到服务。
在SpringBoot中,org.springframework.data.rest.webmvc.ResourceNotFoundException绑定到404NOT_FOUND。因此,您不需要为 API 到 return 具有 404 http 状态代码的响应实现任何类型的异常处理程序。
最佳做法是将异常从服务抛出到控制器,并在 @RestControllerAdvice
class.
例如
从服务 class 向控制器
抛出异常@Service
public class ResourceServiceImpl implements ResourceService {
@Override
public void findById(String id) throws ResourceNotFoundException{
throw new ResourceNotFoundException("your_error_code", "msg");
}
}
ControllerAdvice class 示例来处理异常并发送响应 API 以及您的 HTTP 状态和您定义的 ErrorResponse class 对象 JSON。
@RestControllerAdvice
public class ErrorHandler {
@ExceptionHandler(value = { ResourceNotFoundException.class })
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public ErrorResponse handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
logger.error("Handling resource not found exception ", ex);
return new ErrorResponse(ex.getCode(), ex.getMessage());
}
}
ResponseEntityExceptionHandler is the default implementation of Spring for handling of various error .In order to customize the error, override the method.
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(value = { ResourceNotFoundException.class })
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public ErrorResponse handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
logger.error("Handling resource not found exception ", ex);
return new ErrorResponse(ex.getCode(), ex.getMessage());
}
}