我想实现一个自定义的ResponseBodyAdvice
,它只是查找Page<?>
,然后将总元素的数量添加到响应头。
@ControllerAdvice
public class PageResponseAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return Page.class.isAssignableFrom(returnType.getParameterType());
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
((Page<?>) body).getTotalElements();
...
}
}
问题是:
MappingJacksonValue
body
(在beforeBodyWrite
方法中)有更好的实现方法?/我是不是用错了interceptor?我不想关心包装器类,尽管我只想在beforeBodyWrite
方法中使用未修改的普通Page
对象。
编辑:
我现在只需要extend AbstractMappingJacksonResponseBodyAdvice
。这工作得很好,但感觉不太对。也许还是有人有更好的主意。
下面是Page -> Content-Range Header
的代码
@ControllerAdvice
public class PageResponseAdvice extends AbstractMappingJacksonResponseBodyAdvice {
@Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return super.supports(returnType, converterType) && Page.class.isAssignableFrom(returnType.getParameterType());
}
@Override protected void beforeBodyWriteInternal(MappingJacksonValue bodyContainer, MediaType contentType, MethodParameter returnType, ServerHttpRequest request, ServerHttpResponse response) {
Page<?> page = ((Page<?>) bodyContainer.getValue());
Long from = null;
Long to = null;
if(page.getTotalElements() > 0 && page.getNumberOfElements() > 0) {
from = Integer.valueOf(page.getNumber()).longValue()*page.getSize();
to = from + page.getNumberOfElements() - 1;
}
response.getHeaders().add(
HttpHeaders.CONTENT_RANGE,
ContentRangeEncoder.encode(
"items",
from,
to,
page.getTotalElements()
)
);
response.getHeaders().add(
HttpHeaders.ACCEPT_RANGES,
"items"
);
}
}
(如果有人感兴趣的话。这是ContentRangeEncoder
):
public class ContentRangeEncoder {
private static final Pattern TYPE_PATTERN = Pattern.compile("[a-zA-Z0-9]+");
private static final Predicate<String> TYPE_PATTERN_PREDICATE = TYPE_PATTERN.asPredicate();
public static <T extends Number & Comparable<T>> String encode(String unit, T from, T to, T length) {
StringBuilder sb = new StringBuilder();
if(unit != null) {
Assert.isTrue(TYPE_PATTERN_PREDICATE.test(unit));
sb.append(unit).append(" ");
}
if(from == null && to == null) {
sb.append("*");
} else {
Assert.notNull(from);
Assert.notNull(to);
Assert.isTrue(from.compareTo(to) <= 0);
sb.append(from).append("-").append(to);
}
sb.append("/");
if(length == null) {
sb.append("*");
} else {
Assert.isTrue(to == null || length.compareTo(to) > 0);
sb.append(length);
}
return sb.toString();
}
}
发布于 2018-06-09 04:27:05
至于主体为什么是MappingJacksonValue
类型,这取决于您的配置和特定处理程序方法的返回值。
顺便说一句,WebMvcConfigurationSupport
将JsonViewResponseBodyAdvice
添加到RequestMappingHandlerAdapter
中,如果在调用之前调用此ResponseBodyAdvice
bean,这就解释了主体为什么是MappingJacksonValue
。主体从一个ResponseBodyAdvice
bean传递到下一个bean,每个bean以它认为合适的任何“形式”返回主体。
下面是JsonViewResponseBodyAdvice
的超类'AbstractMappingJacksonResponseBodyAdvice‘的摘录,看看正文发生了什么:
public final Object beforeBodyWrite(@Nullable Object body,
MethodParameter returnType, ..., ..., ..., ...) {
//...
MappingJacksonValue container = getOrCreateContainer(body);
//...
return container;
}
https://stackoverflow.com/questions/28511914
复制相似问题