有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Spring自动添加“XTotalCount”头

我正在为我的Web应用程序使用“rest上的管理员”UI,它有下一个限制:

Note: The jsonServer REST client expects the API to include a X-Total-Count header in the response to GET_LIST calls. The value must be the total number of resources in the collection. This allows admin-on-rest to know how many pages of resources there are in total, and build the pagination controls.

我通过将X-Total-Count头添加到手动返回REST端点的列表中解决了此问题,如下所示: response.addHeader("X-Total-Count", String.valueOf(outputList.size()));

但我想知道:是否有一些优雅的方式可以在春天自动完成?我的意思是,当某个端点返回JSON列表时,自动添加具有适当值的头


共 (3) 个答案

  1. # 1 楼答案

    因为从页面中可以得到全部元素。所以我给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是一种服务方法,它在存储库中使用PageFindall(Pageable Pageable)

    注意:如果内容范围不适合您,请将其更改为X-Total-Count

  2. # 2 楼答案

    是的,有!(如果您使用的是spring 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;
        }
    }
    
  3. # 3 楼答案

    如果您不想要响应中元素的总数,而是想要相应的JPA方法PagingAndSortingRepository中实体的总数,您可以做一些对分页应用程序有用的事情:)

    受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;
        }
    
    }
    

    确保调用默认方法的可分页版本,如它返回Page而不是List

    repository.findAll(new PageRequest(0,100));
    

    如果不使用存储库,则必须执行两个查询: Select * from ...Select count(*) from ... 并返回一个Wrapper,其中包含结果列表的内容,以及来自count的总数的总和。然后,您可以更改@ControllerAdvice类,以期望您的Wrapper,并从中获取总数,然后将其放在标题中