使用RestTemplate访问带有完整参数的外部GET链接,出现以下报错。
java.lang.IllegalStateException: No instances available for **********
at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:79)
at org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor.intercept(LoadBalancerInterceptor.java:46
at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:86)
at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:70)
往上查了很多资料,说是RestTemplate,调用到了内网,如下
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* 描述:
* @since 2019年11月29日 下午10:20:04
*/
@Configuration
public class RestConfig {
@Bean(name="defineRestTemplate")
//@LoadBalanced //加上代表是在Eureka上去找服务,不能调用外网,也不能调用本地如:127.0.0.1
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
注入及使用:
@Autowired
@Qualifier(value = "defineRestTemplate") // 月一定要加上,不然找不到
private RestTemplate restTemplate;
public void test() {
Object forObject = restTemplate.getForObject("完整的外部get链接,条件都已经拼凑好,返回为json", Object.class);
System.out.println(forObject);
}
调试时,又出现了403:Bad Request。
换下一个方式:使用使用feign调用的方式,由于完整的链接,连服务名称都找不到,自然是不行的。
最后还是Apache上找到了解决办法,Apache家族和Spring家族相比,就好比俄罗斯武器和西方国家武器,一个粗犷耐操,一个精细实用。同样的功能,肯定是优先使用Spring,Spring不行了再使用Apache。
//(GET) 访问url,并返回结果Request:org.apache.http.client.fluent.Request
String str = Request.Get(url).connectTimeout(Constant.NUMBER_1500).socketTimeout(Constant.NUMBER_1500).execute().returnContent().asString();
GET访问使用:
// Execute a GET with timeout settings and return response content as String.
Request.Get("http://somehost/")
.connectTimeout(1000)
.socketTimeout(1000)
.execute().returnContent().asString();
POST访问时:
// Execute a POST with the 'expect-continue' handshake, using HTTP/1.1,
// containing a request body as String and return response content as byte array.
Request.Post("http://somehost/do-stuff")
.useExpectContinue()
.version(HttpVersion.HTTP_1_1)
.bodyString("Important stuff", ContentType.DEFAULT_TEXT)
.execute().returnContent().asBytes();
POST代理访问:
// Execute a POST with a custom header through the proxy containing a request body
// as an HTML form and save the result to the file
Request.Post("http://somehost/some-form")
.addHeader("X-Custom-header", "stuff")
.viaProxy(new HttpHost("myproxy", 8080))
.bodyForm(Form.form().add("username", "vip").add("password", "secret").build())
.execute().saveContent(new File("result.dump"));
对身份验证进行缓存访问:
Executor executor = Executor.newInstance()
.auth(new HttpHost("somehost"), "username", "password")
.auth(new HttpHost("myproxy", 8080), "username", "password")
.authPreemptive(new HttpHost("myproxy", 8080));
executor.execute(Request.Get("http://somehost/"))
.returnContent().asString();
executor.execute(Request.Post("http://somehost/do-stuff")
.useExpectContinue()
.bodyString("Important stuff", ContentType.DEFAULT_TEXT))
.returnContent().asString();
Apache的东西真是让人又爱又恨,明明能够做出别人做不出来的东西,可偏偏不好好做。
需要访问外网API,若遇到问题可以参考以下Apache专门为HTTP访问开发的工具包,包名:org.apache.http.client.fluent.Request
使用方法及地址