我正在尝试构建我的第一个基于spring boot的rest api,并且试图了解在找不到资源的情况下返回404的常用做法。
首先,我不知道是否应该考虑不将资源视为“异常事件”还是只是通常发生的事情而我的应用程序应该经常处理。
我发现的大多数解决方案都建议使用带注释的异常,该异常告诉处理程序在找不到资源的情况下返回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);
}
}
现在,我想知道我在代码中使用最简单的结构这一事实:
我应该把它扔到哪里?在存储库级别?还是只返回null并在控制器级别抛出异常?会更有效还是不好的做法?
答案 0 :(得分:1)
返回错误的方式与API紧密相关,而服务代码应与API无关。换句话说,如果出于某种原因需要在REST API旁边添加SOAP API,则服务代码应该能够为这两个API提供服务。因此,任何与API紧密耦合的事物都应在实现API的层(在本例中为您的控制器层)中进行处理。
在我目前的工作地点,我们检查财务主任中正在执行的资源是否存在。由于我们使用的是Hibernate,因此一旦从数据库中检索到实体,该实体将在会话期间保留在会话缓存中,并且如果您选择不向下传递实体,则不会在服务层中第二次检索时产生额外的费用服务。
在SpringBoot中,org.springframework.data.rest.webmvc.ResourceNotFoundException绑定到404 NOT_FOUND。因此,您无需为API实现任何类型的异常处理程序即可返回带有404 http状态代码的响应。
答案 1 :(得分:1)
最佳实践是将异常从服务抛出到控制器,并使用@RestControllerAdvice
类中的正确HttpStatus处理该异常。
例如
从服务类抛出异常到控制器
@Service
public class ResourceServiceImpl implements ResourceService {
@Override
public void findById(String id) throws ResourceNotFoundException{
throw new ResourceNotFoundException("your_error_code", "msg");
}
}
ControllerAdvice类示例,用于处理异常并使用HTTP状态和定义的ErrorResponse类对象作为JSON发送其余API的响应。
@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());
}
}
答案 2 :(得分:0)
您应该在控制器中抛出异常。
答案 3 :(得分:0)
假设您使用的是Spring Boot的最新版本,则最佳实践是在Service中引发异常,因为您可以找到一个实体。
@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)));
}
}
答案 4 :(得分:0)
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());
}
}