HttpClient、okhttp和RestTemplate的区别

不念不忘少年蓝@ 2022-12-16 09:21 237阅读 0赞

欢迎大家关注我的公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。

一、HttpClient

1、pom依赖

  1. <!--HttpClient-->
  2. <dependency>
  3. <groupId>commons-httpclient</groupId>
  4. <artifactId>commons-httpclient</artifactId>
  5. <version>3.1</version>
  6. </dependency>

2、HttpClient代码实现

  1. public class HttpClientUtil {
  2. /** * httpClient的get请求方式 * 使用GetMethod来访问一个URL对应的网页实现步骤: * 1.生成一个HttpClient对象并设置相应的参数; * 2.生成一个GetMethod对象并设置响应的参数; * 3.用HttpClient生成的对象来执行GetMethod生成的Get方法; * 4.处理响应状态码; * 5.若响应正常,处理HTTP响应内容; * 6.释放连接。 * @param url * @param charset * @return */
  3. public static String doGet(String url, String charset) {
  4. //1.生成HttpClient对象并设置参数
  5. HttpClient httpClient = new HttpClient();
  6. //设置Http连接超时为5秒
  7. httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
  8. //2.生成GetMethod对象并设置参数
  9. GetMethod getMethod = new GetMethod(url);
  10. //设置get请求超时为5秒
  11. getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 5000);
  12. //设置请求重试处理,用的是默认的重试处理:请求三次
  13. getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
  14. String response = "";
  15. //3.执行HTTP GET 请求
  16. try {
  17. int statusCode = httpClient.executeMethod(getMethod);
  18. //4.判断访问的状态码
  19. if (statusCode != HttpStatus.SC_OK) {
  20. System.err.println("请求出错:" + getMethod.getStatusLine());
  21. }
  22. //5.处理HTTP响应内容
  23. //HTTP响应头部信息,这里简单打印
  24. Header[] headers = getMethod.getResponseHeaders();
  25. for(Header h : headers) {
  26. System.out.println(h.getName() + "---------------" + h.getValue());
  27. }
  28. //读取HTTP响应内容,这里简单打印网页内容
  29. //读取为字节数组
  30. byte[] responseBody = getMethod.getResponseBody();
  31. response = new String(responseBody, charset);
  32. System.out.println("-----------response:" + response);
  33. //读取为InputStream,在网页内容数据量大时候推荐使用
  34. //InputStream response = getMethod.getResponseBodyAsStream();
  35. } catch (HttpException e) {
  36. //发生致命的异常,可能是协议不对或者返回的内容有问题
  37. System.out.println("请检查输入的URL!");
  38. e.printStackTrace();
  39. } catch (IOException e) {
  40. //发生网络异常
  41. System.out.println("发生网络异常!");
  42. } finally {
  43. //6.释放连接
  44. getMethod.releaseConnection();
  45. }
  46. return response;
  47. }
  48. /** * post请求 * @param url * @param json * @return */
  49. public static String doPost(String url, JSONObject json){
  50. HttpClient httpClient = new HttpClient();
  51. PostMethod postMethod = new PostMethod(url);
  52. postMethod.addRequestHeader("accept", "*/*");
  53. postMethod.addRequestHeader("connection", "Keep-Alive");
  54. //设置json格式传送
  55. postMethod.addRequestHeader("Content-Type", "application/json;charset=GBK");
  56. //必须设置下面这个Header
  57. postMethod.addRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");
  58. //添加请求参数
  59. postMethod.addParameter("commentId", json.getString("commentId"));
  60. String res = "";
  61. try {
  62. int code = httpClient.executeMethod(postMethod);
  63. if (code == 200){
  64. res = postMethod.getResponseBodyAsString();
  65. System.out.println(res);
  66. }
  67. } catch (IOException e) {
  68. e.printStackTrace();
  69. }
  70. return res;
  71. }
  72. public static void main(String[] args) {
  73. System.out.println(doGet("http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13026194071", "GBK"));
  74. System.out.println("-----------分割线------------");
  75. System.out.println("-----------分割线------------");
  76. System.out.println("-----------分割线------------");
  77. JSONObject jsonObject = new JSONObject();
  78. jsonObject.put("commentId", "13026194071");
  79. System.out.println(doPost("http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13026194071", jsonObject));
  80. }
  81. }

3、建议

代码复杂,还得操心资源回收等。代码很复杂,冗余代码多,不建议直接使用。

二、okhttp

1、简介

OkHttp是一个高效的HTTP客户端,允许所有同一个主机地址的请求共享同一个socket连接;连接池减少请求延时;透明的GZIP压缩减少响应数据的大小;缓存响应内容,避免一些完全重复的请求

当网络出现问题的时候OkHttp依然坚守自己的职责,它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IPOkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,当握手失败时会回退到TLS 1.0

2、pom依赖

  1. <dependency>
  2. <groupId>com.squareup.okhttp3</groupId>
  3. <artifactId>okhttp</artifactId>
  4. <version>3.10.0</version>
  5. </dependency>

它的请求/响应 API 使用构造器模式builders来设计,它支持阻塞式的同步请求和带回调的异步请求。

3、配置文件

  1. @Configuration
  2. public class OkHttpConfig {
  3. @Bean
  4. public OkHttpClient okHttpClient() {
  5. return new OkHttpClient.Builder()
  6. //.sslSocketFactory(sslSocketFactory(), x509TrustManager())
  7. .retryOnConnectionFailure(false)
  8. .connectionPool(pool())
  9. .connectTimeout(30, TimeUnit.SECONDS)
  10. .readTimeout(30, TimeUnit.SECONDS)
  11. .writeTimeout(30,TimeUnit.SECONDS)
  12. .build();
  13. }
  14. @Bean
  15. public X509TrustManager x509TrustManager() {
  16. return new X509TrustManager() {
  17. @Override
  18. public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
  19. }
  20. @Override
  21. public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
  22. }
  23. @Override
  24. public X509Certificate[] getAcceptedIssuers() {
  25. return new X509Certificate[0];
  26. }
  27. };
  28. }
  29. @Bean
  30. public SSLSocketFactory sslSocketFactory() {
  31. try {
  32. //信任任何链接
  33. SSLContext sslContext = SSLContext.getInstance("TLS");
  34. sslContext.init(null, new TrustManager[]{ x509TrustManager()}, new SecureRandom());
  35. return sslContext.getSocketFactory();
  36. } catch (NoSuchAlgorithmException e) {
  37. e.printStackTrace();
  38. } catch (KeyManagementException e) {
  39. e.printStackTrace();
  40. }
  41. return null;
  42. }
  43. /** * Create a new connection pool with tuning parameters appropriate for a single-user application. * The tuning parameters in this pool are subject to change in future OkHttp releases. Currently */
  44. @Bean
  45. public ConnectionPool pool() {
  46. return new ConnectionPool(200, 5, TimeUnit.MINUTES);
  47. }
  48. }

4、客户端工具

  1. @Slf4j
  2. public class OkHttpClient {
  3. private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
  4. private volatile static okhttp3.OkHttpClient client;
  5. private static final int MAX_IDLE_CONNECTION = Integer
  6. .parseInt(ConfigManager.get("httpclient.max_idle_connection"));
  7. private static final long KEEP_ALIVE_DURATION = Long
  8. .parseLong(ConfigManager.get("httpclient.keep_alive_duration"));
  9. private static final long CONNECT_TIMEOUT = Long.parseLong(ConfigManager.get("httpclient.connectTimeout"));
  10. private static final long READ_TIMEOUT = Long.parseLong(ConfigManager.get("httpclient. "));
  11. /** * 单例模式(双重检查模式) 获取类实例 * * @return client */
  12. private static okhttp3.OkHttpClient getInstance() {
  13. if (client == null) {
  14. synchronized (okhttp3.OkHttpClient.class) {
  15. if (client == null) {
  16. client = new okhttp3.OkHttpClient.Builder()
  17. .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
  18. .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
  19. .connectionPool(new ConnectionPool(MAX_IDLE_CONNECTION, KEEP_ALIVE_DURATION,
  20. TimeUnit.MINUTES))
  21. .build();
  22. }
  23. }
  24. }
  25. return client;
  26. }
  27. public static String syncPost(String url, String json) throws IOException {
  28. RequestBody body = RequestBody.create(JSON, json);
  29. Request request = new Request.Builder()
  30. .url(url)
  31. .post(body)
  32. .build();
  33. try {
  34. Response response = OkHttpClient.getInstance().newCall(request).execute();
  35. if (response.isSuccessful()) {
  36. String result = response.body().string();
  37. log.info("syncPost response = {}, responseBody= {}", response, result);
  38. return result;
  39. }
  40. String result = response.body().string();
  41. log.info("syncPost response = {}, responseBody= {}", response, result);
  42. throw new IOException("三方接口返回http状态码为" + response.code());
  43. } catch (Exception e) {
  44. log.error("syncPost() url:{} have a ecxeption {}", url, e);
  45. throw new RuntimeException("syncPost() have a ecxeption {}" + e.getMessage());
  46. }
  47. }
  48. public static String syncGet(String url, Map<String, Object> headParamsMap) throws IOException {
  49. Request request;
  50. final Request.Builder builder = new Request.Builder().url(url);
  51. try {
  52. if (!CollectionUtils.isEmpty(headParamsMap)) {
  53. final Iterator<Map.Entry<String, Object>> iterator = headParamsMap.entrySet()
  54. .iterator();
  55. while (iterator.hasNext()) {
  56. final Map.Entry<String, Object> entry = iterator.next();
  57. builder.addHeader(entry.getKey(), (String) entry.getValue());
  58. }
  59. }
  60. request = builder.build();
  61. Response response = OkHttpClient.getInstance().newCall(request).execute();
  62. String result = response.body().string();
  63. log.info("syncGet response = {},responseBody= {}", response, result);
  64. if (!response.isSuccessful()) {
  65. throw new IOException("三方接口返回http状态码为" + response.code());
  66. }
  67. return result;
  68. } catch (Exception e) {
  69. log.error("remote interface url:{} have a ecxeption {}", url, e);
  70. throw new RuntimeException("三方接口返回异常");
  71. }
  72. }
  73. }

三、RestTemplate

1、pom依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. </dependency>

2、get请求(不带参的即把参数取消即可)

  1. // 1-getForObject()
  2. User user1 = this.restTemplate.getForObject(uri, User.class);
  3. // 2-getForEntity()
  4. ResponseEntity<User> responseEntity1 = this.restTemplate.getForEntity(uri, User.class);
  5. HttpStatus statusCode = responseEntity1.getStatusCode();
  6. HttpHeaders header = responseEntity1.getHeaders();
  7. User user2 = responseEntity1.getBody();
  8. // 3-exchange()
  9. RequestEntity requestEntity = RequestEntity.get(new URI(uri)).build();
  10. ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);
  11. User user3 = responseEntity2.getBody();

方式一:

  1. Notice notice = restTemplate.getForObject("http://fantj.top/notice/list/{1}/{2}"
  2. , Notice.class,1,5);

方式二:

  1. Map<String,String> map = new HashMap();
  2. map.put("start","1");
  3. map.put("page","5");
  4. Notice notice = restTemplate.getForObject("http://fantj.top/notice/list/"
  5. , Notice.class,map);

3、post请求

  1. // 1-postForObject()
  2. User user1 = this.restTemplate.postForObject(uri, user, User.class);
  3. // 2-postForEntity()
  4. ResponseEntity<User> responseEntity1 = this.restTemplate.postForEntity(uri, user, User.class);
  5. // 3-exchange()
  6. RequestEntity<User> requestEntity = RequestEntity.post(new URI(uri)).body(user);
  7. ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);

方式一:

  1. String url = "http://demo/api/book/";
  2. HttpHeaders headers = new HttpHeaders();
  3. MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
  4. headers.setContentType(type);
  5. String requestJson = "{...}";
  6. HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
  7. String result = restTemplate.postForObject(url, entity, String.class);
  8. System.out.println(result);

方式二:

  1. @Test
  2. public void rtPostObject(){
  3. RestTemplate restTemplate = new RestTemplate();
  4. String url = "http://47.xxx.xxx.96/register/checkEmail";
  5. HttpHeaders headers = new HttpHeaders();
  6. headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
  7. MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
  8. map.add("email", "844072586@qq.com");
  9. HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
  10. ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );
  11. System.out.println(response.getBody());
  12. }

发表评论

表情:
评论列表 (有 0 条评论,237人围观)

还没有评论,来说两句吧...

相关阅读

    相关 restTemplate使用

    目录 目录 一、概述? 二、使用步骤 1.引入依赖 2.创建RestTemplate对象,交由spring容器进行管理 3.使用方法 3.1 GET请求