使用 spring RestTemplate 消耗 json+hal _embedded 资源的问题
Posted
技术标签:
【中文标题】使用 spring RestTemplate 消耗 json+hal _embedded 资源的问题【英文标题】:Problems consuming json+hal _embedded resources with spring RestTemplate 【发布时间】:2018-03-18 18:12:52 【问题描述】:我有一个简单的用例,我想使用一个用 json+hal 表示的资源集合。
我使用 spring RestTemplate 并将其配置为使用 Jackson2HalModule。 当我调试我的代码时,我发现 Response 对象确实包含准确的元数据(例如页面和资源的数量)和响应标头,但没有内容或链接。过去一天,我查看了互联网上的许多文章和指南,根据我的发现,我觉得我的自定义休息模板应该适用于我的用例。
如果有人能对此有所了解,我将不胜感激。
我的服务代码如下:
@Service
public class EventServiceImpl extends BaseService implements EventService
private static final String knownEntity = "59d786d642572853721728f6";
private static String SERVICE_URL = "http://EVENTS-SERVER";
private static String EVENTS_PATH = "/events";
@Autowired
@LoadBalanced
protected RestTemplate restTemplate;
@Override
public ResponseEntity<PagedResources<Event>> fetchEventsList()
// acceptable media type
List<MediaType> acceptableMediaTypes = Arrays.asList(HAL_JSON);
// header
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
HttpEntity<String> entity = new HttpEntity<String>(null, headers);
ResponseEntity<PagedResources<Event>> response = getRestTemplateWithHalMessageConverter()
.exchange(SERVICE_URL + EVENTS_PATH, HttpMethod.GET, entity, new ParameterizedTypeReference<PagedResources<Event>>());
return response;
public RestTemplate getRestTemplateWithHalMessageConverter()
List<HttpMessageConverter<?>> existingConverters = restTemplate.getMessageConverters();
List<HttpMessageConverter<?>> newConverters = new ArrayList<>();
newConverters.add(getHalMessageConverter());
newConverters.addAll(existingConverters);
restTemplate.setMessageConverters(newConverters);
return restTemplate;
private HttpMessageConverter getHalMessageConverter()
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new Jackson2HalModule());
MappingJackson2HttpMessageConverter halConverter = new TypeConstrainedMappingJackson2HttpMessageConverter(ResourceSupport.class);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
halConverter.setSupportedMediaTypes(Arrays.asList(HAL_JSON));
halConverter.setObjectMapper(objectMapper);
return halConverter;
我的简单模型是:
public class Event
private String name;
private String location;
private int capacity;
public String getName()
return name;
public String getLocation()
return location;
public int getCapacity()
return capacity;
为了完整起见,这里是我尝试使用的 hal+json 形状的示例:
"_embedded":
"events": [
"name": null,
"location": null,
"capacity": 0,
"currentState": "CANCELLED",
"_links":
"self":
"href": "http://192.168.1.6:2221/events/59d786d642572853721728f6"
,
"event":
"href": "http://192.168.1.6:2221/events/59d786d642572853721728f6"
,
"reinstate":
"href": "http://192.168.1.6:2221/events/59d786d642572853721728f6/reinstate"
,
"reschedule":
"href": "http://192.168.1.6:2221/events/59d786d642572853721728f6/reschedule"
,
"name": null,
"location": null,
"capacity": 0,
"currentState": "ADVERTISED",
"_links":
"self":
"href": "http://192.168.1.6:2221/events/59d7f14342572812ceca7fc6"
,
"event":
"href": "http://192.168.1.6:2221/events/59d7f14342572812ceca7fc6"
,
"cancel":
"href": "http://192.168.1.6:2221/events/59d7f14342572812ceca7fc6/cancel"
,
"reschedule":
"href": "http://192.168.1.6:2221/events/59d7f14342572812ceca7fc6/reschedule"
,
"name": null,
"location": null,
"capacity": 0,
"currentState": "ADVERTISED",
"_links":
"self":
"href": "http://192.168.1.6:2221/events/59d7f14742572812ceca7fc7"
,
"event":
"href": "http://192.168.1.6:2221/events/59d7f14742572812ceca7fc7"
,
"cancel":
"href": "http://192.168.1.6:2221/events/59d7f14742572812ceca7fc7/cancel"
,
"reschedule":
"href": "http://192.168.1.6:2221/events/59d7f14742572812ceca7fc7/reschedule"
,
"name": null,
"location": null,
"capacity": 0,
"currentState": "ADVERTISED",
"_links":
"self":
"href": "http://192.168.1.6:2221/events/59d7f14c42572812ceca7fc8"
,
"event":
"href": "http://192.168.1.6:2221/events/59d7f14c42572812ceca7fc8"
,
"cancel":
"href": "http://192.168.1.6:2221/events/59d7f14c42572812ceca7fc8/cancel"
,
"reschedule":
"href": "http://192.168.1.6:2221/events/59d7f14c42572812ceca7fc8/reschedule"
]
,
"_links":
"self":
"href": "http://192.168.1.6:2221/events?page,size,sort",
"templated": true
,
"profile":
"href": "http://192.168.1.6:2221/profile/events"
,
"page":
"size": 20,
"totalElements": 4,
"totalPages": 1,
"number": 0
编辑:我可以毫无问题地使用单个事件。
【问题讨论】:
【参考方案1】:我遇到了类似的问题,最后我使用了org.springframework.hateoas.Resources
对于我下面的例子,这个对象位于org.springframework.hateoas:spring-hateoas:jar:0.25.2.RELEASE
它是从org.springframework.boot:spring-boot-starter-data-rest:jar:2.1.7.RELEASE
中提取的,因此假设您声明了spring-boot-starter-data-rest
依赖项,它很有可能已经在您的类路径中。
这是一个简单的例子(使用您的信息):
RestTemplate restTemplate = new RestTemplate();
Resources<Event> resourceEvents = restTemplate.getForObject("http://192.168.1.6:2221/events", Resources.class);
List<Event> events = new ArrayList<>(resourceEvents.getContent());
可能有一些陷阱使这不是那么简单,但希望这可以为解决您的问题提供一个开始。
【讨论】:
以上是关于使用 spring RestTemplate 消耗 json+hal _embedded 资源的问题的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 spring 记录 RestTemplate 请求和响应?