@Configuration
public class OkHttpConfig {
@Bean
public RestTemplate restTemplate() throws Exception {
// 1. 定義繞過憑證的 TrustManager
X509TrustManager trustManager = new X509TrustManager() {
@Override public void checkClientTrusted(X509Certificate[] chain, String authType) {}
@Override public void checkServerTrusted(X509Certificate[] chain, String authType) {}
@Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; }
};
// 2. 建立 SSLContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());
// 3. 建立 OkHttpClient 並配置連線池
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory(), trustManager)
.hostnameVerifier((hostname, session) -> true) // 繞過 Hostname 驗證
.connectionPool(new ConnectionPool(50, 5, TimeUnit.MINUTES)) // 最大 50 個閒置連線
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.build();
// 4. 將 OkHttp 封裝進 RestTemplate
return new RestTemplate(new OkHttp3ClientHttpRequestFactory(okHttpClient));
}
}
QENvbmZpZ3VyYXRpb24KCnB1YmxpYyBjbGFzcyBPa0h0dHBDb25maWcgewoKCgogICAgQEJlYW4KCiAgICBwdWJsaWMgUmVzdFRlbXBsYXRlIHJlc3RUZW1wbGF0ZSgpIHRocm93cyBFeGNlcHRpb24gewoKICAgICAgICAvLyAxLiDlrprnvqnnuZ7pgY7mhpHorYnnmoQgVHJ1c3RNYW5hZ2VyCgogICAgICAgIFg1MDlUcnVzdE1hbmFnZXIgdHJ1c3RNYW5hZ2VyID0gbmV3IFg1MDlUcnVzdE1hbmFnZXIoKSB7CgogICAgICAgICAgICBAT3ZlcnJpZGUgcHVibGljIHZvaWQgY2hlY2tDbGllbnRUcnVzdGVkKFg1MDlDZXJ0aWZpY2F0ZVtdIGNoYWluLCBTdHJpbmcgYXV0aFR5cGUpIHt9CgogICAgICAgICAgICBAT3ZlcnJpZGUgcHVibGljIHZvaWQgY2hlY2tTZXJ2ZXJUcnVzdGVkKFg1MDlDZXJ0aWZpY2F0ZVtdIGNoYWluLCBTdHJpbmcgYXV0aFR5cGUpIHt9CgogICAgICAgICAgICBAT3ZlcnJpZGUgcHVibGljIFg1MDlDZXJ0aWZpY2F0ZVtdIGdldEFjY2VwdGVkSXNzdWVycygpIHsgcmV0dXJuIG5ldyBYNTA5Q2VydGlmaWNhdGVbXXt9OyB9CgogICAgICAgIH07CgoKCiAgICAgICAgLy8gMi4g5bu656uLIFNTTENvbnRleHQKCiAgICAgICAgU1NMQ29udGV4dCBzc2xDb250ZXh0ID0gU1NMQ29udGV4dC5nZXRJbnN0YW5jZSgiVExTIik7CgogICAgICAgIHNzbENvbnRleHQuaW5pdChudWxsLCBuZXcgVHJ1c3RNYW5hZ2VyW117dHJ1c3RNYW5hZ2VyfSwgbmV3IFNlY3VyZVJhbmRvbSgpKTsKCgoKICAgICAgICAvLyAzLiDlu7rnq4sgT2tIdHRwQ2xpZW50IOS4pumFjee9rumAo+e3muaxoAoKICAgICAgICBPa0h0dHBDbGllbnQgb2tIdHRwQ2xpZW50ID0gbmV3IE9rSHR0cENsaWVudC5CdWlsZGVyKCkKCiAgICAgICAgICAgICAgICAuc3NsU29ja2V0RmFjdG9yeShzc2xDb250ZXh0LmdldFNvY2tldEZhY3RvcnkoKSwgdHJ1c3RNYW5hZ2VyKQoKICAgICAgICAgICAgICAgIC5ob3N0bmFtZVZlcmlmaWVyKChob3N0bmFtZSwgc2Vzc2lvbikgLT4gdHJ1ZSkgLy8g57me6YGOIEhvc3RuYW1lIOmpl+itiQoKICAgICAgICAgICAgICAgIC5jb25uZWN0aW9uUG9vbChuZXcgQ29ubmVjdGlvblBvb2woNTAsIDUsIFRpbWVVbml0Lk1JTlVURVMpKSAvLyDmnIDlpKcgNTAg5YCL6ZaS572u6YCj57eaCgogICAgICAgICAgICAgICAgLmNvbm5lY3RUaW1lb3V0KDUsIFRpbWVVbml0LlNFQ09ORFMpCgogICAgICAgICAgICAgICAgLnJlYWRUaW1lb3V0KDEwLCBUaW1lVW5pdC5TRUNPTkRTKQoKICAgICAgICAgICAgICAgIC5idWlsZCgpOwoKCgogICAgICAgIC8vIDQuIOWwhyBPa0h0dHAg5bCB6KOd6YCyIFJlc3RUZW1wbGF0ZQoKICAgICAgICByZXR1cm4gbmV3IFJlc3RUZW1wbGF0ZShuZXcgT2tIdHRwM0NsaWVudEh0dHBSZXF1ZXN0RmFjdG9yeShva0h0dHBDbGllbnQpKTsKCiAgICB9Cgp9Cg==