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); }