最近运维突然抽风,把服务端访问方式改成https,但是RestTemplate默认是不支持https的,造成所有接口调用失败,经过一翻折腾后终于支持HTTPS,现将spring boot配置resttemplate及支持HTTPS的方法整理如下:
@[toc]
在项目中导入如下的RestTemplate加载类
@Configuration
public class RestTemplateConfig {
private Logger logger = LoggerFactory.getLogger(getClass().getName());
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
restTemplate.setErrorHandler(new ResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
return false;
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
}
});
return restTemplate;
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(15000);//读超时时间,单位为ms
factory.setConnectTimeout(10000);//连接超时时间,单位为ms
return factory;
}
}
导入该配置类后,就可以在项目中正常使用restTmeplate了
一般的使用方法如下:
//get请求
public String getO(String url, Map<String, ?> paramMap) {
logger.info("get-> url = " + url + " params: " + paramMap.toString());
String s = restTemplate.getForObject(url, String.class, paramMap);
logger.info("res->" + s);
return s;
}
//pos请求
public String postO(String url, MultiValueMap paramMap) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(paramMap, headers);
logger.info("post-> url = " + url + " params: " + paramMap.toString());
String s = restTemplateConfig.restTemplate(restTemplateConfig.simpleClientHttpRequestFactory())
.postForObject(url, httpEntity, String.class);
logger.info("res->" + s);
return s;
}
RestTemplateConfig中使用的是simpleClientHttpRequestFactory来构造RestTemplate实例的,但它是不支持https,要支持https需要替换simpleClientHttpRequestFactory为HttpComponentsClientHttpRequestFactory
第一步:引入依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
第二步:修改后的RestTemplateConfig文件如下
@Configuration
public class RestTemplateConfig {
private Logger logger = LoggerFactory.getLogger(getClass().getName());
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
restTemplate.setErrorHandler(new ResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
return false;
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
}
});
return restTemplate;
}
//为了支持https 改为下面的factory
@Bean(name = "httpsFactory")
public HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory()
{
try {
CloseableHttpClient httpClient = HttpClientUtils.acceptsUntrustedCertsHttpClient();
HttpComponentsClientHttpRequestFactory httpsFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
httpsFactory.setReadTimeout(40000);
httpsFactory.setConnectTimeout(40000);
return httpsFactory;
}
catch (Exception e ){
logger.info(e.getMessage());
return null;
}
}
}
其中HttpClientUtils的代码如下:
public class HttpClientUtils {
public static CloseableHttpClient acceptsUntrustedCertsHttpClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
HttpClientBuilder b = HttpClientBuilder.create();
// setup a Trust Strategy that allows all certificates.
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
return true;
}
}).build();
b.setSSLContext(sslContext);
// don't check Hostnames, either.
// -- use SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if you don't want to weaken
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
// here's the special part:
// -- need to create an SSL Socket Factory, to use our weakened "trust strategy";
// -- and create a Registry, to register it.
//
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslSocketFactory)
.build();
// now, we create connection-manager using our Registry.
// -- allows multi-threaded use
PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager( socketFactoryRegistry);
connMgr.setMaxTotal(200);
connMgr.setDefaultMaxPerRoute(100);
b.setConnectionManager( connMgr);
// finally, build the HttpClient;
// -- done!
CloseableHttpClient client = b.build();
return client;
}
}
经过上述修改后,RestTmplate就能同时支持http和https了
下面这个HttpClient是我对RestTemplate常用调用方法的一个封装,喜欢的直接拿去。。。。
@Component
public class HttpClient {
private Logger logger = LoggerFactory.getLogger(getClass().getName());
@Autowired
private RestTemplate restTemplate;
@Autowired
private RestTemplateConfig restTemplateConfig;
public HttpClient() {
//this.restTemplate = new RestTemplate();
}
/////////////////////////////////////////get//////////////////////////////////////////////
/**
* 一般的GET请求,封装getForEntity接口
* */
public <T> ResponseEntity<T> getE(String url, Class<T> responseType, Object... uriVariables) {
return restTemplate.getForEntity(url, responseType, uriVariables);
}
/**
* 一般的GET请求
* */
public String getO(String url, Map<String, ?> paramMap) {
logger.info("get-> url = " + url + " params: " + paramMap.toString());
String s = restTemplate.getForObject(url, String.class, paramMap);
logger.info("res->" + s);
return s;
}
/**
* 一般的GET请求,并返回header
* */
public String getWithHeader(String url, Map<String, ?> paramMap,HttpHeaders headers ) {
logger.info("get-> url = " + url + " params: " + paramMap.toString());
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> results = restTemplate.exchange(url,HttpMethod.GET, entity, String.class, paramMap);
String s = results.getBody();
logger.info("res->" + s);
return s;
}
public ResponseEntity<String> getE2(String url, Map<String, ?> paramMap ) {
logger.info("get-> url = " + url + " params: " + paramMap.toString());
HttpEntity<String> entity = new HttpEntity<String>("parameters");
ResponseEntity<String> results = restTemplate.exchange(url,HttpMethod.GET, entity, String.class, paramMap);
String s = results.getBody();
logger.info("res->" + s);
return results;
}
/**
* 一般的GET请求,请求信息附带cookies
* */
public String getOCookie(String url, Map<String, ?> paramMap,List<String> cookies ) {
logger.info("get-> url = " + url + " params: " + paramMap.toString() + " cookies: "+ cookies.toString());
HttpHeaders headers = new HttpHeaders();
headers.put(HttpHeaders.COOKIE,cookies);
//headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> results = restTemplate.exchange(url,HttpMethod.GET, entity, String.class, paramMap);
String s = results.getBody();
//String s = restTemplate.getForObject(url, String.class, paramMap);
logger.info("res->" + s);
return s;
}
/////////////////////////////////////////post//////////////////////////////////////////////
/**
* 一般的POST请求
* */
public String postO(String url, MultiValueMap paramMap) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(paramMap, headers);
logger.info("post-> url = " + url + " params: " + paramMap.toString());
String s = restTemplateConfig.restTemplate(restTemplateConfig.httpComponentsClientHttpRequestFactory()).postForObject(url, httpEntity, String.class);
logger.info("res->" + s);
//logger.info("res->" + JsonFormatUtil.formatJson(s));
return s;
}
/**
* 一般的POST请求,请求信息为JSONObject
* */
public String post_json(String url,JSONObject msg)
{
RestTemplate restTemplate = new RestTemplate();
//请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
//请求体
//封装成一个请求对象
HttpEntity entity = new HttpEntity(msg.toJSONString(), headers);
String result = restTemplateConfig.restTemplate(restTemplateConfig.httpComponentsClientHttpRequestFactory()).postForObject(url, entity, String.class);
return result;
}
/**
* 一般的POST请求,请求信息附带cookies
* */
public String postOCookie(String url, MultiValueMap paramMap, List<String> cookies ) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.put(HttpHeaders.COOKIE,cookies);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(paramMap, headers);
logger.info("post-> url = " + url + " params: " + paramMap.toString());
String s = restTemplateConfig.restTemplate(restTemplateConfig.httpComponentsClientHttpRequestFactory()).postForObject(url, httpEntity, String.class);
logger.info("res->" + JsonFormatUtil.formatJson(s));
return s;
}
}
@Autowired
private HttpClient httpClient;
get请求:
public JSONObject getUserInfo(String userName,Long userId){
String url = "http://localhost/demo/getUserInfo?userId={userId}&userName={userName}";
HashMap<String, String> param = new HashMap<String, String>();
param.put("userName", userName);
param.put("userId", 14587);
String re = httpClient.getO(url, param);
JSONObject r = JSON.parseObject(re);
return r;
}
post请求:
public String updateUserInfo(Long userId,String nickName) {
String url = "http://localhost/demo/updateNickName";
MultiValueMap<String, Object> param = new LinkedMultiValueMap<String, Object>();
param.add("nickName", nickName);
param.add("userId", userId);
String re = httpClient.postO(url, param);
re = JSON.parseObject(re).get("result").toString();
return re;
}