在RestTemplate使用中,很多情况下不了解的开发者认为RestTemplate只是OKHttp、HttpClient这些工具类的替代者,其实这两者是有着本质区别的。OKHttp一级HttpClient这些工具类是Java用来发送Http请求的,这个在日常开发中经常使用,但是RestTemplate定位不是这样,并不是为了取代Http工具类的使用,相反它底层可以使用各种不同的Http工具类,它的目的更多在于简化Http工具类的使用,并且可以通过Spring注解的方式来增强RestTemplate的功能,比如配置负载均衡。
配置RestTemplate
@Configuration
@Slf4j
public class RestTemplateConfig {
@Bean
@LoadBalanced //RestTemplate负载均衡生效
public RestTemplate getRestTemplate(){
OkHttpClient okHttpClient = OkHttpClientObject.CLIENT.getClientInstance();
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new OkHttp3ClientHttpRequestFactory(okHttpClient)); //配置OKHttp使用的工具类,这里使用OKHttp
return restTemplate;
}
}
复制代码
RestTemplate调用
调用RestTemplate的方法有很多,restTemplate提供了常见的get
、post
、put
等方法的调用,这里以Post方法为例进行介绍。
//header一级提交的Post参数均封装成HttpEntity,如果不希望对返回参数进行解析,可以统一返回String
private String sendRequestByRestTemplate(HttpServletRequest wrapper, String serviceName, String path) {
try {
String reqUrl = String.format("http://%s%s",serviceName,path);
HttpHeaders headers = getHttpHeaders(wrapper, reqUrl);
HttpEntity<String> reqData = new HttpEntity<> (IOUtils.toString(wrapper.getReader()),headers);
String result = restTemplate.postForObject(reqUrl,reqData,String.class);
return result;
}catch (Exception e){
log.info("rpc send request failed [{}]",e.getMessage());
return "";
}
}
复制代码
header方法如下所示:
private HttpHeaders getHttpHeaders(HttpServletRequest wrapper, String reqUrl) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
Enumeration<String> originHeadersNames = wrapper.getHeaderNames();
while (originHeadersNames.hasMoreElements()){
String name = originHeadersNames.nextElement();
if(!name.contains("x-hmac-auth")){
headers.add(name, wrapper.getHeader(name));
}
}
return headers;
}
复制代码
需要注意的是,如果希望启用负载均衡,那么传入RestTemplate中的url地址的格式必须是:http://${serviceId}/${requestPath}
其中serviceId是Eureka中注册的服务名称,requestPath是轻轻路径。具体原因可以参考如下的代码:
public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
//通过servieId找到负载均衡器
ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
Server server = this.getServer(loadBalancer, hint);
if (server == null) {
throw new IllegalStateException("No instances available for " + serviceId);
} else {
RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request);
}
}
复制代码
很多开发者都知道RestTemplate支持负载均衡器,但是在使用过程中如果没有注意到调用的请求格式,那么在实际应用中就有肯能找不到合法的后端调用服务地址,进而跑出异常。
小结
以上是本人在使用RestTemplate中的一些小的收获,希望能够帮的上大家。下一篇文章介绍一下RestTemplate的源码。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END