Java调用Http/Https接口(6)--RestTemplate调用Http/Https接口
RestTemplate是Spring提供的用于访问Http接口的客户端,提供同步的API;在将来的Spring版本中可能会过时,将逐渐被WebClient替代。文中所使用到的软件版本:Java 1.8.0_191、SpringBoot 2.2.1.RELEASE。
1、服务端
2、调用Http接口
2.1、GET请求
public static void get() { try { String requestPath = "http://localhost:8080/demo/httptest/getUser?userId=1000&userName=李白"; RestTemplate template = new RestTemplate(); //System.out.println(template.getMessageConverters()); //第二个为StringHttpMessageConverter template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); ResponseEntity<String> response = template.getForEntity(requestPath, String.class); System.out.println("get返回状态:" + response.getStatusCode()); System.out.println("get返回结果:" + response.getBody()); } catch (Exception e) { e.printStackTrace(); } }
2.2、POST请求(发送键值对数据)
public static void post() { String requestPath = "http://localhost:8080/demo/httptest/getUser"; RestTemplate template = new RestTemplate(); template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); MultiValueMap<String, String> map = new LinkedMultiValueMap <String, String>(); map.add("userId", "1000"); map.add("userName", "李白"); ResponseEntity<String> response = template.postForEntity(requestPath, map, String.class); System.out.println("post返回状态:" + response.getStatusCode()); System.out.println("post返回结果:" + response.getBody()); }
2.3、POST请求(发送JSON数据)
public static void post2() { String requestPath = "http://localhost:8080/demo/httptest/addUser"; RestTemplate template = new RestTemplate(); template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); String param = "{\"userId\": \"1001\",\"userName\":\"杜甫\"}"; HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json"); HttpEntity<String> entity = new HttpEntity<String>(param, headers); ResponseEntity<String> response = template.postForEntity(requestPath, entity, String.class); System.out.println("post json返回状态:" + response.getStatusCode()); System.out.println("post json返回结果:" + response.getBody()); }
2.4、上传文件
public static void upload() { String requestPath = "http://localhost:8080/demo/httptest/upload"; RestTemplate template = new RestTemplate(); template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "file/*"); HttpEntity<FileSystemResource> entity = new HttpEntity<FileSystemResource>(new FileSystemResource("d:/a.jpg"), headers); ResponseEntity<String> response = template.postForEntity(requestPath, entity, String.class); System.out.println("upload返回状态:" + response.getStatusCode()); System.out.println("upload返回结果:" + response.getBody()); }
2.5、上传文件及发送键值对数据
public static void mulit() { String requestPath = "http://localhost:8080/demo/httptest/multi"; RestTemplate template = new RestTemplate(); template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); MultiValueMap<String, Object> map = new LinkedMultiValueMap <String, Object>(); map.add("param1", "参数1"); map.add("param2", "参数2"); map.add("file", new FileSystemResource("d:/a.jpg")); ResponseEntity<String> response = template.postForEntity(requestPath, map, String.class); System.out.println("mulit返回状态:" + response.getStatusCode()); System.out.println("mulit返回结果:" + response.getBody()); }
2.6、完整例子
package com.abc.demo.http.client; import java.nio.charset.Charset; import org.springframework.core.io.FileSystemResource; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; /** * * 通过RestTemplate调用Http接口 * */ public class RestTemplateCase { /** * GET请求 */ public static void get() { try { String requestPath = "http://localhost:8080/demo/httptest/getUser?userId=1000&userName=李白"; RestTemplate template = new RestTemplate(); //System.out.println(template.getMessageConverters()); //第二个为StringHttpMessageConverter template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); ResponseEntity<String> response = template.getForEntity(requestPath, String.class); System.out.println("get返回状态:" + response.getStatusCode()); System.out.println("get返回结果:" + response.getBody()); } catch (Exception e) { e.printStackTrace(); } } /** * POST请求(发送键值对数据) */ public static void post() { String requestPath = "http://localhost:8080/demo/httptest/getUser"; RestTemplate template = new RestTemplate(); template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); MultiValueMap<String, String> map = new LinkedMultiValueMap <String, String>(); map.add("userId", "1000"); map.add("userName", "李白"); ResponseEntity<String> response = template.postForEntity(requestPath, map, String.class); System.out.println("post返回状态:" + response.getStatusCode()); System.out.println("post返回结果:" + response.getBody()); } /** * POST请求(发送json数据) */ public static void post2() { String requestPath = "http://localhost:8080/demo/httptest/addUser"; RestTemplate template = new RestTemplate(); template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); String param = "{\"userId\": \"1001\",\"userName\":\"杜甫\"}"; HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json"); HttpEntity<String> entity = new HttpEntity<String>(param, headers); ResponseEntity<String> response = template.postForEntity(requestPath, entity, String.class); System.out.println("post json返回状态:" + response.getStatusCode()); System.out.println("post json返回结果:" + response.getBody()); } /** * 上传文件 */ public static void upload() { String requestPath = "http://localhost:8080/demo/httptest/upload"; RestTemplate template = new RestTemplate(); template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "file/*"); HttpEntity<FileSystemResource> entity = new HttpEntity<FileSystemResource>(new FileSystemResource("d:/a.jpg"), headers); ResponseEntity<String> response = template.postForEntity(requestPath, entity, String.class); System.out.println("upload返回状态:" + response.getStatusCode()); System.out.println("upload返回结果:" + response.getBody()); } /** * 上传文件及发送键值对数据 */ public static void mulit() { String requestPath = "http://localhost:8080/demo/httptest/multi"; RestTemplate template = new RestTemplate(); template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); MultiValueMap<String, Object> map = new LinkedMultiValueMap <String, Object>(); map.add("param1", "参数1"); map.add("param2", "参数2"); map.add("file", new FileSystemResource("d:/a.jpg")); ResponseEntity<String> response = template.postForEntity(requestPath, map, String.class); System.out.println("mulit返回状态:" + response.getStatusCode()); System.out.println("mulit返回结果:" + response.getBody()); } public static void main(String[] args) { get(); post(); post2(); upload(); mulit(); } }
3、调用Https接口
与调用Http接口不一样的部分主要在设置ssl部分,设置方法是扩展SimpleClientHttpRequestFactory并在prepareConnection方法中进行ssl的设置;ssl的设置与HttpsURLConnection很相似(参见Java调用Http/Https接口(2)--HttpURLConnection/HttpsURLConnection调用Http/Https接口);下面用GET请求来演示ssl的设置,其他调用方式类似。
package com.abc.demo.http.client; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.HttpURLConnection; import java.nio.charset.Charset; import java.security.KeyStore; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import org.springframework.http.ResponseEntity; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.client.RestTemplate; import com.abc.demo.common.util.FileUtil; /** * 通过RestTemplate调用Https接口 */ public class RestTemplateHttpsCase { public static void main(String[] args) { try { /* * 请求有权威证书的地址 */ String requestPath = "https://www.baidu.com/"; RestTemplate template = new RestTemplate(); template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); ResponseEntity<String> response = template.getForEntity(requestPath, String.class); System.out.println("get1返回结果:" + response.getBody()); /* * 请求自定义证书的地址 */ //获取信任证书库 KeyStore trustStore = getkeyStore("jks", "d:/temp/cacerts", "123456"); //不需要客户端证书 requestPath = "https://10.49.196.10:9010/myservice"; template = new RestTemplate(new HttpsClientRequestFactory(trustStore)); template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); response = template.getForEntity(requestPath, String.class); System.out.println("get2返回结果:" + response.getBody()); //需要客户端证书,客户端证书可以是用 keytool 生成的 pks12 格式密钥库,也可以是用 OpenSSL 生成的 pkcs12 格式证书。 requestPath = "https://10.49.196.10:9016/myservice"; KeyStore keyStore = getkeyStore("pkcs12", "d:/client.p12", "123456"); template = new RestTemplate(new HttpsClientRequestFactory(keyStore, "123456", trustStore)); template.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); response = template.getForEntity(requestPath, String.class); System.out.println("get3返回结果:" + response.getBody()); } catch (Exception e) { e.printStackTrace(); } } /** * 获取证书 * @return */ private static KeyStore getkeyStore(String type, String filePath, String password) { KeyStore keySotre = null; FileInputStream in = null; try { keySotre = KeyStore.getInstance(type); in = new FileInputStream(new File(filePath)); keySotre.load(in, password.toCharArray()); } catch (Exception e) { e.printStackTrace(); } finally { FileUtil.close(in); } return keySotre; } /** * 扩展SimpleClientHttpRequestFactory以支持Https */ private static class HttpsClientRequestFactory extends SimpleClientHttpRequestFactory { private KeyStore keyStore; private String keyStorePassword; private KeyStore trustStore; public HttpsClientRequestFactory(KeyStore keyStore, String keyStorePassword, KeyStore trustStore) { this.keyStore = keyStore; this.keyStorePassword = keyStorePassword; this.trustStore = trustStore; } public HttpsClientRequestFactory(KeyStore trustStore) { this.trustStore = trustStore; } @Override protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException { try { if (!(connection instanceof HttpsURLConnection)) { throw new RuntimeException("An instance of HttpsURLConnection is expected"); } HttpsURLConnection httpsConnection = (HttpsURLConnection) connection; KeyManager[] keyManagers = null; TrustManager[] trustManagers = null; if (this.keyStore != null) { KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); keyManagerFactory.init(keyStore, keyStorePassword.toCharArray()); keyManagers = keyManagerFactory.getKeyManagers(); } if (this.trustStore != null) { TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509"); trustManagerFactory.init(trustStore); trustManagers = trustManagerFactory.getTrustManagers(); } else { trustManagers = new TrustManager[] { new DefaultTrustManager()}; } SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagers, trustManagers, null); httpsConnection.setSSLSocketFactory(sslContext.getSocketFactory()); //验证URL的主机名和服务器的标识主机名是否匹配 httpsConnection.setHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String s, SSLSession sslSession) { //if ("xxx".equals(hostname)) { // return true; //} else { // return false; //} return true; } }); super.prepareConnection(httpsConnection, httpMethod); } catch (Exception e) { e.printStackTrace(); } } } private static final class DefaultTrustManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return null; } } }
4、AsyncRestTemplate
该模板已过时,建议使用 WebClient 替代。