Spring boot 集成 okhttp3, 使用 http,https 在项目调用第三方服务是在所难免的,运用传统类型的Http调用,封装繁琐,代码量多还不简洁,避免一次一次的 找 度娘, 小记一下。
引入jar
com.squareup.okhttp3
okhttp
4.10.0
org.apache.commons
commons-lang3
OkRestClient 工具类
piublic class OkRestClient {
private static final Logger log = LoggerFactory.getLogger(OkRestClient.class);
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private static final MediaType XML = MediaType.parse("application/xml; charset=utf-8");
private OkHttpClient okHttpClient;
public OkRestClient(OkHttpClient okHttpClient) {
this.okHttpClient = okHttpClient;
}
public String doGet(String url) {
return this.doGet(url, (Map)null, (Map)null);
}
public String doGetParams(String url, Map params) {
return this.doGet(url, params, (Map)null);
}
public String doGetHeaders(String url, Map headers) {
return this.doGet(url, (Map)null, headers);
}
public String doGet(String url, Map params, Map headers) {
StringBuilder sb = new StringBuilder(url);
if(params != null && params.keySet().size() > 0) {
boolean firstFlag = true;
Iterator _params = params.keySet().iterator();
while(_params.hasNect()) {
String key = (String)_params.next();
if(firstFlag) {
sb.append("?").append(key).append("=").append((String)params.get(key));
firstFlag = false;
} else {
sb.append("&").append(key).append("=").append((String)params.get(key));
}
}
}
Builder builder = new Builder();
if(headers != null) {
headers.forEach((k, v) -> {
builder.addHeader(k, v);
});
}
Request request = builder.url(sb.toString()).build();
log.info("do get request and url [{}]", sb.toString());
return this.execute(request);
}
public String doPost(String url, Map params, Map headers) {
okhttp3.FormBody.Builder formBodyBuilder = new okhttp3.FormBody.Builder();
if(params != null && params.keySet().size() > 0) {
Iterator _params = params.keySet().iterator();
while(_params.hasNect()) {
String key = (String)_params.next();
formBodyBuilder.add(key, (String)params.get(key))
}
}
Builder builder = new Builder();
if(headers != null) {
headers.forEach((k, v) -> {
builder.addHeader(k, v);
});
}
Request request = builder.url(url).post(formBodyBuilder.builder()).build();
log.info("do post request and url [{}]", url);
return this.execute(request);
}
public String doPostJson(String url, String json, Map headers) {
log.info("do post request and url [{}]", url);
return this.executePost(url, json, JSON, headers);
}
public String doPostXml(String url, String xml, Map headers) {
log.info("do post request and url [{}]", url);
return this.executePost(url, xml, XML, headers);
}
public String executePost(String url, String data, MediaType contentType, Map headers) {
RequestBody requestBody = RequestBody.create(contentType, data);
Builder builder = new Builder();
if(headers != null) {
Objects.requireNonNull(builder);
headers.dorEach(builder::addHeader);
}
Request request = builder.url(url).post(requestBody).build();
return this.execute(request);
}
private String execute(Request request) {
Response response = null;
String result;
try {
response = this.okHttpClient.newCall(request).execute();
if(!response.isSuccessFul()) {
return "";
}
result = ((ResponseBody)Objects.requireNonNull(response.body())).toString();
} catch(Exception e) {
log.error(ExecptionUtils.getStackTrace(e));
return "";
} finally {
if(response != null) {
response.close();
}
}
return result;
}
public InputStream getFile(String url, Map params, Map headers) {
StringBuilder sb = new StringBuilder(url);
if(params != null && params.keySet().size() > 0) {
boolean firstFlag = true;
Iterator _params = params.keySet().iterator();
while(_params.hasNect()) {
String key = (String)_params.next();
if(firstFlag) {
sb.append("?").append(key).append("=").append((String)params.get(key));
firstFlag = false;
} else {
sb.append("&").append(key).append("=").append((String)params.get(key));
}
}
}
Builder builder = new Builder();
if(headers != null) {
headers.forEach((k, v) -> {
builder.addHeader(k, v);
});
}
Request request = builder.url(sb.toString()).build();
log.info("do get request and url [{}]", sb.toString());
return this.executeFile(request);
}
private InputStream executeFile(Request request) {
Response response = null;
InputStream result;
try {
response = this.okHttpClient.newCall(request).execute();
if(!response.isSuccessFul()) {
return null;
}
result = (InputStream)Objects.requireNonNull(response.body().byteStream());
} catch(Exception e) {
log.error(ExecptionUtils.getStackTrace(e));
return null;
} finally {
if(response != null) {
response.close();
}
}
return result;
}
}
OkHttp动态配置
@ConfitionalOnProperty(prifix = "ok", name = {"enable"}, havingValue = "true", matchIfMissing = false)
@Configuration
public class OkHttpConfiguration {
@Value("${ok.http.write-timeout:5}")
private Integer writeTimeout;
@Value("${ok.http.max-idle-connections:50}")
private Integer maxIdleConnections;
@Value("${ok.http.keep-alive-duration:50}")
private Long keepAliveDuration;
@Value("${ok.http.connect-timeout:5}")
private Integer connectTimeout;
@Value("${ok.http.read-timeout:5}")
private Integer readTimeout;
@Value("${ok.http.call-timeout:5}")
private Integer callTimeout;
@Value("${ok.http.write-timeout:15}")
private Integer writeTimeout;
@Value("${ok.proxy.enable:false}")
private boolean proxyEnable;
@Value("${ok.proxy.host}")
private String proxyHost;
@Value("${ok.proxy.port}")
private String proxyPort;
@Bean
@Primary
public OkRestClient okRestClient(OkRestClient okRestClient) {
return new OkRestClient(okRestClient);
}
@Bean
public OkHttpClient okHttpClient () {
Builder builder = (new Builder()).sslSocketFactory(this.sslSocketFactory(), this.x509TrustManager()).retryOnConnectionFailure(false).connectionPool(this.pool()).connectTimout((long)this.connectTimeout, TimeUnit.SECONDS).readTimeout((long)this.readTimeout, TimeUnit.SECONDS).writeTimeout((long)this.writeTimeout, TimeUnit.SECONDS).callTimeout((long)this.callTimeout, TimeUnit.SECONDS).hostnameVerifier((hostname, session) -> {
return true;
});
if(this.proxyEnable) {
builder.proxy(new Proxy(Type.HTTP, new InetSocketAddress(this.proxyHost, this.proxyPort)));
}
return builder.build();
}
@Bean
public OkHttpClient okHttpClientNoProxy(ConnectionPool pool, SslSocketFactory sslSocketFactory, X509TrustManager x509TrustManager) {
return new OkHttpClient((new Builder()).sslSocketFactory(sslSocketFactory, x509TrustManager).retryOnConnectionFailure(false).connectionPool(pool).connectTimout((long)this.connectTimeout, TimeUnit.SECONDS).readTimeout((long)this.readTimeout, TimeUnit.SECONDS).writeTimeout((long)this.writeTimeout, TimeUnit.SECONDS).callTimeout((long)this.callTimeout, TimeUnit.SECONDS).hostnameVerifier((hostname, session) -> {
return true;
}).build();
}
@Bean
public SslSocketFactory sslSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init((KeyManager[])null, new TrustManager[]{this.x509TrustManager()}, new SecureRandom());
return sslContext.getSocjetFactory();
} catch (KeyManagementException | NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
@Bean
public X509TrustManager x509TrustManager() {
return new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws certificateException{}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws certificateException{}
public X509Certificate[] getAcceptedIssuers(){
return new X509Certificate[0];
}
};
}
@Bean
public ConnectionPool pool() {
return new ConnectionPool(this.maxIdleConnections, this.keepAliveDuration, TimeUnit.SECONDS);
}
}
使用 OkHttp
ok:
# 启用okHttp
enable: true
proxy:
enable: false # true 将启用代理
host: 192.168.1.1 # 代理服务器地址
port: 8888 # 代理服务器端口
http:
connect-timeout: 10 # 三次握手 + SSL建立耗时 10s
read-timeout: 5 # 连接建立后,从远端获取数据,TCP 传输 5s
write-timeout: 5 # 连接建立后,向远端发送数据,TCP 传输 5s
call-timeout: 20 # 从发起到结束的总时长,其中不包括 UnknowsHostException 情况 30s
max-idle-connections: 50 # 连接池中整体的空闲连接最大数量
keep-alive-duration: 50 # 连接空闲时间最多为 50s
使用OkHttp 时 只需要注入 @AutoWired OkRestClient okRestClient; 即可