Springboot REST API和响应状态的常见做法

时间:2018-11-24 16:04:52

标签: java spring-boot exception-handling

我正在尝试构建我的第一个基于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);
    }
}

现在,我想知道我在代码中使用最简单的结构这一事实:

  1. 控制器
  2. 服务
  3. 存储库

我应该把它扔到哪里?在存储库级别?还是只返回null并在控制器级别抛出异常?会更有效还是不好的做法?

5 个答案:

答案 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());
            } 
            }