我正在为我的网络应用程序使用'admin-on-rest'用户界面,它有下一个限制:
注意:jsonServer REST客户端希望API包含一个 响应GET_LIST调用的X-Total-Count标头。价值必须 是集合中的资源总数。这允许 admin-on-rest知道总共有多少页资源, 并建立分页控制。
我通过手动将X-Total-Count标头添加到我的列表返回REST端点来解决了这个问题,如下所示:
response.addHeader("X-Total-Count", String.valueOf(outputList.size()));
但我想知道:如果有一些优雅的方式在Spring自动完成它?我的意思是当某个端点返回JSON-list时,自动添加此标头的值是否正确?
答案 0 :(得分:6)
是的,有! (如果您使用的是4.1或更高版本的弹簧)。
它被称为ResponseBodyAdvice,它使您能够拦截调用(就在写入响应之前,并允许访问原始http响应)。
基本上你需要的是实现这样的控制器建议:
@ControllerAdvice
public class ResourceSizeAdvice implements ResponseBodyAdvice<Collection<?>> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
//Checks if this advice is applicable.
//In this case it applies to any endpoint which returns a collection.
return Collection.class.isAssignableFrom(returnType.getParameterType());
}
@Override
public Collection<?> beforeBodyWrite(Collection<?> body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
response.getHeaders().add("X-Total-Count", String.valueOf(body.size()));
return body;
}
}
答案 1 :(得分:3)
如果您不仅仅需要响应中元素的总数,而只需要PagingAndSortingRepository
的相应JPA方法中的实体总数,您可以执行类似于对分页应用程序有用的操作: )
灵感来自Bohdan的回答(https://stackoverflow.com/a/44376133/986160)
@ControllerAdvice
public class ResourceSizeAdvice implements ResponseBodyAdvice<Page<?>> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
//Checks if this advice is applicable.
//In this case it applies to any endpoint which returns a page.
return Page.class.isAssignableFrom(returnType.getParameterType());
}
@Override
public Page<?> beforeBodyWrite(Page<?> page, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
serverHttpResponse.getHeaders().add("X-Total-Count",String.valueOf(page.getTotalElements()));
return page;
}
}
确保调用默认方法的Pageable版本,因此它会返回Page
而不是List
:
repository.findAll(new PageRequest(0,100));
如果您不使用存储库,则必须执行两个查询:
Select * from ...
和
Select count(*) from ...
并返回一个Wrapper
,其中包含结果列表的内容加上来自计数的总数的总和。然后,您可以更改@ControllerAdvice
课程以期望Wrapper
并从中获取总数并将其放入标题中
答案 2 :(得分:0)
因为您可以从Page获得总元素。所以我已经将标题添加到ResponseEntity
@GetMapping(value = POSTS, headers = "Accept=application/json")
public ResponseEntity<?> getListPost(@RequestParam(required = false, defaultValue = "0") Integer page, @RequestParam(required = false, defaultValue = "25") Integer size) {
// Create pageable
Pageable pageable = new PageRequest(page, size);
Page<Post> pagePost = postService.getPagePost(pageable);
HttpHeaders headers = new HttpHeaders() {
{
add("Access-Control-Expose-Headers", "Content-Range");
add("Content-Range", String.valueOf(pagePost.getTotalElements()));
}
};
// return new ResponseEntity<>(new CommonResponseBody("OK", 200, postList), HttpStatus.OK);
return new ResponseEntity<>(new CommonResponseBody("OK", 200, new LinkedHashMap() {
{
put("data", pagePost.getContent());
}
}), headers, HttpStatus.OK);
}
getPagePost是在存储库中使用Page findAll(可分页可分页)的服务方法。
注意:如果内容范围不适合,请将内容范围更改为X-Total-Count。