项目需要用别的应用的接口,于是使用RestTemplate,Spring boot下配置很简单:
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
// 连接超时
factory.setConnectTimeout(15 * 1000);
// 读取超时
factory.setReadTimeout(15 * 1000);
return factory;
}
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate(simpleClientHttpRequestFactory());
// 使用StringHttpMessageConverter作为默认的转换器,这样就不用每次都设置RequestMapping中的produces属性
restTemplate.getMessageConverters().add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}
但是发现没有请求时没有将Origin头带过去,网上查了下发现是由于**
SimpleClientHttpRequestFactory
使用了标准 JDK 工具的 ClientHttpRequestFactory 实现。
HttpUrlConnection 源码里配置了headr黑名单,Origin就在其中,https://stackoverflow.com/questions/41699608/resttemplate-not-passing-origin-header
StackOverflow上给的解决方法是设置属性允许使用受限头
通过命令行参数
-Dsun.net.http.allowRestrictedHeaders=true
我使用的这个,代码里设置属性
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
后续使用时发现,如果请求不是200返回,restTemplate会报错:org.springframework.web.client.ResourceAccessException: I/O error on GET request
网上搜了后换了个ClientHttpRequestFactory实现:
HttpComponentsClientHttpRequestFactory
它使用 Apache HttpComponents HttpClient 创建请求。
@Bean
public ClientHttpRequestFactory clientHttpRequestFactory() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
// 连接超时
factory.setConnectTimeout(5000);
// 数据读取超时时间,即SocketTimeout
factory.setReadTimeout(5000);
// 连接不够用的等待时间,不宜过长,必须设置,比如连接不够用时,时间过长将是灾难性的
factory.setConnectionRequestTimeout(200);
return factory;
}
然后因为没用默认的ClientHttpRequestFactory 实现了,也不存在头限制了,之前的设置属性的代码也可以去掉了
试一下用错误的Http方法调用接口,然后报错:
org.springframework.web.client.HttpClientErrorException$MethodNotAllowed 405
这样的异常好处理多了。
Q.E.D.