Return 每个空响应 404
Return 404 for every null response
我想 return 404 当响应对象为 null 时在 spring 启动时自动为每个响应自动响应。
我需要建议。
我不想检查控制器中的对象是否为空。
在 Spring 中执行此操作的最简单方法是编写您自己的异常 class,如下所示
@ResponseStatus(value = HttpStatus.NOT_FOUND)
class ResourceNotFoundException extends RuntimeException{
}
然后从任何地方抛出 ResourceNotFoundException。
if (something == null) throw new ResourceNotFoundException();
更多 -> Read
您需要多个 Spring 模块才能完成此任务。基本步骤是:
- 声明一个异常 class,可用于在存储库方法未 return 预期值时抛出异常。
- 添加一个
@ControllerAdvice
来捕获自定义异常并将其转换为 HTTP 404
状态代码。
- 添加拦截 return 存储库方法值的 AOP 建议,并在发现值不符合预期时引发自定义异常。
Step 1: Exception class
public class ResourceNotFoundException extends RuntimeException {}
Step 2: Controller advice
@ControllerAdvice
public class ResourceNotFoundExceptionHandler
{
@ExceptionHandler(ResourceNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public void handleResourceNotFound() {}
}
Step 3: AspectJ advice
@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 这样的 REST 客户端为 Google Chrome 添加一些记录。然后,尝试通过其标识符获取现有记录将 return 正确记录,但尝试通过不存在的标识符获取记录将 return 404
.
类似于@manish 的回答 (),但没有 AspectJ 切入点,而是使用另一个 @ControllerAdvice
:
Step 1: NotFoundException class:
public class NotFoundException extends RuntimeException {
public NotFoundException(String msg) {
super(msg);
}
public NotFoundException() {}
}
Step 2: Check if body returned in endpoint is null and throw 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;
}
}
Step 3: handle NotFoundException and make the response have a status of 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);
}
}
Alternative to Step 3:
您可以只用 @ResponseStatus
注释您的 NotFoundException
并覆盖 fillInStackTrace()
(来自 ),以便它具有与 GlobalExceptionAdvice
类似的效果并且不会'像这样显示堆栈跟踪:
@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;
}
}
不需要抛出异常,现在 ResponseBodyAdvice
就可以了:
@ControllerAdvice
public class NullTo404 implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
if (body == null) {
response.setStatusCode(HttpStatus.NOT_FOUND);
}
return body;
}
}
同样,您可以实现ResponseBodyAdvice<Optional<?>>
,并在设置响应状态之前检查Optional.isEmpty()
。它具有与 CrudRepository
很好地协同工作的额外好处。大多数控制器方法最终都是这样结束的:
public Optional<Product> getProductBySku(@PathVariable String sku) {
// logic goes here...
return productRepository.findBySku(sku);
}
我想 return 404 当响应对象为 null 时在 spring 启动时自动为每个响应自动响应。
我需要建议。
我不想检查控制器中的对象是否为空。
在 Spring 中执行此操作的最简单方法是编写您自己的异常 class,如下所示
@ResponseStatus(value = HttpStatus.NOT_FOUND)
class ResourceNotFoundException extends RuntimeException{
}
然后从任何地方抛出 ResourceNotFoundException。
if (something == null) throw new ResourceNotFoundException();
更多 -> Read
您需要多个 Spring 模块才能完成此任务。基本步骤是:
- 声明一个异常 class,可用于在存储库方法未 return 预期值时抛出异常。
- 添加一个
@ControllerAdvice
来捕获自定义异常并将其转换为 HTTP404
状态代码。 - 添加拦截 return 存储库方法值的 AOP 建议,并在发现值不符合预期时引发自定义异常。
Step 1: Exception class
public class ResourceNotFoundException extends RuntimeException {}
Step 2: Controller advice
@ControllerAdvice
public class ResourceNotFoundExceptionHandler
{
@ExceptionHandler(ResourceNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public void handleResourceNotFound() {}
}
Step 3: AspectJ advice
@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 这样的 REST 客户端为 Google Chrome 添加一些记录。然后,尝试通过其标识符获取现有记录将 return 正确记录,但尝试通过不存在的标识符获取记录将 return 404
.
类似于@manish 的回答 (@ControllerAdvice
:
Step 1: NotFoundException class:
public class NotFoundException extends RuntimeException {
public NotFoundException(String msg) {
super(msg);
}
public NotFoundException() {}
}
Step 2: Check if body returned in endpoint is null and throw 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;
}
}
Step 3: handle NotFoundException and make the response have a status of 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);
}
}
Alternative to Step 3:
您可以只用 @ResponseStatus
注释您的 NotFoundException
并覆盖 fillInStackTrace()
(来自 GlobalExceptionAdvice
类似的效果并且不会'像这样显示堆栈跟踪:
@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;
}
}
不需要抛出异常,现在 ResponseBodyAdvice
就可以了:
@ControllerAdvice
public class NullTo404 implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
if (body == null) {
response.setStatusCode(HttpStatus.NOT_FOUND);
}
return body;
}
}
同样,您可以实现ResponseBodyAdvice<Optional<?>>
,并在设置响应状态之前检查Optional.isEmpty()
。它具有与 CrudRepository
很好地协同工作的额外好处。大多数控制器方法最终都是这样结束的:
public Optional<Product> getProductBySku(@PathVariable String sku) {
// logic goes here...
return productRepository.findBySku(sku);
}