选择一个优秀的 HTTP Client 的重要性
- 连接池
- 请求/响应编解码(异步、超时设置等)
- API丰富程度及扩展性
JAVA 项目中接口调用怎么做 ?
- HttpClient
- OKhttp
- RestTemplate
上面是最常见的几种用法,我们基于目前主流的SpringBoot简单的介绍一下用法及对比。
基于springboot的HttpClient、OKhttp、RestTemplate对比
一、HttpClient
1、HttpClient 是Apache的一个三方网络框架,网络请求做了完善的封装,api众多,用起来比较方便,开发快。
二、OKhttp
1、高效的HTTP客户端,它能允许同一ip和端口的请求重用一个socket,这种方式能大大降低网络连接的时间,和每次请求都建立socket,再断开socket的方式相比,降低了服务器服务器的压力,透明的GZIP压缩减少响应数据的大小;缓存响应内容。
2、okhttp 对http和https都有良好的支持。
3、okhttp 对大数据量的网络请求支持非常好。
Util工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | import okhttp3.*; import org.apache.commons.lang3.exception.ExceptionUtils; import java.io.File; import java.util.Iterator; import java.util.Map; @Slf4j public class OkHttpUtil{ private static OkHttpClient okHttpClient; @Autowired public OkHttpUtil(OkHttpClient okHttpClient) { OkHttpUtil.okHttpClient= okHttpClient; } /** * get * @param url 请求的url * @param param 请求的参数 * @return */ public static String get(String url, Map<String, String> param) { String responseBody = ""; StringBuffer sb = new StringBuffer(url); if (param!= null && param.keySet().size() > 0) { boolean firstFlag = true; Iterator iterator = param.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry<String, String>) iterator.next(); if (firstFlag) { sb.append("?" + entry.getKey() + "=" + entry.getValue()); firstFlag = false; } else { sb.append("&" + entry.getKey() + "=" + entry.getValue()); } } } Request request = new Request.Builder() .url(sb.toString()) .build(); Response response = null; try { response = okHttpClient.newCall(request).execute(); int status = response.code(); if (response.isSuccessful()) { return response.body().string(); } } catch (Exception e) { log.error("okhttp3 post exception:{}", e.getMessage()); } finally { if (response != null) { response.close(); } } return responseBody; } /** * post * * @param url 请求的url * @param params post form 提交的参数 * @return */ public static String post(String url, Map<String, String> params) { String responseBody = ""; FormBody.Builder builder = new FormBody.Builder(); //添加参数 if (params != null && params.keySet().size() > 0) { for (String key : params.keySet()) { builder.add(key, params.get(key)); } } Request request = new Request.Builder() .url(url) .post(builder.build()) .build(); Response response = null; try { response = okHttpClient.newCall(request).execute(); int status = response.code(); if (response.isSuccessful()) { return response.body().string(); } } catch (Exception e) { log.error("okhttp3 post exception:{}", e.getMessage()); } finally { if (response != null) { response.close(); } } return responseBody; } /** * get * @param url 请求的url * @param param 请求的参数 * @return */ public static String getForHeader(String url, Map<String, String> param) { String responseBody = ""; StringBuffer sb = new StringBuffer(url); if (param != null && param.keySet().size() > 0) { boolean firstFlag = true; Iterator iterator = param.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry<String, String>) iterator.next(); if (firstFlag) { sb.append("?" + entry.getKey() + "=" + entry.getValue()); firstFlag = false; } else { sb.append("&" + entry.getKey() + "=" + entry.getValue()); } } } Request request = new Request.Builder() .addHeader("key", "value") .url(sb.toString()) .build(); Response response = null; try { response = okHttpClient.newCall(request).execute(); int status = response.code(); if (response.isSuccessful()) { return response.body().string(); } } catch (Exception e) { log.error("okhttp3 post exception:{}", e.getMessage()); } finally { if (response != null) { response.close(); } } return responseBody; } /** * Post请求发送JSON数据 * @param url 请求Url * @param jsonParams 请求的JSON */ public static String postJsonParams(String url, String jsonParams) { String responseBody = ""; RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams); Request request = new Request.Builder() .url(url) .post(requestBody) .build(); Response response = null; try { response = okHttpClient.newCall(request).execute(); int status = response.code(); if (response.isSuccessful()) { return response.body().string(); } } catch (Exception e) { log.error("okhttp3 post exception:{}", e.getMessage()); } finally { if (response != null) { response.close(); } } return responseBody; } /** * Post请求发送xml类型数据 * @param url 请求Url * @param xml 请求的xml */ public static String postXmlParams(String url, String xml) { String responseBody = ""; RequestBody requestBody = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml); Request request = new Request.Builder() .url(url) .post(requestBody) .build(); Response response = null; try { response = okHttpClient.newCall(request).execute(); int status = response.code(); if (response.isSuccessful()) { return response.body().string(); } } catch (Exception e) { log.error("okhttp3 post exception:{}", e.getMessage()); } finally { if (response != null) { response.close(); } } return responseBody; } } |
三、RestTemplate
1、Spring 提供的用于访问Rest服务的客户端, RestTemplate 提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
2、面向对 RESTful Web 服务调用的功能。
在微服务中的使用
1、第三方服务调用,个人常用 RestTemplate
2、微服务间调用,个人使用feign,同时使用OKhttp替换feign中默认的httpClient。
Feign在默认情况下使用的是JDK原生的URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection 。 我们可以用HTTP Client 或 OKhttp 替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。
SpringCloud 1.x
1 2 3 4 5 6 7 8 9 10 | <!-- 使用Apache HttpClient替换Feign原生httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <dependency> <groupId>com.netflix.feign</groupId> <artifactId>feign-httpclient</artifactId> <version>${feign-httpclient}</version> </dependency> |
application.properties中添加:
1 | feign.httpclient.enabled=true |
1 2 3 4 5 6 | <!-- 使用OKhttp替换Feign原生httpclient --> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> <version>10.2.0</version> </dependency> |
application.properties中添加:
1 | feign.okhttp.enabled=true |
SpringColud 2.x
1 2 3 4 5 6 | <!-- 使用OKhttp替换openFeign原生httpclient --> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.10.0</version> </dependency> |
application.properties中添加:
1 | feign.okhttp.enabled=true |