设置 DEFAULT_VIEW_INCLUSION 具有全局效果,而我们所需要的只是能够序列化 Page 对象。以下代码将为 Page 注册一个序列化程序,并对您的代码进行简单更改:
@Bean
public Module springDataPageModule() {
return new SimpleModule().addSerializer(Page.class, new JsonSerializer<Page>() {
@Override
public void serialize(Page value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject();
gen.writeNumberField("totalElements",value.getTotalElements());
gen.writeNumberField("totalPages", value.getTotalPages());
gen.writeNumberField("number", value.getNumber());
gen.writeNumberField("size", value.getSize());
gen.writeBooleanField("first", value.isFirst());
gen.writeBooleanField("last", value.isLast());
gen.writeFieldName("content");
serializers.defaultSerializeValue(value.getContent(),gen);
gen.writeEndObject();
}
});
}
另一个(可以说更优雅)的解决方案是注册以下 ResponseBodyAdvice。它将确保您的 REST 端点仍将返回 JSON 数组,并设置 HTTP 标头“X-Has-Next-Page”以指示是否有更多数据。优点是:
1)没有额外的计数(*)查询到您的数据库(单个查询)
2) 响应更优雅,因为它返回一个 JSON 数组
/**
* ResponseBodyAdvice to support Spring data Slice object in JSON responses.
* If the value is a slice, we'll write the List as an array, and add a header to the HTTP response
*
* @author blagerweij
*/
@ControllerAdvice
public class SliceResponseBodyAdvice 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 instanceof Slice) {
Slice slice = (Slice) body;
response.getHeaders().add("X-Has-Next-Page", String.valueOf(slice.hasNext()));
return slice.getContent();
}
return body;
}
}