我正在构建两个应该相互通信的微服务。 我正在使用Eureka作为服务注册表。
微服务1 - Microservice1.java
@SpringBootApplication
public class Microservice1Application {
public static void main(String[] args) {
SpringApplication.run(Microservice1Application.class, args);
}
}
Microservice1Controller.java
@RestController
@RequestMapping("/getdata")
public class Microservice1Controller {
@GetMapping(value = "/")
public ResponseEntity<Microservice1ResponseWrapper<List<Customer1>>> getAll() {
List<Customer1> list = //get data from repository
return new ResponseEntity<Microservice1ResponseWrapper<List<Customer1>>>(new Microservice1ResponseWrapper<List<Customer1>>(Microservice1ResponseStatus.SUCCESS,list);
}
}
Microservice1ResponseWrapper.java -这是通用包装器
public class Microservice1ResponseWrapper<T> {
private Microservice1ResponseStatus status;
private T data;
//constructor, getter and setters
}
applicationProperties.yaml
spring:
application:
name: microservice1
server:
port: 8073
微服务2 将从Microservice1获取数据的Microservice2
@SpringBootApplication
public class Microservice2Application {
public static void main(String[] args) {
SpringApplication.run(Microservice2Application.class, args);
}
}
@Configuration
class Config {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Microservice2Controller.java
@RestController
@RequestMapping("/fetchdata")
public class Microservice2Controller {
@Autowired
private RestTemplate restTemplate;
@GetMapping(value = "/")
public ResponseEntity<Microservice2ResponseWrapper<List<Customer2>>> getAll() {
String getAllUrl = "http://microservice1/getdata/";
ParameterizedTypeReference<Microservice2ResponseWrapper<List<Customer2>>> parameterizedTypeReference =
new ParameterizedTypeReference<Microservice2ResponseWrapper<List<Customer2>>>(){};
ResponseEntity<Microservice2ResponseWrapper<List<Customer2>>> listData =
restTemplate.exchange(getAllUrl, HttpMethod.GET, null,parameterizedTypeReference);
return listData;
}
}
Microservice2ResponseWrapper.java -这是通用包装器
public class Microservice2ResponseWrapper<T> {
private Microservice2ResponseStatus status;
private T data;
//constructor, getter and setters
}
applicationProperties.yaml
spring:
application:
name: microservice2
server:
port: 8074
Customer1(在Microservice1中)和Customer2(在Microservice2中)几乎是相同的对象。
public class Customer1 implements Serializable {
private static final long serialVersionUID = 1L;
private Long custId;
private String custName;
private String firstName;
private String lastName;
private Long age;
public Customer1() {
}
public Customer1(String custName, String firstName, String lastName, Long age) {
this.custName = custName;
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public Customer1(Long custId, String custName, String firstName, String lastName, Long age) {
this.custId = custId;
this.custName = custName;
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
//getter, setter and toString
}
Microservice2中的Customer2.java
public class Customer2 implements Serializable {
private static final long serialVersionUID = 1L;
private Long custId;
private String custName;
private String firstName;
private String lastName;
private Long age;
public Customer2() {
}
//getter, setter and toString
}
当我运行Microservice1:http://localhost:8073/getdata时,它会从数据库中获取数据并且工作正常。这是我在屏幕上看到的回复:
<Microservice1ResponseWrapper>
<status>SUCCESS</status>
<data>
<custId>1</custId>
<custName>string1</custName>
<firstName>string1</firstName>
<lastName>string1</lastName>
<age>30</age>
</data>
</Microservice1ResponseWrapper>
当我运行Microservice2:http://localhost:8074/fetchdata时,它应该转到Microservice 1并获取数据。
但是,我收到如下错误:
org.springframework.web.client.RestClientException: Error while extracting response for type
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:117)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:994)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:977)
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.rest.Customer2` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('1'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.rest.Customer2` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('1')
at [Source: (PushbackInputStream); line: 1, column: 61] (through reference chain: com.rest.wrapper.Microservice2ResponseWrapper["data"]->java.util.ArrayList[0])
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:245)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:227)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:102)
... 77 more
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.rest.Customer2` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('1')
at [Source: (PushbackInputStream); line: 1, column: 61] (through reference chain: com.rest.wrapper.Microservice2ResponseWrapper["data"]->java.util.ArrayList[0])
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1032)
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1373)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:171)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:286)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:369)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3084)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:239)
我在ParameterizedTypeReference或resttemplate交换呼叫中犯了任何错误吗?
注意:如果我在没有Eureka注册表的情况下运行这两个微服务,则它们绝对可以正常工作。但是,当我介绍Eureka并在Eureka中注册这两项服务时,就会遇到上述问题。 为此,我刚刚对Miroservice2控制器进行了更改: 字符串getAllUrl =“ http://localhost:8073/getdata/”;
更新-19/02/22
这是我尝试过的
更新了Microservice1Controller-getAll()如下:
@GetMapping(value = "/")
public ResponseEntity<List<Customer1>> getAll() {
List<Customer1> list = //get data from repository
return new ResponseEntity<List<Customer1>>(list);
}
更新了Microservice2Controller- getAll()方法
@GetMapping(value = "/")
public ResponseEntity<List<Customer2>> getAll() {
String getAllUrl = "http://microservice1/getdata/";
ParameterizedTypeReference<List<Customer2>> parameterizedTypeReference =
new ParameterizedTypeReference<List<Customer2>>(){};
ResponseEntity<List<Customer2>> listData =
restTemplate.exchange(getAllUrl, HttpMethod.GET, null,parameterizedTypeReference);
return listData;
}
如前所述,这可以很好地调用Microservice2的Microservice1。 Microservice1将ResponseEntity>返回给Microservice2,而Microservice2将其转换为ResponseEntity>。
但是,
返回ResponseEntity<Microservice1ResponseWrapper<List<Customer1>>>
到Microservice2和Microservice2的Microservice1无法转换为ResponseEntity<Microservice2ResponseWrapper<List<Customer2>>>
。
答案 0 :(得分:0)
您需要为Customer2类创建一个默认的构造函数。 Customer2(){}
答案 1 :(得分:0)
我无法使用RestTemplate解决它。因此,我继续尝试使用Open Feign。
步骤1。在pom.xml中,我添加了依赖项
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
</dependency>
第2步。添加客户端界面
@FeignClient(name = "microservice1")
public interface Microservice1Client {
@GetMapping(value = "/getdata/")
ResponseEntity<Microservice1ResponseWrapper<List<Customer1>>> getAll();
}
步骤3。在Microservice2Controller中注入FeignClient bean Microservice1Client
@RestController
@RequestMapping("/fetchdata")
public class Microservice2Controller {
@Autowired
Microservice1Client microservice1Client;
@GetMapping(value = "/")
public ResponseEntity<Microservice2ResponseWrapper<List<Customer2>>> getAll() {
return microservice1Client.getAll();
}
}