Pav*_*uri 8 java spring pagination json spring-mvc
我在我的REST控制器中使用Spring数据分页并返回Paged实体.我想在JSONViews的帮助下控制作为JSON返回的数据.
当我返回一个对象时,我能够实现结果.但是当我返回Page时,我收到空白的JSON作为回复.
以下是我的方法签名.
@JsonView(TravelRequestView.MyRequests.class)
@RequestMapping("/travel/requests")
public Page<TravelRequest> getUserTravelRequests(
@RequestParam("ps") int pageSize, @RequestParam("p") int page,
@RequestParam(defaultValue = "", value = "q") String searchString)
Run Code Online (Sandbox Code Playgroud)
我删除@JsonView注释时能够收到响应.
Nar*_*mha 10
如果您使用的是spring-boot,那么另一个更简单的解决方案是将以下内容添加到application.yml中
spring:
jackson:
mapper:
DEFAULT_VIEW_INCLUSION: true
Run Code Online (Sandbox Code Playgroud)
或application.properties
spring.jackson.mapper.DEFAULT_VIEW_INCLUSION=true
Run Code Online (Sandbox Code Playgroud)
使用这种方法,我们的优势是保留了ObjectMapperSpring容器的托管,而不是创建一个新的ObjectMapper.因此,一旦我们使用spring管理的ObjectMapper,我们定义的任何Custom Serialzers仍将继续工作,例如CustomDateSerialzer
参考:http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html
设置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();
}
});
}
Run Code Online (Sandbox Code Playgroud)
另一个(可以说是更优雅的)解决方案是注册以下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;
}
}
Run Code Online (Sandbox Code Playgroud)
我实际上找到了一种更简单、更好的方法来做到这一点。我遇到的问题是我无法在收到的 Page 对象上设置 @JsonView 注释。因此,我创建了 Page 接口的实现并向其中添加了 JsonView。我现在返回的是 MyPage,而不是返回 Page
public class MyPage<T> implements Page<T> {
private Page<T> pageObj;
public MyPage(Page<T> pageObj) {
this.pageObj = pageObj;
}
@JsonView(PaginatedResult.class)
@Override
public int getNumber() {
return pageObj.getNumber();
}
@Override
public int getSize() {
return pageObj.getSize();
}
@JsonView(PaginatedResult.class)
@Override
public int getNumberOfElements() {
return pageObj.getNumberOfElements();
}
@JsonView(PaginatedResult.class)
@Override
public List<T> getContent() {
return pageObj.getContent();
}
@Override
public boolean hasContent() {
return pageObj.hasContent();
}
@Override
public Sort getSort() {
return pageObj.getSort();
}
@JsonView(PaginatedResult.class)
@Override
public boolean isFirst() {
return pageObj.isFirst();
}
@JsonView(PaginatedResult.class)
@Override
public boolean isLast() {
return pageObj.isLast();
}
@Override
public boolean hasNext() {
return pageObj.hasNext();
}
@Override
public boolean hasPrevious() {
return pageObj.hasPrevious();
}
@Override
public Pageable nextPageable() {
return pageObj.nextPageable();
}
@Override
public Pageable previousPageable() {
return pageObj.previousPageable();
}
@Override
public Iterator<T> iterator() {
return pageObj.iterator();
}
@JsonView(PaginatedResult.class)
@Override
public int getTotalPages() {
return pageObj.getTotalPages();
}
@JsonView(PaginatedResult.class)
@Override
public long getTotalElements() {
return pageObj.getTotalElements();
}
}
Run Code Online (Sandbox Code Playgroud)
尝试使用下面的代码,
@Configuration
public class MyInterceptorConfig extends WebMvcConfigurerAdapter{
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper() {
private static final long serialVersionUID = 1L;
@Override
protected DefaultSerializerProvider _serializerProvider(SerializationConfig config) {
// replace the configuration with my modified configuration.
// calling "withView" should keep previous config and just add my changes.
return super._serializerProvider(config.withView(TravelRequestView.MyRequests.class));
}
};
mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
converter.setObjectMapper(mapper);
converters.add(converter);
}
Run Code Online (Sandbox Code Playgroud)
虽然我不想因此而获得功劳,但这是来自的参考
它将检索实体的所有用 jsonview (TravelRequestView.MyRequests.class) 注释的变量以及所有未用 jsonview 注释的变量。如果您不想要对象的某些属性,请使用不同的视图进行注释。
| 归档时间: |
|
| 查看次数: |
4344 次 |
| 最近记录: |