You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 05:35:12