使用服务名
示例:
@Component
public class OrganizationRestTemplateClient {
@Autowired
RestTemplate restTemplate;
public Organization getOrganization(String organizationId){
ResponseEntity<Organization> restExchange =
restTemplate.exchange(
"http://organizationservice/v1/organizations/{organizationId}",
HttpMethod.GET,
null, Organization.class, organizationId);
return restExchange.getBody();
}
}
上面的示例中,远程调用的 url
使用的不是一个确定的ip:port
,而是organizationservice
。其实这里的organizationservice
代表的是众多微服务spring.application.name=organizationservice
的服务,真正的逻辑会对url
进行解析,通过服务发现找到对应的服务实例集合中的一个实例的物理地址,然后发起真正的请求。
当然整个过程中还涉及到了负载均衡,目前为止默认使用的是 Netflix Ribbon
。
Microservices - RestTemplate UnknownHostException
在发起请求的时候,如果使用的是服务名,而不是确定的物理地址,那么有可能出现UnknownHostException
的异常,这是因为在注入RestTemplate
的时候缺少注解@LoadBalance
,该注解告知Spring Cloud创建一个基于Ribbon的RestTemplate,才可以实现客户端负载均衡。
@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
返回结果是泛型
通常,我们都会将返回结果封装成一个统一的ResponseWrapper
,比如:
public class ResponseWrapper<T> {
private int code;
private String message;
private T data;
// 省略 getter、setter
}
那么,如果希望返回结果是ResponseWrapper<Organization>
呢,要如何操作?
答案是,可以借助spring
提供的org.springframework.core.ParameterizedTypeReference
来实现。
实例:
@Component
public class OrganizationRestTemplateClient {
@Autowired
RestTemplate restTemplate;
public ResponseWrapper<Organization> getOrganization(String organizationId){
ResponseEntity<ResponseWrapper<Organization>> restExchange =
restTemplate.exchange(
serviceUri,
HttpMethod.GET,
null,
new ParameterizedTypeReference<ResponseWrapper<Organization>>(){},
organizationId);
return restExchange.getBody();
}
}
其中new ParameterizedTypeReference<ResponseWrapper<Organization>>(){}
是匿名内部类。
暂时先这么多,以后碰到其他的再补充。
网友评论