RestTemplate作为spring-web项目的一部分,在Spring 3.0版本开始被引入。

RestTemplate类通过为HTTP方法(例如GET,POST,PUT,DELETE等)提供重载的方法,提供了一种非常方便的方法访问基于HTTP的Web服务。如果你的Web服务API基于标准的RESTful风格设计,使用效果将更加的完美。


在服务生成RestTemplate的Bean时绕过SSL验证,一般情况下,会通过SimpleClientHttpRequestFactory来构建RestTemplate实例,但是它不支持https,要支持https需要替换SimpleClientHttpRequestFactory为HttpComponentsClientHttpRequestFactory,而且我们还要引入httpclient依赖

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>

自定义ErrorHandler

import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.DefaultResponseErrorHandler;

/**
* 功能:捕获RestTemplate异常
*
*/
public class RtErrorHandler extends DefaultResponseErrorHandler {

@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return super.hasError(response);
}

@Override
public void handleError(ClientHttpResponse response) throws IOException {
HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
// 白名单。白名单上的异常则不处理,直接返回
List<HttpStatus> donotDeal = new ArrayList<>();
donotDeal.add(HttpStatus.UNAUTHORIZED);

// 非白名单则处理
if (!donotDeal.contains(statusCode)) {
super.handleError(response);
}
}

}

RestConfiguration

import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.security.cert.X509Certificate;

@Configuration
public class RestConfiguration {


@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory, RestTemplateBuilder builder){
RestTemplate build = builder.build();
build.setErrorHandler(new RtErrorHandler());
build.setRequestFactory(factory);
return build;
}

@Bean
public ClientHttpRequestFactory httpComponentsClientHttpRequestFactory() throws Exception {
// 自定义证书校验器
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) {
}

@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) {
}

@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
};

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());


SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);

CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(csf)
.build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(20000);
factory.setReadTimeout(15000);
factory.setHttpClient(httpClient);
return factory;
}

调用

@Resource
private RestTemplate restTemplate;


@Test
public void main() {
// 定义请求头
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("xxxx", "xxxx");
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

// 封装参数,千万不要替换为Map与HashMap,否则参数无法传递
MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
multiValueMap.add("param", "11");

HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(multiValueMap, httpHeaders);

String s = restTemplate.postForObject("https://xxxxx", httpEntity, String.class);
System.out.println(s);
}