Http和Https网络同步请求httpclient和异步请求async-http-client

HTTP与HTTPS网络请求封装
本文介绍了使用Apache HttpClient和Async-HTTP-Client进行HTTP及HTTPS请求的封装方法,包括GET、POST请求及其SSL证书验证,并对比了两种客户端在网络请求性能上的表现。

原文:https://blog.youkuaiyun.com/fengshizty/article/details/53100694

 

Http和https网络请求

    主要总结一下使用到的网络请求框架,一种是同步网络请求org.apache.httpcomponents的httpclient,另一种是异步网络请求com.ning的async-http-client,总结一下常用的http请求方式封装使用,如post、get、put、delete等,以及涉及到ssl证书https请求的双向证书验证。

    一、apache同步请求httpclient

    1、引入文件

    

[java]  view plain  copy
 
  1. <dependency>  
  2.             <groupId>org.apache.httpcomponents</groupId>  
  3.             <artifactId>httpclient</artifactId>  
  4.             <version>4.5.2</version>  
  5.         </dependency>  

 

 

    2、http和https的方法封装

    涉及常用的post和get的请求,https的ssl双向证书验证。

   

[java]  view plain  copy
 
  1. import java.io.IOException;  
  2. import java.io.UnsupportedEncodingException;  
  3. import java.net.URLEncoder;  
  4. import java.security.KeyStore;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7. import java.util.Map;  
  8. import java.util.Map.Entry;  
  9.   
  10. import javax.net.ssl.SSLContext;  
  11.   
  12. import org.apache.http.NameValuePair;  
  13. import org.apache.http.client.config.RequestConfig;  
  14. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  15. import org.apache.http.client.methods.CloseableHttpResponse;  
  16. import org.apache.http.client.methods.HttpGet;  
  17. import org.apache.http.client.methods.HttpPost;  
  18. import org.apache.http.conn.ssl.SSLConnectionSocketFactory;  
  19. import org.apache.http.entity.StringEntity;  
  20. import org.apache.http.impl.client.CloseableHttpClient;  
  21. import org.apache.http.impl.client.HttpClients;  
  22. import org.apache.http.message.BasicNameValuePair;  
  23. import org.apache.http.ssl.SSLContexts;  
  24. import org.apache.http.util.EntityUtils;  
  25. import org.springframework.core.io.ClassPathResource;  
  26. import org.springframework.core.io.Resource;  
  27.   
  28. /** 
  29.  * 创建时间:2016年11月9日 下午4:16:32 
  30.  *  
  31.  * @author andy 
  32.  * @version 2.2 
  33.  */  
  34. public class HttpUtils {  
  35.   
  36.     private static final String DEFAULT_CHARSET = "UTF-8";  
  37.       
  38.     private static final int CONNECT_TIME_OUT = 5000; //链接超时时间3秒  
  39.       
  40.     private static final RequestConfig REQUEST_CONFIG = RequestConfig.custom().setConnectTimeout(CONNECT_TIME_OUT).build();  
  41.       
  42.     private static SSLContext wx_ssl_context = null; //微信支付ssl证书  
  43.       
  44.     static{  
  45.         Resource resource = new ClassPathResource("wx_apiclient_cert.p12");  
  46.         try {  
  47.             KeyStore keystore = KeyStore.getInstance("PKCS12");  
  48.             char[] keyPassword = ConfigUtil.getProperty("wx.mchid").toCharArray(); //证书密码  
  49.             keystore.load(resource.getInputStream(), keyPassword);  
  50.             wx_ssl_context = SSLContexts.custom().loadKeyMaterial(keystore, keyPassword).build();  
  51.         } catch (Exception e) {  
  52.             e.printStackTrace();  
  53.         }  
  54.     }  
  55.   
  56.     /** 
  57.      * @description 功能描述: get 请求 
  58.      * @param url 请求地址 
  59.      * @param params 参数 
  60.      * @param headers headers参数 
  61.      * @return 请求失败返回null 
  62.      */  
  63.     public static String get(String url, Map<String, String> params, Map<String, String> headers) {  
  64.   
  65.         CloseableHttpClient httpClient = null;  
  66.         if (params != null && !params.isEmpty()) {  
  67.             StringBuffer param = new StringBuffer();  
  68.             boolean flag = true; // 是否开始  
  69.             for (Entry<String, String> entry : params.entrySet()) {  
  70.                 if (flag) {  
  71.                     param.append("?");  
  72.                     flag = false;  
  73.                 } else {  
  74.                     param.append("&");  
  75.                 }  
  76.                 param.append(entry.getKey()).append("=");  
  77.                   
  78.                 try {  
  79.                     param.append(URLEncoder.encode(entry.getValue(), DEFAULT_CHARSET));  
  80.                 } catch (UnsupportedEncodingException e) {  
  81.                     //编码失败  
  82.                 }  
  83.             }  
  84.             url += param.toString();  
  85.         }  
  86.   
  87.         String body = null;  
  88.         CloseableHttpResponse response = null;  
  89.         try {  
  90.             httpClient = HttpClients.custom()  
  91.                     .setDefaultRequestConfig(REQUEST_CONFIG)  
  92.                     .build();  
  93.             HttpGet httpGet = new HttpGet(url);  
  94.             response = httpClient.execute(httpGet);  
  95.             body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);  
  96.         } catch (Exception e) {  
  97.             e.printStackTrace();  
  98.         } finally {  
  99.             if (response != null) {  
  100.                 try {  
  101.                     response.close();  
  102.                 } catch (IOException e) {  
  103.                     e.printStackTrace();  
  104.                 }  
  105.             }  
  106.   
  107.             if (httpClient != null) {  
  108.                 try {  
  109.                     httpClient.close();  
  110.                 } catch (IOException e) {  
  111.                     e.printStackTrace();  
  112.                 }  
  113.             }  
  114.         }  
  115.         return body;  
  116.     }  
  117.   
  118.     /** 
  119.      * @description 功能描述: get 请求 
  120.      * @param url 请求地址 
  121.      * @return 请求失败返回null 
  122.      */  
  123.     public static String get(String url) {  
  124.         return get(url, null);  
  125.     }  
  126.   
  127.     /** 
  128.      * @description 功能描述: get 请求 
  129.      * @param url 请求地址 
  130.      * @param params 参数 
  131.      * @return 请求失败返回null 
  132.      */  
  133.     public static String get(String url, Map<String, String> params) {  
  134.         return get(url, params, null);  
  135.     }  
  136.   
  137.     /** 
  138.      * @description 功能描述: post 请求 
  139.      * @param url 请求地址 
  140.      * @param params 参数 
  141.      * @return 请求失败返回null 
  142.      */  
  143.     public static String post(String url, Map<String, String> params) {  
  144.         CloseableHttpClient httpClient = null;  
  145.         HttpPost httpPost = new HttpPost(url);  
  146.         List<NameValuePair> nameValuePairs = new ArrayList<>();  
  147.         if (params != null && !params.isEmpty()) {  
  148.             for (Entry<String, String> entry : params.entrySet()) {  
  149.                 nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));  
  150.             }  
  151.         }  
  152.   
  153.         String body = null;  
  154.         CloseableHttpResponse response = null;  
  155.         try {  
  156.             httpClient = HttpClients.custom()  
  157.                     .setDefaultRequestConfig(REQUEST_CONFIG)  
  158.                     .build();  
  159.             httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, DEFAULT_CHARSET));  
  160.             response = httpClient.execute(httpPost);  
  161.             body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);  
  162.         } catch (Exception e) {  
  163.             e.printStackTrace();  
  164.         } finally {  
  165.             if (response != null) {  
  166.                 try {  
  167.                     response.close();  
  168.                 } catch (IOException e) {  
  169.                     e.printStackTrace();  
  170.                 }  
  171.             }  
  172.   
  173.             if (httpClient != null) {  
  174.                 try {  
  175.                     httpClient.close();  
  176.                 } catch (IOException e) {  
  177.                     e.printStackTrace();  
  178.                 }  
  179.             }  
  180.         }  
  181.         return body;  
  182.     }  
  183.   
  184.     /** 
  185.      * @description 功能描述: post 请求 
  186.      * @param url 请求地址 
  187.      * @param s 参数xml 
  188.      * @return 请求失败返回null 
  189.      */  
  190.     public static String post(String url, String s) {  
  191.         CloseableHttpClient httpClient = null;  
  192.         HttpPost httpPost = new HttpPost(url);  
  193.         String body = null;  
  194.         CloseableHttpResponse response = null;  
  195.         try {  
  196.             httpClient = HttpClients.custom()  
  197.                     .setDefaultRequestConfig(REQUEST_CONFIG)  
  198.                     .build();  
  199.             httpPost.setEntity(new StringEntity(s, DEFAULT_CHARSET));  
  200.             response = httpClient.execute(httpPost);  
  201.             body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);  
  202.         } catch (Exception e) {  
  203.             e.printStackTrace();  
  204.         } finally {  
  205.             if (response != null) {  
  206.                 try {  
  207.                     response.close();  
  208.                 } catch (IOException e) {  
  209.                     e.printStackTrace();  
  210.                 }  
  211.             }  
  212.   
  213.             if (httpClient != null) {  
  214.                 try {  
  215.                     httpClient.close();  
  216.                 } catch (IOException e) {  
  217.                     e.printStackTrace();  
  218.                 }  
  219.             }  
  220.         }  
  221.         return body;  
  222.     }  
  223.   
  224.     /** 
  225.      * @description 功能描述: post https请求,服务器双向证书验证 
  226.      * @param url 请求地址 
  227.      * @param params 参数 
  228.      * @return 请求失败返回null 
  229.      */  
  230.      public static String posts(String url, Map<String, String> params) {  
  231.         CloseableHttpClient httpClient = null;  
  232.         HttpPost httpPost = new HttpPost(url);  
  233.         List<NameValuePair> nameValuePairs = new ArrayList<>();  
  234.         if (params != null && !params.isEmpty()) {  
  235.             for (Entry<String, String> entry : params.entrySet()) {  
  236.                 nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));  
  237.             }  
  238.         }  
  239.   
  240.         String body = null;  
  241.         CloseableHttpResponse response = null;  
  242.         try {  
  243.             httpClient = HttpClients.custom()  
  244.                     .setDefaultRequestConfig(REQUEST_CONFIG)  
  245.                     .setSSLSocketFactory(getSSLConnectionSocket())  
  246.                     .build();  
  247.             httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, DEFAULT_CHARSET));  
  248.             response = httpClient.execute(httpPost);  
  249.             body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);  
  250.         } catch (Exception e) {  
  251.             e.printStackTrace();  
  252.         } finally {  
  253.             if (response != null) {  
  254.                 try {  
  255.                     response.close();  
  256.                 } catch (IOException e) {  
  257.                     e.printStackTrace();  
  258.                 }  
  259.             }  
  260.   
  261.             if (httpClient != null) {  
  262.                 try {  
  263.                     httpClient.close();  
  264.                 } catch (IOException e) {  
  265.                     e.printStackTrace();  
  266.                 }  
  267.             }  
  268.         }  
  269.         return body;  
  270.     }  
  271.       
  272.     /** 
  273.      * @description 功能描述: post https请求,服务器双向证书验证 
  274.      * @param url 请求地址 
  275.      * @param s 参数xml 
  276.      * @return 请求失败返回null 
  277.      */  
  278.     public static String posts(String url, String s) {  
  279.         CloseableHttpClient httpClient = null;  
  280.         HttpPost httpPost = new HttpPost(url);  
  281.         String body = null;  
  282.         CloseableHttpResponse response = null;  
  283.         try {  
  284.             httpClient = HttpClients.custom()  
  285.                     .setDefaultRequestConfig(REQUEST_CONFIG)  
  286.                     .setSSLSocketFactory(getSSLConnectionSocket())  
  287.                     .build();  
  288.             httpPost.setEntity(new StringEntity(s, DEFAULT_CHARSET));   
  289.             response = httpClient.execute(httpPost);  
  290.             body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);  
  291.         } catch (Exception e) {  
  292.             e.printStackTrace();  
  293.         } finally {  
  294.             if (response != null) {  
  295.                 try {  
  296.                     response.close();  
  297.                 } catch (IOException e) {  
  298.                     e.printStackTrace();  
  299.                 }  
  300.             }  
  301.   
  302.             if (httpClient != null) {  
  303.                 try {  
  304.                     httpClient.close();  
  305.                 } catch (IOException e) {  
  306.                     e.printStackTrace();  
  307.                 }  
  308.             }  
  309.         }  
  310.         return body;  
  311.     }  
  312.   
  313.     //获取ssl connection链接  
  314.     private static SSLConnectionSocketFactory getSSLConnectionSocket() {  
  315.         return new SSLConnectionSocketFactory(wx_ssl_context, new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"}, null,  
  316.                 SSLConnectionSocketFactory.getDefaultHostnameVerifier());  
  317.     }  
  318. }  

 

 

     二、com.ning异步请求async-http-client

    1、引入文件

 

    

[java]  view plain  copy
 
  1. <dependency>  
  2.             <groupId>com.ning</groupId>  
  3.             <artifactId>async-http-client</artifactId>  
  4.             <version>1.9.40</version>  
  5.         </dependency>  

 

 

 

    2、http和https的方法封装

 

    涉及常用的post和get的请求,https的ssl双向证书验证。

 

[java]  view plain  copy
 
  1. import java.security.KeyStore;  
  2. import java.security.SecureRandom;  
  3. import java.util.Map;  
  4. import java.util.Set;  
  5. import java.util.concurrent.Future;  
  6.   
  7. import javax.net.ssl.KeyManagerFactory;  
  8. import javax.net.ssl.SSLContext;  
  9.   
  10. import org.springframework.core.io.ClassPathResource;  
  11. import org.springframework.core.io.Resource;  
  12.   
  13. import com.ning.http.client.AsyncHttpClient;  
  14. import com.ning.http.client.AsyncHttpClientConfig;  
  15. import com.ning.http.client.Response;  
  16.   
  17. /** 
  18.  * 创建时间:2016年11月8日 下午5:16:32 
  19.  *  
  20.  * @author andy 
  21.  * @version 2.2 
  22.  */  
  23. public class HttpKit {  
  24.       
  25.     private static final String DEFAULT_CHARSET = "UTF-8";  
  26.       
  27.     private static final int CONNECT_TIME_OUT = 5000; //链接超时时间3秒  
  28.   
  29.     private static SSLContext wx_ssl_context = null; //微信支付ssl证书  
  30.       
  31.     static{  
  32.           
  33.         Resource resource = new ClassPathResource("wx_apiclient_cert.p12"); //获取微信证书 或者直接从文件流读取  
  34.         char[] keyStorePassword = ConfigUtil.getProperty("wx.mchid").toCharArray(); //证书密码  
  35.         try {  
  36.             KeyStore keystore = KeyStore.getInstance("PKCS12");  
  37.             keystore.load(resource.getInputStream(), keyStorePassword);  
  38.             KeyManagerFactory keyManagerFactory = KeyManagerFactory  
  39.                     .getInstance(KeyManagerFactory.getDefaultAlgorithm());  
  40.             keyManagerFactory.init(keystore, keyStorePassword);  
  41.             SSLContext wx_ssl_context = SSLContext.getInstance("TLS");  
  42.             wx_ssl_context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());  
  43.         } catch (Exception e) {  
  44.             e.printStackTrace();  
  45.         }  
  46.     }  
  47.   
  48.     /** 
  49.      * @description 功能描述: get 请求 
  50.      * @param url 请求地址 
  51.      * @param params 参数 
  52.      * @param headers headers参数 
  53.      * @return 请求失败返回null 
  54.      */  
  55.     public static String get(String url, Map<String, String> params, Map<String, String> headers) {  
  56.         AsyncHttpClient http = new AsyncHttpClient(new AsyncHttpClientConfig.Builder()  
  57.                 .setConnectTimeout(CONNECT_TIME_OUT).build());  
  58.         AsyncHttpClient.BoundRequestBuilder builder = http.prepareGet(url);  
  59.         builder.setBodyEncoding(DEFAULT_CHARSET);  
  60.         if (params != null && !params.isEmpty()) {  
  61.             Set<String> keys = params.keySet();  
  62.             for (String key : keys) {  
  63.                 builder.addQueryParam(key, params.get(key));  
  64.             }  
  65.         }  
  66.   
  67.         if (headers != null && !headers.isEmpty()) {  
  68.             Set<String> keys = headers.keySet();  
  69.             for (String key : keys) {  
  70.                 builder.addHeader(key, params.get(key));  
  71.             }  
  72.         }  
  73.         Future<Response> f = builder.execute();  
  74.         String body = null;  
  75.         try {  
  76.             body = f.get().getResponseBody(DEFAULT_CHARSET);  
  77.         } catch (Exception e) {  
  78.             e.printStackTrace();  
  79.         }  
  80.         http.close();  
  81.         return body;  
  82.     }  
  83.   
  84.     /** 
  85.      * @description 功能描述: get 请求 
  86.      * @param url 请求地址 
  87.      * @return 请求失败返回null 
  88.      */  
  89.     public static String get(String url) {  
  90.         return get(url, null);  
  91.     }  
  92.   
  93.     /** 
  94.      * @description 功能描述: get 请求 
  95.      * @param url 请求地址 
  96.      * @param params 参数 
  97.      * @return 请求失败返回null 
  98.      */  
  99.     public static String get(String url, Map<String, String> params) {  
  100.         return get(url, params, null);  
  101.     }  
  102.   
  103.     /** 
  104.      * @description 功能描述: post 请求 
  105.      * @param url 请求地址 
  106.      * @param params 参数 
  107.      * @return 请求失败返回null 
  108.      */  
  109.     public static String post(String url, Map<String, String> params) {  
  110.         AsyncHttpClient http = new AsyncHttpClient(new AsyncHttpClientConfig.Builder()  
  111.                 .setConnectTimeout(CONNECT_TIME_OUT).build());  
  112.         AsyncHttpClient.BoundRequestBuilder builder = http.preparePost(url);  
  113.         builder.setBodyEncoding(DEFAULT_CHARSET);  
  114.         if (params != null && !params.isEmpty()) {  
  115.             Set<String> keys = params.keySet();  
  116.             for (String key : keys) {  
  117.                 builder.addQueryParam(key, params.get(key));  
  118.             }  
  119.         }  
  120.         Future<Response> f = builder.execute();  
  121.         String body = null;  
  122.         try {  
  123.             body = f.get().getResponseBody(DEFAULT_CHARSET);  
  124.         } catch (Exception e) {  
  125.             e.printStackTrace();  
  126.         }  
  127.         http.close();  
  128.         return body;  
  129.     }  
  130.   
  131.     /** 
  132.      * @description 功能描述: post 请求 
  133.      * @param url 请求地址 
  134.      * @param s 参数xml 
  135.      * @return 请求失败返回null 
  136.      */  
  137.     public static String post(String url, String s) {  
  138.         AsyncHttpClient http = new AsyncHttpClient(new AsyncHttpClientConfig.Builder()  
  139.                 .setConnectTimeout(CONNECT_TIME_OUT).build());  
  140.         AsyncHttpClient.BoundRequestBuilder builder = http.preparePost(url);  
  141.         builder.setBodyEncoding(DEFAULT_CHARSET);  
  142.         builder.setBody(s);  
  143.         Future<Response> f = builder.execute();  
  144.         String body = null;  
  145.         try {  
  146.             body = f.get().getResponseBody(DEFAULT_CHARSET);  
  147.         } catch (Exception e) {  
  148.             e.printStackTrace();  
  149.         }  
  150.         http.close();  
  151.         return body;  
  152.     }  
  153.   
  154.     /** 
  155.      * @description 功能描述: post https请求,服务器双向证书验证 
  156.      * @param url 请求地址 
  157.      * @param params 参数 
  158.      * @return 请求失败返回null 
  159.      */  
  160.     public static String posts(String url, Map<String, String> params){  
  161.   
  162.         AsyncHttpClient http = new AsyncHttpClient(  
  163.                 new AsyncHttpClientConfig.Builder()  
  164.                 .setConnectTimeout(CONNECT_TIME_OUT)  
  165.                 .setSSLContext(wx_ssl_context)  
  166.                 .build());  
  167.         AsyncHttpClient.BoundRequestBuilder bbuilder = http.preparePost(url);  
  168.         bbuilder.setBodyEncoding(DEFAULT_CHARSET);  
  169.         if (params != null && !params.isEmpty()) {  
  170.             Set<String> keys = params.keySet();  
  171.             for (String key : keys) {  
  172.                 bbuilder.addQueryParam(key, params.get(key));  
  173.             }  
  174.         }  
  175.         Future<Response> f = bbuilder.execute();  
  176.         String body = null;  
  177.         try {  
  178.             body = f.get().getResponseBody(DEFAULT_CHARSET);  
  179.         } catch (Exception e) {  
  180.             e.printStackTrace();  
  181.         }  
  182.         http.close();  
  183.         return body;  
  184.     }  
  185.   
  186.     /** 
  187.      * @description 功能描述: post https请求,服务器双向证书验证 
  188.      * @param url 请求地址 
  189.      * @param s 参数xml 
  190.      * @return 请求失败返回null 
  191.      */  
  192.     public static String posts(String url, String s) {  
  193.         AsyncHttpClient http = new AsyncHttpClient(  
  194.                 new AsyncHttpClientConfig.Builder()  
  195.                 .setConnectTimeout(CONNECT_TIME_OUT)  
  196.                 .setSSLContext(wx_ssl_context).build());  
  197.         AsyncHttpClient.BoundRequestBuilder builder = http.preparePost(url);  
  198.         builder.setBodyEncoding(DEFAULT_CHARSET);  
  199.         builder.setBody(s);  
  200.         Future<Response> f = builder.execute();  
  201.         String body = null;  
  202.         try {  
  203.             body = f.get().getResponseBody(DEFAULT_CHARSET);  
  204.         } catch (Exception e) {  
  205.             e.printStackTrace();  
  206.         }  
  207.         http.close();  
  208.         return body;  
  209.     }  
  210. }  



 

 

    三、测试

 

    相同结果下,对同一网络请求平均测试20次请求性能

         

   

    对于少量的网络请求来说httpclient和异步的async-http-client相差无几,甚至比异步还要快,但是在大量网络请求来说异步性能可能更高,但是上面需要优化如减少链接创建、设置超时时间、设置重试次数等等。

 

java 工具包, async-http-client-1.6.3.jar com.google.gson.DefaultDateTypeAdapter.class com.google.gson.ExclusionStrategy.class com.google.gson.FieldAttributes.class com.google.gson.FieldNamingPolicy.class com.google.gson.FieldNamingStrategy.class com.google.gson.Gson.class com.google.gson.GsonBuilder.class com.google.gson.InstanceCreator.class com.google.gson.JsonArray.class com.google.gson.JsonDeserializationContext.class com.google.gson.JsonDeserializer.class com.google.gson.JsonElement.class com.google.gson.JsonIOException.class com.google.gson.JsonNull.class com.google.gson.JsonObject.class com.google.gson.JsonParseException.class com.google.gson.JsonParser.class com.google.gson.JsonPrimitive.class com.google.gson.JsonSerializationContext.class com.google.gson.JsonSerializer.class com.google.gson.JsonStreamParser.class com.google.gson.JsonSyntaxException.class com.google.gson.LongSerializationPolicy.class com.google.gson.TreeTypeAdapter.class com.google.gson.TypeAdapter.class com.google.gson.TypeAdapterFactory.class com.google.gson.annotations.Expose.class com.google.gson.annotations.SerializedName.class com.google.gson.annotations.Since.class com.google.gson.annotations.Until.class com.google.gson.internal.ConstructorConstructor.class com.google.gson.internal.Excluder.class com.google.gson.internal.JsonReaderInternalAccess.class com.google.gson.internal.LazilyParsedNumber.class com.google.gson.internal.ObjectConstructor.class com.google.gson.internal.Primitives.class com.google.gson.internal.Streams.class com.google.gson.internal.StringMap.class com.google.gson.internal.UnsafeAllocator.class com.google.gson.internal.bind.ArrayTypeAdapter.class com.google.gson.internal.bind.CollectionTypeAdapterFactory.class com.google.gson.internal.bind.DateTypeAdapter.class com.google.gson.internal.bind.JsonTreeReader.class com.google.gson.internal.bind.JsonTreeWriter.class com.google.gson.internal.bind.MapTypeAdapterFactory.class com.google.gson.internal.bind.ObjectTypeAdapter.c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值