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.inspur.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.inspur.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.inspur.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.40.x.x:9010/zsywservice"; 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()); //需要客戶端證書 requestPath = "https://10.40.x.x:9016/zsywservice"; 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替代。