如何使用Spring和Vaadin在Grid中展示API响应数据?
解决方案
第一步:确认POJO与API响应的映射匹配
先排查POJO和Skulabs API响应结构是否完全匹配,这是映射错误的核心原因:
- 假设Skulabs API返回的响应结构如下:
{ "serial_numbers": [ { "serial_number": "SN123", "order_number": "ORD456", "time": "2024-05-20T10:00:00Z", "item_id": "ITEM789" }, ... ] } - 对应的
SerialRoot类需要包含列表字段,注意用Jackson注解处理JSON与Java字段名的映射:import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; public class SerialRoot { @JsonProperty("serial_numbers") private List<SerialNumbers> serialNumbers; public List<SerialNumbers> getSerialNumbers() { return serialNumbers; } public void setSerialNumbers(List<SerialNumbers> serialNumbers) { this.serialNumbers = serialNumbers; } } SerialNumbers类要对应单个条目字段,必须提供所有字段的getter方法(Vaadin Grid依赖getter读取数据):import com.fasterxml.jackson.annotation.JsonProperty; public class SerialNumbers { @JsonProperty("serial_number") private String serialNumber; @JsonProperty("order_number") private String orderNumber; @JsonProperty("time") private String time; // 若用LocalDateTime,需配置Jackson日期模块 @JsonProperty("item_id") private String itemId; public String getSerialNumber() { return serialNumber; } public String getOrderNumber() { return orderNumber; } public String getTime() { return time; } public String getItemId() { return itemId; } // setter按需添加 }
第二步:确保WebClient正确获取完整数据列表
检查WebClient调用逻辑,确保拿到的是全部数据而非单个对象:
- 如果API返回包含列表的根对象,用
bodyToMono获取SerialRoot后提取列表:import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; public class SkulabsService { private final WebClient webClient; public SkulabsService(WebClient.Builder webClientBuilder) { this.webClient = webClientBuilder.baseUrl("https://api.skulabs.com").build(); } public Mono<List<SerialNumbers>> getSerialNumbers() { return webClient.get() .uri("/your-api-endpoint") // 替换为实际Skulabs API端点 .header("Authorization", "Bearer YOUR_API_KEY") // 添加认证信息 .retrieve() .bodyToMono(SerialRoot.class) .map(SerialRoot::getSerialNumbers); } } - 如果API直接返回
SerialNumbers的JSON数组,直接用bodyToFlux转成列表:public Mono<List<SerialNumbers>> getSerialNumbers() { return webClient.get() .uri("/your-api-endpoint") .header("Authorization", "Bearer YOUR_API_KEY") .retrieve() .bodyToFlux(SerialNumbers.class) .collectList(); }
第三步:正确配置Vaadin Grid并加载数据
在Vaadin视图中初始化Grid、绑定字段,然后订阅WebClient结果更新Grid:
import com.vaadin.flow.component.grid.Grid; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.Route; import reactor.core.publisher.Mono; @Route("serial-numbers") public class SerialNumbersView extends VerticalLayout { private final Grid<SerialNumbers> grid; private final SkulabsService skulabsService; public SerialNumbersView(SkulabsService skulabsService) { this.skulabsService = skulabsService; grid = new Grid<>(SerialNumbers.class); // 显式配置要显示的列,避免自动生成冗余列 grid.addColumn(SerialNumbers::getSerialNumber).setHeader("Serial Number"); grid.addColumn(SerialNumbers::getOrderNumber).setHeader("Order Number"); grid.addColumn(SerialNumbers::getTime).setHeader("Time"); grid.addColumn(SerialNumbers::getItemId).setHeader("Item ID"); add(grid); loadData(); } private void loadData() { Mono<List<SerialNumbers>> dataMono = skulabsService.getSerialNumbers(); // 在Vaadin UI线程中更新数据,避免线程安全问题 dataMono.subscribe(data -> { getUI().ifPresent(ui -> ui.access(() -> { grid.setItems(data); // 传入完整列表,而非单个元素 })); }, error -> { // 错误处理:打印日志或显示前端提示 error.printStackTrace(); }); } }
常见问题排查
- Grid为空:在
loadData中打印data.size()确认WebClient是否获取到数据,同时检查POJO的getter方法是否存在且命名正确。 - 仅显示一行:检查是否错误地传入了列表的单个元素(比如
grid.setItems(data.get(0))),应直接传入完整列表。 - 映射错误:用
ObjectMapper手动测试JSON转POJO,排查字段匹配问题:ObjectMapper mapper = new ObjectMapper(); String apiJson = "复制API返回的JSON字符串"; SerialRoot root = mapper.readValue(apiJson, SerialRoot.class); System.out.println(root.getSerialNumbers().size());
内容的提问来源于stack exchange,提问作者Madster
相关产品推荐
相关产品推荐

