我希望在Spring引导中自动响应对象为null时返回404。
我需要建议。
我不想在控制器中检查它是否为空。
答案 0 :(得分:4)
您需要多个Spring模块才能实现此目的。基本步骤是:
@ControllerAdvice
并将其转换为HTTP 404
状态代码。第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;
}
}