如何在 web 服务响应中将 json 响应作为块返回?

Posted

技术标签:

【中文标题】如何在 web 服务响应中将 json 响应作为块返回?【英文标题】:How to return json response as chunks in webservice response? 【发布时间】:2020-09-12 22:51:38 【问题描述】:

我有一个简单的Spring REST Web 服务端点,它将myqsl 查询的结果公开为json

@RestController
public class DbController 
    @GetMapping(produces = APPLICATION_JSON_VALUE)
    public List<Map<String, Object>> query() 
        return crudRepository.queryForList(sql);
    

问题:对于返回 500k 个对象(意味着:行)的大型查询,这会消耗大量内存。

有什么方法可以将“部分”json 结果写入响应流?

【问题讨论】:

你可以考虑实现一个分页。 部分是指限制返回的行数还是限制每行的列数? 我不想限制任何事情。我只是想以块的形式写出某种“部分 json”响应,所以我不必一次序列化所有行(每行一个 json 对象)。从而减少了内存负载。 无论如何,对于如此大的数据集,您将需要一些限制,您可以实现分页并获得行数。然后您可以在 JS 中发送一些脚本,例如如果您有 100 000 行5 个请求,每个请求将返回 20 000 个 但是js客户端必须提前知道行数。这是不可能的,因为我的 sql 总是返回不同的行数。 【参考方案1】:

您可以使用Pagination 为每个请求的客户端创建一个数据块。

你可以这样做:

存储库:

@Repository
    public interface SomethingRepository extends PagingAndSortingRepository<Something, Long> 
        Page<Something> findByMember_Id(Long memberId, Pageable pageable);
    

SomethingPageDto:

public class SomethingPageDto

    @JsonProperty("favourite_list")
    private List<SomethingDto> somethings= new ArrayList<>();

    @JsonProperty("total_pages")
    private int totalPages;

    @JsonProperty("current_page")
    private int currentPage;

    @JsonProperty("total_elements")
    private Long totalElements;

    @JsonProperty("current_page_elements")
    private int currentPageElement;
    

服务:

@Autowired
private SomethingRepository repository;

public SomethingPageDTO getSomething(int pageNo, int pageSize, Long memberId) throws Exception 

Pageable paging = new PageRequest(pageNo, pageSize);

Page<Something> somethingPage = repository.findByMember_Id(memberId, paging);

//map EntityList to DTO

List<SomethingPageDTO > somethingDtos = new ArrayList<>();
return somethingDtos = somethingPage.getContent();
                       //somethingPage.getTotalElements();
                       //somethingPage.getTotalPages();

控制器:

@RestController
@RequestMapping("/some")
public class EmployeeController 

    @Autowired
    somethingService service;

    @GetMapping
    public ResponseEntity<List<Something>> getAll(
                        @RequestParam Integer pageNo, 
                        @RequestParam Integer pageSize,
                        @RequestParam Long memberId

    
        List<somethingDto> list = service.getSomething(pageNo, pageSize, memberId);

        return new ResponseEntity<List<SomethingDto>>(list, new HttpHeaders(), HttpStatus.OK); 
    

更多资源:

https://dzone.com/articles/pagination-in-springboot-applications

https://howtodoinjava.com/spring-boot2/pagination-sorting-example/

https://www.baeldung.com/rest-api-pagination-in-spring

【讨论】:

但是客户如何提前知道可以返回多少页呢? @membersound spring 自己处理它,您只需要创建一个 DTO,其中包含一些内容和其他字段(如 totalElements 和 totalPages)的列表,并将其作为响应发送给客户端。我在服务部分(在返回线下)添加了一些 cmets,以及一个示例 somethingPageDto。 对你有帮助吗? @membersound

以上是关于如何在 web 服务响应中将 json 响应作为块返回?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React js 中将 HTML 模板呈现为来自 json 的响应

以 JSON 字符串数组形式获取 AFNetworking 响应的结果

如何在 JQuery 中将 json 响应读取为名称值对

如何解析从 Web 服务响应收到的 JSON 响应

如何在 Android 中将 JSON 参数作为 Web 服务请求发送? [复制]

模拟 API 响应时如何在单元测试中使用 JSON 文件