Spring boot 消耗 2 rest 并合并一些字段

Spring boot consume 2 rest and merge some fields

我是 Spring 的新手,我遇到了一个问题,我需要使用 2 个远程 Rest 服务并合并结果。需要对正确方法有一些了解。 我得到了这样的东西:

{"subInventories":[
  {"OrganizationId": 0,
    "OrganizationCode":"",
    "SecondaryInventoryName":"",
    "Description":""},...{}...],
{"organizations":[
  {"OrganizationId":0,
    "OrganizationCode":"",
    "OrganizationName":"",
    "ManagementBusinessUnitId":,
    "ManagementBusinessUnitName":""}, ...{}...]}

并且需要把它变成这样的东西:

{"items":[
{"OrganizationId":0,
    "OrganizationCode":"",
    "OrganizationName":"",
    "ManagementBusinessUnitId":0,
    "ManagementBusinessUnitName":"",
    "SecondaryInventoryName":"",
    "Description":""},...{}...]

得到 2 个@Entitys 来表示每个项目,组织和库存具有 JSON 字段等属性。 编辑 目前正在尝试与 Java8 stream()

匹配
@GetMapping("/manipulate")
public List<Organization> getManipulate() {
    List<Organization> organization = (List<Organization>)(Object) organizationController.getOrganization();
    List<SubInventories> subInventories = (List<SubInventories>)(Object) getSuvInventories();
    List<Organization> intersect = organization.stream().filter(o -> subInventories.stream().anyMatch(s -> s.getOrganizationId()==o.getOrganizationId()))
            .collect(Collectors.toList());
    return intersect;
    
}

但我有很多 classes 并且我不知道是否只为每个组织获取子库存并将它们放入地图列表中是否会更好

List<Map<String,Object> myList = new ArrayList<>();
//Loops here
Map<String,Object> a = new HashMap<>();
a.put("OrganizationID", 1231242415)...
myList.add(a)

完全不知道什么是正确的方法。

EDIT2

这是我正在使用的 classes。

组织

@Entity
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Organization implements Serializable{
    
    //@JsonObject("OrganizationId")
    @Id
    private Long OrganizationId;
    private Long ManagementBusinessUnitId;
    private String OrganizationCode,OrganizationName,ManagementBusinessUnitName;
    
    public Organization() {
    }
//getters setters
}

子库存

@Entity
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
@JsonIgnoreProperties(ignoreUnknown = true)
public class SubInventories implements Serializable{
    
    @Id
    private Long OrganizationId;
    private String OrganizationCode,SecondaryInventoryName,Description;
    
    public SubInventories() {
        
    }
//getters and setters
}

要解包消费的包装器

@JsonAutoDetect(fieldVisibility = Visibility.ANY)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Wrapper {
    //@JsonProperty("items")
    private List<Object> items;

    public Wrapper() {
    }
    
    public List<Object> getOrganization() {
        return items;
    }

    public void setOrganization(List<Object> organization) {
        this.items = organization;
    }
    
}

组织控制器

@RestController
public class OrganizationController {
    
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private Environment env;
    
    @GetMapping("/organizations")
    public List<Object> getOrganization() {
        return getOrganizationInfo();
        
    }

    private List<Object> getOrganizationInfo() {
        String url = env.getProperty("web.INVENTORY_ORGANIZATIONS");
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
        builder.queryParam("fields", "OrganizationId,OrganizationCode,OrganizationName,ManagementBusinessUnitId,ManagementBusinessUnitName");
        builder.queryParam("onlyData", "true");
        HttpHeaders headers = new HttpHeaders();
        headers.setBasicAuth(env.getProperty("authentication.name"),env.getProperty("authentication.password"));
        HttpEntity request = new HttpEntity(headers);
        ResponseEntity<Wrapper> temp = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, request, new ParameterizedTypeReference<Wrapper>() {});
        List<Object> data = temp.getBody().getOrganization();
        return data;
    }
    
    
}

子库存控制器

@RestController
public class SubInventoryController {
    
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private Environment env;
    
    @GetMapping("/sub")
    public List<Object> getSuvInventories() {
    
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("this is private :(");

        builder.queryParam("onlyData", "true");
        builder.queryParam("expand", "subinventoriesDFF");
        builder.queryParam("limit", "999999");  
        builder.queryParam("fields", "OrganizationId,OrganizationCode,SecondaryInventoryName,Description");
        HttpHeaders headers = new HttpHeaders();
        headers.setBasicAuth(env.getProperty("authentication.name"),env.getProperty("authentication.password"));
        headers.set("REST-Framework-Version", "2");
        HttpEntity request = new HttpEntity(headers);
        ResponseEntity<Wrapper> subInventories = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, request, new ParameterizedTypeReference<Wrapper>() {});
        List<Object> data = subInventories.getBody().getOrganization();
        return data;
    }

}

我现在在哪里

@RestController
public class MainController {
    
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private Environment env;
    @Autowired
    private OrganizationController organizationController;
    @Autowired
    private SubInventoryController subInventoryController;
    
    @GetMapping("/manipulate")
    public Map<Organization, List<SubInventories>> getManipulate() {
        List<Organization> organizations = (List<Organization>)(Object) organizationController.getOrganization();
        List<SubInventories> subInventories = (List<SubInventories>)(Object) subInventoryController.getSuvInventories();
        Map<Organization,List<SubInventories>> result = new HashMap<Organization,List<SubInventories>>();
        for(Organization organization : organizations) {
            List<SubInventories> subInventoryMatched = (List<SubInventories>) subInventories.stream().filter( s -> s.getOrganizationId()== organization.getOrganizationId()).collect(Collectors.toList());
            result.put(organizations.get(0), subInventoryMatched);
        }
        return result;  
    }
}

据我了解,我需要为每个 POJO 制作一个包装器 class,因为响应看起来像这样 /组织

{
    "items": [
        {
            "OrganizationId": 1,
            "OrganizationCode": "adasd",
            "OrganizationName": "Hotel Bahía Príncipe Sunlight Costa Adeje",
            "ManagementBusinessUnitId": 131231,
            "ManagementBusinessUnitName": "asdasfdas"
        },
        {
            "OrganizationId": 2,
            "OrganizationCode": "adadas",
            "OrganizationName": "Hadasd",
            "ManagementBusinessUnitId": 1231,
            "ManagementBusinessUnitName": "aewfrqaew"
        }]}

和/subInventories

{
    "items": [
        {
            "OrganizationId": 1,
            "OrganizationCode": "asada",
            "SecondaryInventoryName": "adfasdfasdgf",
            "Description": "pub"
        },
        {
            "OrganizationId": 2,
            "OrganizationCode": "asgfrgtsdh",
            "SecondaryInventoryName": "B LOB",
            "Description": "pub2"
        }
]}

如果将通用对象与对象一起使用,我会得到一个 java.lang.ClassCastException: java.util.LinkedHashMap 与 stream().filter 中的 com.demo.model.Organization 不兼容,并且对于字段的合并另一个 class 得到想要的

{
    "items": [
        {
            "OrganizationId": 1,
            "OrganizationCode": "asdas",
            "OrganizationName": "adsadasd",
            "ManagementBusinessUnitId": 1,
            "ManagementBusinessUnitName": "asdasdf",
            "SecondaryInventoryName": "sfsdfsfa",
            "Description": "pub1"
        }]}

大量 classes 如果我得到很多 POJO

根据您提供的信息,我假设如下:

  • 您有两种数据类型(Java classes)。它们应该合并为一个 Java class
  • 您必须从不同来源加载此数据
  • 没有 class 领先

我可以为您提供一些示例代码。该代码基于以前的采用。这会给你一个想法。这不是简单的复制和粘贴解决方案。

首先创建一个 class,其中包含要包含在结果中的所有字段:

public class Matched {
  private Object fieldA;
  private Object fieldB;

// Some getter and Setter
}

基本思想是加载数据。比找到两个对应的对象。之后对每个字段进行匹配。


public List<Matched> matchYourData() {
  // load your data
  List<DataA> dataAList = loadYourDataA();
  List<DataB> dataBList = loadYourDataB();

  List<Matched> resultList = new ArryList<>();
  for (dataA: DataA) {
    DataB dataB = dataBList.stream()
        .filter(data -> data.getId() == dataA.getId())
        .findFirst().orElseThrow();
    // Now you have your data. Let's match them.
    Matched matched = new Matched();
    matched.setFieldA(dataB.getFieldA() == dataA.getFieldA() ? doSomething() : doSomethingElse());
    // Set all your fields. Decide for everyone the matching strategy
    resultList.add(matched);
  }
  return resultList;
}

这是一个非常简单的解决方案。当然,您可以使用 Mapstruct 等工具进行映射。但这取决于你的环境。