每个空响应返回404

时间:2017-05-10 09:05:18

标签: http spring-boot httpresponse

我希望在Spring引导中自动响应对象为null时返回404。

我需要建议。

我不想在控制器中检查它是否为空。

3 个答案:

答案 0 :(得分:4)

您需要多个Spring模块才能实现此目的。基本步骤是:

  1. 声明一个异常类,当存储库方法未返回预期值时,该异常类可用于引发异常。
  2. 添加捕获自定义异常的@ControllerAdvice并将其转换为HTTP 404状态代码。
  3. 添加一个AOP建议,拦截存储库方法的返回值,并在找到与期望值不匹配的值时引发自定义异常。
  4.   

    第1步:异常类

    public class ResourceNotFoundException extends RuntimeException {}
    
      

    第2步:控制器建议

    @ControllerAdvice
    public class ResourceNotFoundExceptionHandler
    {
      @ExceptionHandler(ResourceNotFoundException.class)
      @ResponseStatus(HttpStatus.NOT_FOUND)
      public void handleResourceNotFound() {}
    }
    
      

    第3步:AspectJ建议

    @Aspect
    @Component
    public class InvalidRepositoryReturnValueAspect
    {
      @AfterReturning(pointcut = "execution(* org.example.data.*Repository+.findOne(..))", returning = "result")
      public void intercept(final Object result)
      {
        if (result == null)
        {
          throw new ResourceNotFoundException();
        }
      }
    }
    

    示例应用程序on Github可用于演示所有这些操作。使用像Postman for Google Chrome这样的REST客户端来添加一些记录。然后,尝试通过其标识符获取现有记录将正确返回记录,但尝试通过不存在的标识符获取记录将返回404

答案 1 :(得分:1)

在Spring中执行此操作的最简单方法是编写自己的异常类,如下所示

@ResponseStatus(value = HttpStatus.NOT_FOUND)
class ResourceNotFoundException extends RuntimeException{
}

然后从任何地方抛出ResourceNotFoundException。

if (something == null) throw new ResourceNotFoundException();

了解更多 - > Read

答案 2 :(得分:1)

与@manish的答案(https://stackoverflow.com/a/43891952/986160)类似,但是没有AspectJ切入点,而是使用了另一个@ControllerAdvice

  

步骤1: NotFoundException类:

public class NotFoundException extends RuntimeException {
    public NotFoundException(String msg) {
        super(msg);
    }
    public NotFoundException() {}
}
  

步骤2:检查端点中返回的正文是否为null并抛出NotFoundException:

@ControllerAdvice
public class NotFoundAdvice implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    @Override
    @SuppressWarnings("unchecked")
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body == null) {
            throw new NotFoundException("resource not found");
        }
        return body;
    }
}
  

步骤3:处理NotFoundException并使响应的状态为404

@ControllerAdvice
public class GlobalExceptionAdvice {

    @Data
    public class ErrorDetails {
        private Date timestamp;
        private String message;
        private String details;

        public ErrorDetails(Date timestamp, String message, String details) {
            super();
            this.timestamp = timestamp;
            this.message = message;
            this.details = details;
        }
    }

    @ExceptionHandler(NotFoundException.class)
    public final ResponseEntity<ErrorDetails> notFoundHandler(Exception ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(),
                request.getDescription(false));
        return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
    }
}
  

替代步骤3:

您可以用NotFoundException注释@ResponseStatus并覆盖fillInStackTrace()(来自https://stackoverflow.com/a/31263942/986160),以使其与GlobalExceptionAdvice类似,而不会像这样显示stacktrace:

@ResponseStatus(value = HttpStatus.NOT_FOUND,reason =  "resource not found")
public class NotFoundException extends RuntimeException {
    public NotFoundException(String msg) {
        super(msg);
    }
    public NotFoundException() {}

    @Override
    public synchronized Throwable fillInStackTrace() {
        return this;
    }
}