我有一台服务器通过spring-data-rest公开资源,据我所知,HAL或HATEOAS使用它。但是当我尝试将它与Feign结合使用时,我似乎无法注册被拾取的Jackson2HalModule。
将Feign“客户端”连接到新转换器是否需要做些什么?它是否使用了另一个ObjectMapper而不是我在这里使用的那个?
代码:
@Inject
public void configureObjectMapper(ObjectMapper mapper, RestTemplate template) {
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);
template.getMessageConverters().add(converter);
}
来自服务器的响应:
{
"_links" : {
"self" : {
"href" : "http://localhost:13372/user{?page,size,sort}",
"templated" : true
},
"search" : {
"href" : "http://localhost:13372/user/search"
}
},
"_embedded" : {
"user" : [ {
"id" : "5567613e5da543dba4201950",
"version" : 0,
"created" : "2015-05-28T18:41:02.685Z",
"createdBy" : "system test",
"edited" : "2015-05-28T18:41:02.713Z",
"editedBy" : "system test",
"username" : "devuser",
"email" : "dev@test.com",
"roles" : [ "USER" ],
"_links" : {
"self" : {
"href" : "http://localhost:13372/user/5567613e5da543dba4201950"
}
}
} ]
},
"page" : {
"size" : 20,
"totalElements" : 1,
"totalPages" : 1,
"number" : 0
}
}
例外:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
at [Source: java.io.PushbackInputStream@7b6c6e70; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:762)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:758)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.handleNonArray(CollectionDeserializer.java:275)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:216)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:206)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:25)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3066)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2221)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:205)
答案 0 :(得分:5)
我发现了问题。 由于REST API的响应是单个响应,因此发生了异常。因此它未能将其视为实体列表。
当我添加(基于上面的代码)时:
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
它有效
编辑: 另外,我已经像这样实现了FeignClient:
@Service
@FeignClient(UsersConstants.USER_SERVICE_NAME)
public interface UsersServices {
@RequestMapping(method = RequestMethod.GET, value = "/user")
List<User> getUsers();
}
但它应该如何,因为它是一个可分页的资源:
@Service
@FeignClient(UsersConstants.USER_SERVICE_NAME)
public interface UsersServices {
@RequestMapping(method = RequestMethod.GET, value = "/user")
List<PagedResources<User>> getUsers();
}
PagedResource位于HATEOAS依赖项中:
<dependency>
<groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId>
</dependency>
它还有许多其他类可以提供帮助,例如资源,资源等。
答案 1 :(得分:5)
这对我有用:
@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
@SpringBootApplication
@EnableFeignClients
public class Application {
....
}
请注意@EnableHypermediaSupport
@FeignClient(url = "http://localhost:8080")
public interface PersonClient {
@RequestMapping(method = RequestMethod.GET, value = "/persons")
Resources<Person> getPersons();
@RequestMapping(method = RequestMethod.GET, value = "/persons/{id}")
Resource<Person> getPerson(@PathVariable("id") long id);
}
我在这里创建了一个完整的例子:https://github.com/jtdev/spring-feign-data-rest-example
请注意,只需将maven pom从spring-boot切换到spring-cloud(不更改代码),很容易导致json错误。
答案 2 :(得分:3)
您应该在应用程序中定义feignDecoder
bean。如果您的环境中有spring-hateoas
,请尝试以下操作:
@Bean
public Decoder feignDecoder() {
ObjectMapper mapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.registerModule(new Jackson2HalModule());
return new ResponseEntityDecoder(new JacksonDecoder(mapper));
}
然后您可以将您的HAL用作PagedResource
。
答案 3 :(得分:0)
我让这个为我工作(谢谢@Devabc,你的例子帮了我很多):
我想为用户获取资源的PagedResources。
记得添加
@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
到您的主要应用程序类。
My Feign客户端如下所示:
@FeignClient("user-microservice")
public interface UserClient {
@RequestMapping(method = RequestMethod.GET, value = "/user")
PagedResources<Resource<User>> findAll();
}
还要记住为模型添加默认和参数化构造函数。 (在我的情况下是用户)我不确定为什么,但这似乎解决了我的序列化问题。
最后我使用了这个版本的Feign
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.1.5.RELEASE</version>
</dependency>
答案 4 :(得分:0)
检查link
Greg Turnquist 下面的评论确实适用于集合类型返回
C)要从集合中提取的类型应为Resources<Resource<Question>>
。该集合具有链接以及集合的每个条目。