Spring HAL 消费者返回空资源

Spring HAL consumer returning empty Resource

我想递归地使用 HAL 格式的端点。示例端点响应如下所示:

{
  "_embedded" : {
    "machineStateClassAnswers" : [ {
      "name" : 1,
      "extendedTimeSegmentAnswer" : {
        "duration" : 24,
        "goodParts" : 87,
        "rejectedParts" : 16,
        "relativeDurationInPercentage" : 17,
        "count" : 7,
        "averageDuration" : 3.5714
      },
      "_links" : {
        "self" : {
          "href" : "http://localhost:1890/equipment/class_1?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
        },
        "class" : {
          "href" : "http://localhost:1890/equipment/class_1?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
        }
      }
    }, {
      "name" : 2,
      "extendedTimeSegmentAnswer" : {
        "duration" : 34,
        "goodParts" : 54,
        "rejectedParts" : 11,
        "relativeDurationInPercentage" : 24,
        "count" : 5,
        "averageDuration" : 7.8
      },
      "_links" : {
        "self" : {
          "href" : "http://localhost:1890/equipment/class_2?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
        },
        "class" : {
          "href" : "http://localhost:1890/equipment/class_2?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
        }
      }
    }, {
      "name" : 3,
      "extendedTimeSegmentAnswer" : {
        "duration" : 86,
        "goodParts" : 76,
        "rejectedParts" : 15,
        "relativeDurationInPercentage" : 60,
        "count" : 7,
        "averageDuration" : 21.5714
      },
      "_links" : {
        "self" : {
          "href" : "http://localhost:1890/equipment/class_3?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
        },
        "class" : {
          "href" : "http://localhost:1890/equipment/class_3?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
        }
      }
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:1890/equipment/classes?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
    }
  }
}

我尝试使用 restTemplate class 和来自 Spring HATEOAS 的 Jackson2HalModule 使用此端点,例如:

@Service
public class TableResponseService {

    @Value("${url}")
    String url;

    private final RestTemplate restTemplate;

    public TableResponseService(RestTemplateBuilder restTemplateBuilder) {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.registerModule(new Jackson2HalModule());

        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json"));
        converter.setObjectMapper(mapper);
        this.restTemplate = restTemplateBuilder.additionalMessageConverters(Arrays.asList(converter)).build();
    }

    public Resources<List<MachineStateClassAnswer>> getMachineStates() {
        return restTemplate.exchange(url,
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<Resources<List<MachineStateClassAnswer>>>() {
                }
        ).getBody();
    }
}

数据class是:

public class MachineStateClassAnswer extends ResourceSupport {
    private Long name;
    public ExtendedTimeSegmentAnswer extendedTimeSegmentAnswer;

    public MachineStateClassAnswer(Long name, ExtendedTimeSegmentAnswer extendedTimeSegmentAnswer) {
        this.name = name;
        this.extendedTimeSegmentAnswer = extendedTimeSegmentAnswer;
    }

    public Long getName() {
        return name;
    }

    public ExtendedTimeSegmentAnswer getExtendedTimeSegmentAnswer() {
        return extendedTimeSegmentAnswer;
    }


    public void setName(Long name) {
        this.name = name;
    }

    public void setExtendedTimeSegmentAnswer(ExtendedTimeSegmentAnswer extendedTimeSegmentAnswer) {
        this.extendedTimeSegmentAnswer = extendedTimeSegmentAnswer;
    }
}

public class ExtendedTimeSegmentAnswer extends BasicTimeSegmentAnswer {
    protected Long relativeDurationInPercentage;
    protected Long count;
    protected Double averageDuration;

    public ExtendedTimeSegmentAnswer() {
    }

    public ExtendedTimeSegmentAnswer(Long duration, Long goodParts, Long rejectedParts, Long count, Double averageDuration) {
        super(duration, goodParts, rejectedParts);
        this.count = count;
        this.averageDuration = averageDuration;
    }

    public Long getRelativeDurationInPercentage() {
        return relativeDurationInPercentage;
    }

    public Long getDuration() {
        return duration;
    }


    public Long getCount() {
        return count;
    }

    public void setCount(Long count) {
        this.count = count;
    }

    public Double getAverageDuration() {
        return averageDuration;
    }

    public void setAverageDuration(Double averageDuration) {
        this.averageDuration = averageDuration;
    }

}

并且:

public class BasicTimeSegmentAnswer {
    protected Long duration;
    protected Long goodParts;
    protected Long rejectedParts;

    public BasicTimeSegmentAnswer() {
    }

    public BasicTimeSegmentAnswer(Long duration, Long goodParts, Long rejectedParts) {
        this.duration = duration;
        this.goodParts = goodParts;
        this.rejectedParts = rejectedParts;
    }

    public Long getDuration() {
        return duration;
    }

    public void setDuration(Long duration) {
        this.duration = duration;
    }

    public Long getGoodParts() {
        return goodParts;
    }

    public void setGoodParts(Long goodParts) {
        this.goodParts = goodParts;
    }

    public Long getRejectedParts() {
        return rejectedParts;
    }

    public void setRejectedParts(Long rejectedParts) {
        this.rejectedParts = rejectedParts;
    }

}

我的测试:

@Test
public void testConnection(){
    System.out.println(tableResponseService.getMachineStates());
}

但是returns:

Resources { content: [], links: [] }

无论我试图改变什么,我就是无法让它工作。

对于任何有类似问题的人,这里是解决方案:

  1. 修复消息转换器 this.restTemplate = restTemplateBuilder.messageConverters(converter).build(); ( ... 因为 *+json 存在默认转换器)

  2. 向 MachineStateClassAnswer 添加默认构造函数 public MachineStateClassAnswer() {}