Spring MVC ResponseBodyAdvice 用于在指定 return 类型中添加 header

Spring MVC ResponseBodyAdvice for add header in specify return type

我的控制器中有一个方法 return object 列表。 该方法支持分页结果,在HttpHeader中添加HttpHeaders.LINK以支持Pagination Discoverability。 我被迫添加此行以支持 . 我认为也许 ControllerAdvice 或 ResponseAdvice 支持在那做这件事。 我如何检查 return 方法?如果 return 类型是 QueryResult 则向其添加 HttpHeader?

@RequestMapping(value = "/list", method = RequestMethod.GET)
    public ResponseEntity<QueryResult<Personel>> search(
            SearchOption searchOption)  {
        QueryResult<Personel> list=ipersonelService.search();
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(list, "/api/personel");
        return new ResponseEntity<>(list, headers, HttpStatus.OK);
    } 

这个class通过分页生成Headersclass

public static HttpHeaders generatePaginationHttpHeaders(QueryResult page, String baseUrl)
    throws URISyntaxException {

    HttpHeaders headers = new HttpHeaders();
    headers.add("X-Total-Count", "" + page.getTotalElements());
    String link = "";
    if ((page.getPageNumber() + 1) < page.getTotalPages()) {
        link = "<" + generateUri(baseUrl, page.getPageNumber() + 1, page.getPageSize()) + ">; rel=\"next\",";
    }
    // prev link
    if ((page.getPageNumber()) > 0) {
        link += "<" + generateUri(baseUrl, page.getPageNumber() - 1, page.getPageSize()) + ">; rel=\"prev\",";
    }
    // last and first link
    int lastPage = 0;
    if (page.getTotalPages() > 0) {
        lastPage = page.getTotalPages() - 1;
    }
    link += "<" + generateUri(baseUrl, lastPage, page.getPageSize()) + ">; rel=\"last\",";
    link += "<" + generateUri(baseUrl, 0, page.getPageSize()) + ">; rel=\"first\"";
    headers.add(HttpHeaders.LINK, link);
    return headers;
}


private static String generateUri(String baseUrl, int page, int size) throws URISyntaxException {
        return UriComponentsBuilder.fromUriString(baseUrl).queryParam("page", page).queryParam("size", size).toUriString();
    }



public class QueryResult<T> {

    private int     pageNumber;
    private int     totalElements;
    private int     totalPages;
    private int     pageSize;

    @JsonProperty("rows")
    private List<T> items;

    public QueryResult() {

    }   

    public int getPageNumber() {
        return pageNumber;
    }

    public void setPageNumber(int pageNumber) {
        this.pageNumber = pageNumber;
    }

    public int getTotalElements() {
        return totalElements;
    }

    public void setTotalElements(int totalElements) {
        this.totalElements = totalElements;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public List<T> getItems() {
        return items;
    }

    public void setItems(List<T> items) {
        this.items = items;
    }

    public int getTotalPages() {
        if (this.getPageSize() > 0)
            return this.getTotalElements() / this.getPageSize();

        return 0;
    }

    public void setTotalPages(int totalPages) {
        this.totalPages = totalPages;
    }

}

我想写这样的方法并自动添加link headers

@RequestMapping(value = "/list", method = RequestMethod.GET)
        public QueryResult<Personel> search(
                SearchOption searchOption)  {
            return ripersonelService.search();
        } 

经过搜索我找到了这个解决方案

@ControllerAdvice
public class BaseController implements ResponseBodyAdvice<Object> {


    private final Logger logger = Logger.getLogger(BaseController.class);

    @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 QueryResult){
            QueryResult result =(QueryResult) body;
            HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(result, request.getURI().getPath());
            response.getHeaders().add(HttpHeaders.LINK, headers.getFirst(HttpHeaders.LINK));
            response.getHeaders().add("X-Total-Count", headers.getFirst("X-Total-Count"));
        }

        return body;
    }
}

您可以使用 ResponseBodyAdvice (typically also annotated with @ControllerAdvice). Your implementation's beforeBodyWrite method will be called with the response body and the ServerHttpResponse 的实现。后者使您可以访问响应 headers 并允许您根据需要更新它们。