├── .gitignore ├── CHANGE-LOG.md ├── LICENSE.txt ├── README.md ├── apache-client ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── litesuits │ │ └── http │ │ └── impl │ │ └── apache │ │ ├── ApacheClient.java │ │ ├── DefaultHttpRequestRetryHandler.java │ │ ├── EntityBuilder.java │ │ ├── GZIPEntityWrapper.java │ │ ├── HttpPatch.java │ │ ├── HttpRetryHandler.java │ │ ├── MyLayeredSocketFactory.java │ │ ├── MySSLSocketFactory.java │ │ ├── NotThreadSafe.java │ │ ├── StandardHttpRequestRetryHandler.java │ │ ├── TrustSSLSocketFactory.java │ │ └── entity │ │ ├── AbstractHttpEntity.java │ │ ├── FileEntity.java │ │ ├── InputStreamEntity.java │ │ └── MultipartEntity.java │ └── res │ └── values │ └── strings.xml ├── build.gradle ├── docs ├── 1-first-use.md ├── 2-async-request.md ├── lite-http-0-大纲.md ├── lite-http-1-初始化和初步使用.md ├── lite-http-10-异步并发与调度策略.md ├── lite-http-11-全局配置与参数设置详解.md ├── lite-http-12-通过注解完成API请求.md ├── lite-http-13-多层缓存机制及用法.md ├── lite-http-14-回调监听器详解.md ├── lite-http-15-并发调度控制器详解.md ├── lite-http-2-简化请求和非安全方法的使用.md ├── lite-http-3-自动对象转化.md ├── lite-http-4-自定义DataParser和Json序列化库的替换.md ├── lite-http-5-文件、位图的上传和下载.md ├── lite-http-6-禁用网络和流量&耗时统计.md ├── lite-http-7-重试和重定向.md ├── lite-http-8-处理异常和取消请求.md ├── lite-http-9-POST方式的多种类型数据传输.md └── lite-http-引言.md ├── downloads ├── gson-2.3.jar ├── lite-go-1.0.0.jar ├── lite-http-3.0.0.jar ├── lite-http-3.0.1.jar ├── lite-http-3.1.3.6.jar └── 并发需要依赖lite-go组件.md ├── gradle └── wrapper │ └── gradle-wrapper.jar ├── gradlew ├── gradlew.bat ├── litehttp-sample ├── .gitignore ├── build.gradle ├── libs │ └── fastjson-1.2.5.jar └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── litesuits │ │ └── http │ │ └── sample │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── litesuits │ │ │ └── http │ │ │ ├── custom │ │ │ ├── CustomJSONParser.java │ │ │ ├── FastJson.java │ │ │ └── MyHttpExceptHandler.java │ │ │ ├── model │ │ │ ├── ApiModel.java │ │ │ ├── BaseModel.java │ │ │ ├── User.java │ │ │ └── api │ │ │ │ ├── RichParam.java │ │ │ │ └── UserParam.java │ │ │ └── sample │ │ │ ├── MainActivity.java │ │ │ └── Test.java │ └── res │ │ ├── drawable │ │ └── selector_list_item.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ └── list_item.xml │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── values-zh │ │ └── strings.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── litesuits │ └── http │ └── sample │ └── ExampleUnitTest.java ├── litehttp ├── .gitignore ├── build.gradle ├── libs │ ├── fastjson-1.2.5.jar │ ├── gson-2.3.jar │ ├── lite-go-1.0.0.jar │ └── lite-http-3.1.3.5.jar ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── litesuits │ │ │ └── http │ │ │ ├── HttpCache.java │ │ │ ├── HttpClient.java │ │ │ ├── HttpConfig.java │ │ │ ├── LiteHttp.java │ │ │ ├── annotation │ │ │ ├── HttpBaseUrl.java │ │ │ ├── HttpCacheExpire.java │ │ │ ├── HttpCacheKey.java │ │ │ ├── HttpCacheMode.java │ │ │ ├── HttpCharSet.java │ │ │ ├── HttpID.java │ │ │ ├── HttpMaxRedirect.java │ │ │ ├── HttpMaxRetry.java │ │ │ ├── HttpMethod.java │ │ │ ├── HttpTag.java │ │ │ └── HttpUri.java │ │ │ ├── data │ │ │ ├── Charsets.java │ │ │ ├── Consts.java │ │ │ ├── FastJson.java │ │ │ ├── GsonImpl.java │ │ │ ├── HttpStatus.java │ │ │ ├── Json.java │ │ │ ├── NameValuePair.java │ │ │ ├── StatisticsInfo.java │ │ │ └── TypeToken.java │ │ │ ├── exception │ │ │ ├── ClientException.java │ │ │ ├── HttpClientException.java │ │ │ ├── HttpException.java │ │ │ ├── HttpNetException.java │ │ │ ├── HttpServerException.java │ │ │ ├── NetException.java │ │ │ ├── ServerException.java │ │ │ └── handler │ │ │ │ └── HttpExceptionHandler.java │ │ │ ├── impl │ │ │ └── huc │ │ │ │ ├── HttpUrlClient.java │ │ │ │ └── RetryHandler.java │ │ │ ├── listener │ │ │ ├── GlobalHttpListener.java │ │ │ ├── HttpListener.java │ │ │ └── StatisticsListener.java │ │ │ ├── log │ │ │ └── HttpLog.java │ │ │ ├── network │ │ │ └── Network.java │ │ │ ├── parser │ │ │ ├── DataParser.java │ │ │ ├── FileCacheableParser.java │ │ │ ├── MemCacheableParser.java │ │ │ └── impl │ │ │ │ ├── BitmapParser.java │ │ │ │ ├── BytesParser.java │ │ │ │ ├── FileParser.java │ │ │ │ ├── JsonParser.java │ │ │ │ └── StringParser.java │ │ │ ├── request │ │ │ ├── AbstractRequest.java │ │ │ ├── BitmapRequest.java │ │ │ ├── BytesRequest.java │ │ │ ├── FileRequest.java │ │ │ ├── JsonAbsRequest.java │ │ │ ├── JsonRequest.java │ │ │ ├── StringRequest.java │ │ │ ├── content │ │ │ │ ├── ByteArrayBody.java │ │ │ │ ├── FileBody.java │ │ │ │ ├── HttpBody.java │ │ │ │ ├── InputStreamBody.java │ │ │ │ ├── JsonBody.java │ │ │ │ ├── SerializableBody.java │ │ │ │ ├── StringBody.java │ │ │ │ ├── UrlEncodedFormBody.java │ │ │ │ └── multi │ │ │ │ │ ├── AbstractPart.java │ │ │ │ │ ├── BoundaryCreater.java │ │ │ │ │ ├── BytesPart.java │ │ │ │ │ ├── FilePart.java │ │ │ │ │ ├── InputStreamPart.java │ │ │ │ │ ├── MultipartBody.java │ │ │ │ │ └── StringPart.java │ │ │ ├── param │ │ │ │ ├── CacheMode.java │ │ │ │ ├── HttpCustomParam.java │ │ │ │ ├── HttpMethods.java │ │ │ │ ├── HttpParam.java │ │ │ │ ├── HttpParamModel.java │ │ │ │ ├── HttpReplace.java │ │ │ │ ├── HttpRichParamModel.java │ │ │ │ └── NonHttpParam.java │ │ │ └── query │ │ │ │ ├── JsonQueryBuilder.java │ │ │ │ ├── ModelQueryBuilder.java │ │ │ │ └── SimpleQueryBuilder.java │ │ │ ├── response │ │ │ ├── InternalResponse.java │ │ │ └── Response.java │ │ │ └── utils │ │ │ ├── HexUtil.java │ │ │ ├── HttpUtil.java │ │ │ ├── MD5Util.java │ │ │ ├── StringCodingUtils.java │ │ │ └── UriUtil.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── litesuits │ └── http │ └── ExampleUnitTest.java ├── settings.gradle └── web-server-sample ├── lib ├── javax.annotation.jar ├── javax.ejb.jar ├── javax.jms.jar ├── javax.persistence.jar ├── javax.resource.jar ├── javax.servlet.jar ├── javax.servlet.jsp.jar ├── javax.servlet.jsp.jstl.jar └── javax.transaction.jar ├── src └── com │ └── litesuits │ └── server │ └── PostReceiver.java └── web ├── WEB-INF ├── lib │ ├── commons-codec-1.9.jar │ ├── commons-fileupload-1.3.1.jar │ ├── commons-io-2.4.jar │ ├── commons-logging-1.2.jar │ ├── fluent-hc-4.4.1.jar │ ├── httpclient-4.4.1.jar │ ├── httpclient-cache-4.4.1.jar │ ├── httpclient-win-4.4.1.jar │ ├── httpcore-4.4.1.jar │ ├── httpmime-4.4.1.jar │ ├── jna-4.1.0.jar │ └── jna-platform-4.1.0.jar └── web.xml └── index.jsp /.gitignore: -------------------------------------------------------------------------------- 1 | # root files 2 | 3 | # built application files 4 | *.apk 5 | *.ap_ 6 | .gradle 7 | 8 | # files for the dex VM 9 | *.dex 10 | 11 | # Java class files 12 | *.class 13 | 14 | # generated files 15 | bin/ 16 | gen/ 17 | out/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | *.properties 22 | proguard-project.txt 23 | 24 | # Eclipse project files 25 | .classpath 26 | .project 27 | .settings 28 | 29 | # Proguard folder generated by Eclipse 30 | proguard/ 31 | 32 | # Intellij project files 33 | *.iml 34 | *.ipr 35 | *.iws 36 | .idea/ 37 | 38 | .gradle 39 | 40 | .DS_Store 41 | -------------------------------------------------------------------------------- /CHANGE-LOG.md: -------------------------------------------------------------------------------- 1 | Change Log 2 | 3 | 1.0 Features 4 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 5 | * 1. 单线程:基于当前线程高效率运作。 6 | * 2. 轻量级:微小的内存开销与Jar包体积,仅约 86K 。 7 | * 3. 全支持:GET, POST, PUT, DELETE, HEAD, TRACE, OPTIONS, PATCH. 8 | * 4. 全自动:一行代码将请求Java Model 转化为 Http Parameter,结果Json String 转化为 Java Model 。 9 | * 5. 易拓展:自定义 DataParser,将网络数据流自由转化为你想要的任意数据类型。 10 | * 6. 基于接口:架构灵活,轻松替换网络连接方式的核心实现方式,以及 Json 序列化库。 11 | * 7. 文件上传:支持单个、多个大文件上传。 12 | * 8. 文件下载:支持文件、Bimtap下载及其进度通知。 13 | * 9. 网络禁用:快速禁用一种、多种网络环境,比如禁用 2G,3G 。 14 | * 10. 数据统计:链接、读取时长统计,以及流量统计。 15 | * 11. 异常体系:统一的异常处理体系,简明清晰地抛出可再细分的三大类异常:客户端、网络、服务器异常。 16 | * 12. GZIP压缩:Request, Response 自动 GZIP 压缩节省流量。 17 | * 13. 自动重试:结合探测异常类型和当前网络状况,智能执行重试策略。 18 | * 14. 自动重定向:基于 30X 状态的重试,且可设置最大次数防止过度跳转。 19 | * 15. 自带简单异步执行器,方便开发者实现异步请求方案。 20 | 21 | 22 | 2.0 Features 23 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 24 | * 1. 可配置:更多更灵活的配置选择项,多达 23+ 项。 25 | * 2. 多态化:更加直观的API,输入和输出更加明确。 26 | * 3. 强并发:智能高效的并发调度,有效控制核心并发与队列控制策略。 27 | * 4. 注解化:信息配置约定更多样,如果你喜欢,可以注解 API、Method、ID、TAG、CacheMode 等参数。 28 | * 5. 多层缓存:内存命中更高效!支持多样的缓存模式,支持设置缓存有效期。 29 | * 6. 完善回调:自由设置回调当前或UI线程,自由开启上传、下载进度通知。 30 | * 7. 完善构建:提供 jar 包支持,后边支持 gradle 和 maven 。 31 | 32 | 2.2.0 33 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 34 | 1. 修复某些情况下参数无法拼接到URI的bug; 35 | 2. http参数类可以注解指定Key,避免成员变量出现java关键词,同时增加动态URL构建; 36 | 3. Request接受直接注解参数、内部构建参数(此特性已删除)。 37 | 38 | 2.3.0 39 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 40 | 1. 注解参数动态化; 41 | 2. 优化HttpRichParamModel的使用。 42 | 43 | 3.0.0 44 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 45 | 1. 添加HttpUrlConnection支持,并设置为默认HTTP客户端引擎。 46 | 2. 将Apache HTTP Client移到独立项目。 47 | 3. 优化HttpConfig的体验。 48 | 49 | 3.1.0 50 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 51 | 1. 添加通过 dir 和 key 删除缓存的方法 52 | 53 | 3.1.1 54 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 55 | 1. 修改 Request基类的 属性参数 和 extra map 参数的覆盖顺序。 56 | 57 | 3.1.3.6 58 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 59 | 1. 注意要引入 lite-go 类库 60 | 2. 解决request参数的Encode问题,解决在默写编译器下的Map遍历时泛型丢失引起的强转String问题 61 | -------------------------------------------------------------------------------- /apache-client/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /apache-client/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | minSdkVersion 9 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | testCompile 'junit:junit:4.12' 24 | provided project(':litehttp') 25 | } 26 | -------------------------------------------------------------------------------- /apache-client/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/matianyu/develop/android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /apache-client/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /apache-client/src/main/java/com/litesuits/http/impl/apache/EntityBuilder.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.impl.apache; 2 | 3 | import com.litesuits.http.data.Consts; 4 | import com.litesuits.http.exception.HttpClientException; 5 | import com.litesuits.http.impl.apache.entity.FileEntity; 6 | import com.litesuits.http.impl.apache.entity.InputStreamEntity; 7 | import com.litesuits.http.impl.apache.entity.MultipartEntity; 8 | import com.litesuits.http.request.AbstractRequest; 9 | import com.litesuits.http.request.content.*; 10 | import com.litesuits.http.request.content.multi.MultipartBody; 11 | import org.apache.http.HttpEntity; 12 | import org.apache.http.entity.ByteArrayEntity; 13 | import org.apache.http.entity.StringEntity; 14 | 15 | /** 16 | * help us to build {@link org.apache.http.HttpEntity} 17 | * 18 | * @author MaTianyu 19 | * 2014-1-18上午1:41:41 20 | */ 21 | public class EntityBuilder { 22 | 23 | public static HttpEntity build(AbstractRequest req) throws HttpClientException { 24 | try { 25 | HttpBody body = req.getHttpBody(); 26 | if (body != null) { 27 | req.addHeader(Consts.CONTENT_TYPE, body.getContentType()); 28 | if (body instanceof StringBody) { 29 | // StringBody JsonBody UrlEncodedFormBody 30 | StringBody b = (StringBody) body; 31 | return new StringEntity(b.getString(), b.getCharset()); 32 | } else if (body instanceof ByteArrayBody) { 33 | // ByteArrayBody SerializableBody 34 | ByteArrayBody b = (ByteArrayBody) body; 35 | return new ByteArrayEntity(b.getBytes()); 36 | } else if (body instanceof InputStreamBody) { 37 | InputStreamBody b = (InputStreamBody) body; 38 | return new InputStreamEntity(b.getInstream(), b.getInstream().available(), req); 39 | } else if (body instanceof FileBody) { 40 | FileBody b = (FileBody) body; 41 | return new FileEntity(b.getFile(), b.getContentType(), req); 42 | } else if (body instanceof MultipartBody) { 43 | return new MultipartEntity((MultipartBody) body); 44 | } else { 45 | throw new RuntimeException("Unpredictable Entity Body(非法实体)"); 46 | } 47 | } 48 | } catch (Exception e) { 49 | throw new HttpClientException(e); 50 | } 51 | return null; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /apache-client/src/main/java/com/litesuits/http/impl/apache/GZIPEntityWrapper.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.impl.apache; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.zip.GZIPInputStream; 6 | 7 | import org.apache.http.HttpEntity; 8 | import org.apache.http.entity.HttpEntityWrapper; 9 | 10 | /** 11 | * Enclosing inputstream for gzip decoded data. 12 | * Improve network transmission speed quite a lot. 13 | * 14 | * @author MaTianyu 15 | * 2014-1-1下午7:39:45 16 | */ 17 | class GZIPEntityWrapper extends HttpEntityWrapper { 18 | public GZIPEntityWrapper(HttpEntity wrapped) { 19 | super(wrapped); 20 | } 21 | 22 | @Override 23 | public InputStream getContent() throws IOException { 24 | return new GZIPInputStream(wrappedEntity.getContent()); 25 | } 26 | 27 | @Override 28 | public long getContentLength() { 29 | //unknown 30 | return -1; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /apache-client/src/main/java/com/litesuits/http/impl/apache/HttpPatch.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, 14 | * software distributed under the License is distributed on an 15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | * KIND, either express or implied. See the License for the 17 | * specific language governing permissions and limitations 18 | * under the License. 19 | * ==================================================================== 20 | * 21 | * This software consists of voluntary contributions made by many 22 | * individuals on behalf of the Apache Software Foundation. For more 23 | * information on the Apache Software Foundation, please see 24 | * . 25 | * 26 | */ 27 | 28 | package com.litesuits.http.impl.apache; 29 | 30 | import java.net.URI; 31 | 32 | import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; 33 | 34 | /** 35 | * HTTP PATCH method. 36 | *

37 | * The HTTP PATCH method is defined in RF5789:

The PATCH 39 | * method requests that a set of changes described in the request entity be 40 | * applied to the resource identified by the Request- URI. Differs from the PUT 41 | * method in the way the server processes the enclosed entity to modify the 42 | * resource identified by the Request-URI. In a PUT request, the enclosed entity 43 | * origin server, and the client is requesting that the stored version be 44 | * replaced. With PATCH, however, the enclosed entity contains a set of 45 | * instructions describing how a resource currently residing on the origin 46 | * server should be modified to produce a new version.
47 | *

48 | * 49 | * @since 4.2 50 | */ 51 | @NotThreadSafe 52 | public class HttpPatch extends HttpEntityEnclosingRequestBase { 53 | 54 | public final static String METHOD_NAME = "PATCH"; 55 | 56 | public HttpPatch() { 57 | super(); 58 | } 59 | 60 | public HttpPatch(final URI uri) { 61 | super(); 62 | setURI(uri); 63 | } 64 | 65 | public HttpPatch(final String uri) { 66 | super(); 67 | setURI(URI.create(uri)); 68 | } 69 | 70 | @Override 71 | public String getMethod() { 72 | return METHOD_NAME; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /apache-client/src/main/java/com/litesuits/http/impl/apache/MyLayeredSocketFactory.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.impl.apache; 2 | 3 | import java.io.IOException; 4 | import java.lang.reflect.Field; 5 | import java.net.InetAddress; 6 | import java.net.Socket; 7 | 8 | import javax.net.SocketFactory; 9 | 10 | import org.apache.http.conn.scheme.LayeredSocketFactory; 11 | import org.apache.http.conn.ssl.SSLSocketFactory; 12 | import org.apache.http.params.HttpParams; 13 | 14 | 15 | /** 16 | * Android had a bug where HTTPS made reverse DNS lookups (fixed in Ice Cream Sandwich) 17 | * http://code.google.com/p/android/issues/detail?id=13117 18 | * 19 | * @author MaTianyu 20 | * 2014-1-10上午12:17:04 21 | */ 22 | public class MyLayeredSocketFactory implements LayeredSocketFactory { 23 | SSLSocketFactory delegate = SSLSocketFactory.getSocketFactory(); 24 | 25 | @Override 26 | public Socket createSocket() throws IOException { 27 | return delegate.createSocket(); 28 | } 29 | 30 | @Override 31 | public Socket connectSocket(Socket sock, String host, int port, InetAddress localAddress, int localPort, HttpParams params) 32 | throws IOException { 33 | return delegate.connectSocket(sock, host, port, localAddress, localPort, params); 34 | } 35 | 36 | @Override 37 | public boolean isSecure(Socket sock) throws IllegalArgumentException { 38 | return delegate.isSecure(sock); 39 | } 40 | 41 | @Override 42 | public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { 43 | injectHostname(socket, host); 44 | return delegate.createSocket(socket, host, port, autoClose); 45 | } 46 | 47 | private void injectHostname(Socket socket, String host) { 48 | try { 49 | Field field = InetAddress.class.getDeclaredField("hostName"); 50 | field.setAccessible(true); 51 | field.set(socket.getInetAddress(), host); 52 | } catch (Exception ignored) { 53 | } 54 | } 55 | }; -------------------------------------------------------------------------------- /apache-client/src/main/java/com/litesuits/http/impl/apache/MySSLSocketFactory.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.impl.apache; 2 | 3 | import org.apache.http.conn.ssl.SSLSocketFactory; 4 | 5 | import javax.net.ssl.SSLContext; 6 | import javax.net.ssl.TrustManager; 7 | import javax.net.ssl.X509TrustManager; 8 | import java.io.IOException; 9 | import java.net.Socket; 10 | import java.security.*; 11 | 12 | /** 13 | * This file is introduced to fix HTTPS Post bug on API < ICS see 14 | * http://code.google.com/p/android/issues/detail?id=13117#c14

 

Warning! This omits SSL 15 | * certificate validation on every device, use with caution 16 | */ 17 | public class MySSLSocketFactory extends SSLSocketFactory { 18 | SSLContext sslContext = SSLContext.getInstance("TLS"); 19 | 20 | public MySSLSocketFactory(KeyStore truststore) 21 | throws NoSuchAlgorithmException, KeyManagementException, 22 | KeyStoreException, UnrecoverableKeyException { 23 | super(truststore); 24 | 25 | TrustManager tm = new X509TrustManager() { 26 | public java.security.cert.X509Certificate[] getAcceptedIssuers() { 27 | return null; 28 | } 29 | 30 | @Override 31 | public void checkClientTrusted( 32 | java.security.cert.X509Certificate[] chain, String authType) 33 | throws java.security.cert.CertificateException { 34 | } 35 | 36 | @Override 37 | public void checkServerTrusted( 38 | java.security.cert.X509Certificate[] chain, String authType) 39 | throws java.security.cert.CertificateException { 40 | } 41 | }; 42 | sslContext.init(null, new TrustManager[]{tm}, null); 43 | } 44 | 45 | @Override 46 | public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { 47 | return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); 48 | } 49 | 50 | @Override 51 | public Socket createSocket() throws IOException { 52 | return sslContext.getSocketFactory().createSocket(); 53 | } 54 | 55 | public static KeyStore getKeystore() { 56 | KeyStore trustStore = null; 57 | try { 58 | trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 59 | trustStore.load(null, null); 60 | } catch (Throwable t) { 61 | t.printStackTrace(); 62 | } 63 | return trustStore; 64 | } 65 | 66 | public static SSLSocketFactory getFixedSocketFactory() { 67 | SSLSocketFactory socketFactory; 68 | try { 69 | socketFactory = new MySSLSocketFactory(getKeystore()); 70 | socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 71 | } catch (Throwable t) { 72 | t.printStackTrace(); 73 | socketFactory = SSLSocketFactory.getSocketFactory(); 74 | } 75 | return socketFactory; 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /apache-client/src/main/java/com/litesuits/http/impl/apache/NotThreadSafe.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, 14 | * software distributed under the License is distributed on an 15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | * KIND, either express or implied. See the License for the 17 | * specific language governing permissions and limitations 18 | * under the License. 19 | * ==================================================================== 20 | * 21 | * This software consists of voluntary contributions made by many 22 | * individuals on behalf of the Apache Software Foundation. For more 23 | * information on the Apache Software Foundation, please see 24 | * . 25 | * 26 | */ 27 | package com.litesuits.http.impl.apache; 28 | 29 | import java.lang.annotation.Documented; 30 | import java.lang.annotation.ElementType; 31 | import java.lang.annotation.Retention; 32 | import java.lang.annotation.RetentionPolicy; 33 | import java.lang.annotation.Target; 34 | 35 | /** 36 | * The class to which this annotation is applied is not thread-safe. 37 | * This annotation primarily exists for clarifying the non-thread-safety of a class 38 | * that might otherwise be assumed to be thread-safe, despite the fact that it is a bad 39 | * idea to assume a class is thread-safe without good reason. 40 | * 41 | * @see ThreadSafe 42 | *

43 | * Based on code developed by Brian Goetz and Tim Peierls and concepts 44 | * published in 'Java Concurrency in Practice' by Brian Goetz, Tim Peierls, 45 | * Joshua Bloch, Joseph Bowbeer, David Holmes and Doug Lea. 46 | */ 47 | @Documented 48 | @Target(ElementType.TYPE) 49 | @Retention(RetentionPolicy.CLASS) // The original version used RUNTIME 50 | public @interface NotThreadSafe { 51 | } 52 | -------------------------------------------------------------------------------- /apache-client/src/main/java/com/litesuits/http/impl/apache/StandardHttpRequestRetryHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, 14 | * software distributed under the License is distributed on an 15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | * KIND, either express or implied. See the License for the 17 | * specific language governing permissions and limitations 18 | * under the License. 19 | * ==================================================================== 20 | * 21 | * This software consists of voluntary contributions made by many 22 | * individuals on behalf of the Apache Software Foundation. For more 23 | * information on the Apache Software Foundation, please see 24 | * . 25 | * 26 | */ 27 | 28 | package com.litesuits.http.impl.apache; 29 | 30 | import org.apache.http.HttpRequest; 31 | 32 | import java.util.Locale; 33 | import java.util.Map; 34 | import java.util.concurrent.ConcurrentHashMap; 35 | 36 | /** 37 | * {@link org.apache.http.client.HttpRequestRetryHandler} which assumes 38 | * that all requested HTTP methods which should be idempotent according 39 | * to RFC-2616 are in fact idempotent and can be retried. 40 | *

41 | * According to RFC-2616 section 9.1.2 the idempotent HTTP methods are: 42 | * GET, HEAD, PUT, DELETE, OPTIONS, and TRACE 43 | * 44 | * @since 4.2 45 | */ 46 | public class StandardHttpRequestRetryHandler extends DefaultHttpRequestRetryHandler { 47 | 48 | private final Map idempotentMethods; 49 | 50 | /** 51 | * Default constructor 52 | */ 53 | public StandardHttpRequestRetryHandler(final int retryCount, final boolean requestSentRetryEnabled) { 54 | super(retryCount, requestSentRetryEnabled); 55 | this.idempotentMethods = new ConcurrentHashMap(); 56 | this.idempotentMethods.put("GET", Boolean.TRUE); 57 | this.idempotentMethods.put("HEAD", Boolean.TRUE); 58 | this.idempotentMethods.put("PUT", Boolean.TRUE); 59 | this.idempotentMethods.put("DELETE", Boolean.TRUE); 60 | this.idempotentMethods.put("OPTIONS", Boolean.TRUE); 61 | this.idempotentMethods.put("TRACE", Boolean.TRUE); 62 | } 63 | 64 | /** 65 | * Default constructor 66 | */ 67 | public StandardHttpRequestRetryHandler() { 68 | this(3, false); 69 | } 70 | 71 | @Override 72 | protected boolean handleAsIdempotent(final HttpRequest request) { 73 | if (request == null) { 74 | return true; 75 | } 76 | final String method = request.getRequestLine().getMethod().toUpperCase(Locale.US); 77 | final Boolean b = this.idempotentMethods.get(method); 78 | return b != null && b.booleanValue(); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /apache-client/src/main/java/com/litesuits/http/impl/apache/TrustSSLSocketFactory.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.impl.apache; 2 | 3 | import java.io.IOException; 4 | import java.net.Socket; 5 | import java.security.KeyManagementException; 6 | import java.security.KeyStore; 7 | import java.security.KeyStoreException; 8 | import java.security.NoSuchAlgorithmException; 9 | import java.security.UnrecoverableKeyException; 10 | 11 | import javax.net.ssl.SSLContext; 12 | import javax.net.ssl.TrustManager; 13 | import javax.net.ssl.X509TrustManager; 14 | 15 | import org.apache.http.conn.ssl.SSLSocketFactory; 16 | 17 | /** 18 | * fixed https request bug 19 | * 20 | * @author MaTianyu 21 | * 2014-1-1下午5:09:33 22 | */ 23 | class TrustSSLSocketFactory extends SSLSocketFactory { 24 | SSLContext sslContext = SSLContext.getInstance("TLS"); 25 | 26 | private TrustSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, 27 | UnrecoverableKeyException { 28 | super(truststore); 29 | TrustManager tm = new X509TrustManager() { 30 | public java.security.cert.X509Certificate[] getAcceptedIssuers() { 31 | return null; 32 | } 33 | 34 | @Override 35 | public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) 36 | throws java.security.cert.CertificateException { 37 | } 38 | 39 | @Override 40 | public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) 41 | throws java.security.cert.CertificateException { 42 | } 43 | }; 44 | sslContext.init(null, new TrustManager[]{tm}, null); 45 | } 46 | 47 | @Override 48 | public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { 49 | return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); 50 | } 51 | 52 | @Override 53 | public Socket createSocket() throws IOException { 54 | return sslContext.getSocketFactory().createSocket(); 55 | } 56 | 57 | public static SSLSocketFactory getSocketFactory() { 58 | SSLSocketFactory socketFactory; 59 | try { 60 | KeyStore trustStore = getKeyStore(); 61 | socketFactory = new TrustSSLSocketFactory(trustStore); 62 | socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 63 | } catch (Throwable t) { 64 | t.printStackTrace(); 65 | socketFactory = SSLSocketFactory.getSocketFactory(); 66 | } 67 | return socketFactory; 68 | } 69 | 70 | public static KeyStore getKeyStore() { 71 | KeyStore trustStore = null; 72 | try { 73 | trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 74 | trustStore.load(null, null); 75 | } catch (Throwable t) { 76 | t.printStackTrace(); 77 | } 78 | return trustStore; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /apache-client/src/main/java/com/litesuits/http/impl/apache/entity/FileEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, 14 | * software distributed under the License is distributed on an 15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | * KIND, either express or implied. See the License for the 17 | * specific language governing permissions and limitations 18 | * under the License. 19 | * ==================================================================== 20 | * 21 | * This software consists of voluntary contributions made by many 22 | * individuals on behalf of the Apache Software Foundation. For more 23 | * information on the Apache Software Foundation, please see 24 | * . 25 | * 26 | */ 27 | 28 | package com.litesuits.http.impl.apache.entity; 29 | 30 | import com.litesuits.http.request.AbstractRequest; 31 | 32 | import java.io.*; 33 | 34 | /** 35 | * A self contained, repeatable entity that obtains its content from a file. 36 | * 37 | * @since 4.0 38 | */ 39 | public class FileEntity extends AbstractHttpEntity implements Cloneable { 40 | 41 | protected final File file; 42 | 43 | public FileEntity(final File file, final String contentType, AbstractRequest request) { 44 | super(); 45 | if (file == null) { 46 | throw new IllegalArgumentException("File may not be null"); 47 | } 48 | this.file = file; 49 | setContentType(contentType); 50 | setRequest(request); 51 | } 52 | 53 | public boolean isRepeatable() { 54 | return true; 55 | } 56 | 57 | public long getContentLength() { 58 | return this.file.length(); 59 | } 60 | 61 | public InputStream getContent() throws IOException { 62 | return new FileInputStream(this.file); 63 | } 64 | 65 | /** 66 | * modified by MaTianyu 67 | */ 68 | public void writeTo(final OutputStream outstream) throws IOException { 69 | if (outstream == null) { 70 | throw new IllegalArgumentException("Output stream may not be null"); 71 | } 72 | bytesWritten = 0; 73 | totalSize = file.length(); 74 | InputStream instream = new FileInputStream(this.file); 75 | try { 76 | byte[] tmp = new byte[BUFFER_SIZE]; 77 | int l; 78 | while ((l = instream.read(tmp)) != -1) { 79 | outstream.write(tmp, 0, l); 80 | updateProgress(l); 81 | } 82 | outstream.flush(); 83 | } finally { 84 | instream.close(); 85 | } 86 | } 87 | 88 | /** 89 | * Tells that this entity is not streaming. 90 | * 91 | * @return false 92 | */ 93 | public boolean isStreaming() { 94 | return false; 95 | } 96 | 97 | } // class FileEntity 98 | -------------------------------------------------------------------------------- /apache-client/src/main/java/com/litesuits/http/impl/apache/entity/InputStreamEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, 14 | * software distributed under the License is distributed on an 15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | * KIND, either express or implied. See the License for the 17 | * specific language governing permissions and limitations 18 | * under the License. 19 | * ==================================================================== 20 | * 21 | * This software consists of voluntary contributions made by many 22 | * individuals on behalf of the Apache Software Foundation. For more 23 | * information on the Apache Software Foundation, please see 24 | * . 25 | * 26 | */ 27 | 28 | package com.litesuits.http.impl.apache.entity; 29 | 30 | import com.litesuits.http.request.AbstractRequest; 31 | 32 | import java.io.IOException; 33 | import java.io.InputStream; 34 | import java.io.OutputStream; 35 | 36 | /** 37 | * A streamed, non-repeatable entity that obtains its content from 38 | * an {@link InputStream}. 39 | * 40 | * @since 4.0 41 | */ 42 | public class InputStreamEntity extends AbstractHttpEntity { 43 | 44 | private final InputStream content; 45 | private final long length; 46 | private boolean consumed = false; 47 | 48 | public InputStreamEntity(final InputStream instream, long length, AbstractRequest request) { 49 | super(); 50 | if (instream == null) { 51 | throw new IllegalArgumentException("Source input stream may not be null"); 52 | } 53 | this.content = instream; 54 | this.length = length; 55 | setRequest(request); 56 | } 57 | 58 | public boolean isRepeatable() { 59 | return false; 60 | } 61 | 62 | public long getContentLength() { 63 | return this.length; 64 | } 65 | 66 | public InputStream getContent() throws IOException { 67 | return this.content; 68 | } 69 | 70 | /** 71 | * modified by MaTianyu 72 | */ 73 | public void writeTo(final OutputStream outstream) throws IOException { 74 | if (outstream == null) { 75 | throw new IllegalArgumentException("Output stream may not be null"); 76 | } 77 | InputStream instream = this.content; 78 | byte[] buffer = new byte[BUFFER_SIZE]; 79 | int l; 80 | bytesWritten = 0; 81 | if (this.length < 0) { 82 | totalSize = instream.available(); 83 | // consume until EOF 84 | while ((l = instream.read(buffer)) != -1) { 85 | outstream.write(buffer, 0, l); 86 | updateProgress(l); 87 | } 88 | } else { 89 | // consume no more than length 90 | totalSize = this.length; 91 | long remaining = this.length; 92 | while (remaining > 0) { 93 | l = instream.read(buffer, 0, (int) Math.min(BUFFER_SIZE, remaining)); 94 | if (l == -1) { 95 | break; 96 | } 97 | outstream.write(buffer, 0, l); 98 | updateProgress(l); 99 | remaining -= l; 100 | } 101 | } 102 | this.consumed = true; 103 | } 104 | 105 | // non-javadoc, see interface HttpEntity 106 | public boolean isStreaming() { 107 | return !this.consumed; 108 | } 109 | 110 | // non-javadoc, see interface HttpEntity 111 | public void consumeContent() throws IOException { 112 | this.consumed = true; 113 | // If the input stream is from a connection, closing it will read to 114 | // the end of the content. Otherwise, we don't care what it does. 115 | this.content.close(); 116 | } 117 | 118 | } // class InputStreamEntity 119 | -------------------------------------------------------------------------------- /apache-client/src/main/java/com/litesuits/http/impl/apache/entity/MultipartEntity.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.impl.apache.entity; 2 | 3 | import com.litesuits.http.request.content.multi.MultipartBody; 4 | import org.apache.http.Header; 5 | import org.apache.http.HttpEntity; 6 | import org.apache.http.message.BasicHeader; 7 | 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.OutputStream; 11 | 12 | 13 | /** 14 | * Simplified multipart entity mainly used for sending one or more files. 15 | * 16 | * @author MaTianyu 17 | */ 18 | public class MultipartEntity implements HttpEntity { 19 | 20 | private boolean isRepeatable = false; 21 | private MultipartBody multipartBody; 22 | 23 | public MultipartEntity(MultipartBody multipartBody) { 24 | this.multipartBody = multipartBody; 25 | } 26 | 27 | @Override 28 | public long getContentLength() { 29 | return multipartBody.getContentLength(); 30 | } 31 | 32 | @Override 33 | public Header getContentType() { 34 | return new BasicHeader("Content-Type", multipartBody.getContentType()); 35 | } 36 | 37 | @Override 38 | public void writeTo(final OutputStream outstream) throws IOException { 39 | multipartBody.writeTo(outstream); 40 | } 41 | 42 | @Override 43 | public boolean isChunked() { 44 | return false; 45 | } 46 | 47 | public void setIsRepeatable(boolean isRepeatable) { 48 | this.isRepeatable = isRepeatable; 49 | } 50 | 51 | @Override 52 | public boolean isRepeatable() { 53 | return isRepeatable; 54 | } 55 | 56 | @Override 57 | public boolean isStreaming() { 58 | return false; 59 | } 60 | 61 | @Override 62 | public Header getContentEncoding() { 63 | return null; 64 | } 65 | 66 | @Override 67 | public void consumeContent() throws IOException, UnsupportedOperationException { 68 | if (isStreaming()) { 69 | throw new UnsupportedOperationException("Streaming entity does not implement #consumeContent()"); 70 | } 71 | } 72 | 73 | @Override 74 | public InputStream getContent() throws IOException, UnsupportedOperationException { 75 | throw new UnsupportedOperationException("getContent() is not supported. Use writeTo() instead."); 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /apache-client/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | litehttp-v3-apache-client 3 | 4 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.1.0' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /docs/1-first-use.md: -------------------------------------------------------------------------------- 1 | # Android网络通信框架 LiteHttp2.0 实用教程 2 | 3 | 标签(空格分隔): litehttp教程 android网络通信教程 android http http最佳实践 4 | 5 | --- 6 | 7 |     本系列文章面向各级别尤其中高级android开发者,将展示开源网络通信框架LiteHttp的核心用法,讲解其关键功能的运作原理。 8 |     希望可以让开发者既能熟练使用、修改开源HTTP框架高效完成日常开发任务,又能深入理解litehttp类库本身以及android网络通信相关知识。同时传达了一些框架作者在日常开发中的一些最佳实践,仅作抛砖引玉。 9 | 10 | ##第一节:初步使用 11 | 12 | ###初始化及单例 13 | 14 | 初始化LiteHttp需要传入一个HttpConfig的实例来配置各项参数,不传入即表示使用全部使用默认设置。 15 | 16 | 需要注意的是,一个App仅需要构建一个LiteHttp的实例即可,即单例模式,这样才能最节省系统资源,多个实例并不提升效率。 17 | 18 | 使用默认配置: 19 | ```java 20 | LiteHttp liteHttp = LiteHttp.newApacheHttpClient(null); 21 | ``` 22 | 23 | 简单自定义配置: 24 | ```java 25 | HttpConfig config = new HttpConfig(activity); 26 | 27 | // set app context 28 | config.setContext(activity); 29 | 30 | // custom User-Agent 31 | config.setUserAgent("Mozilla/5.0 (...)"); 32 | 33 | // connect timeout: 10s, socket timeout: 10s 34 | config.setTimeOut(10000, 10000); 35 | 36 | // new with config 37 | LiteHttp liteHttp = LiteHttp.newApacheHttpClient(config); 38 | ``` 39 | 40 | 这个案例示范了context(用于网络状态判断,获取网络类型),User-Agent,连接、读取超时参数配置。 41 | 更多的配置项有达23+项之多,非常的灵活,后边会有专门章节详细说明。 42 | 43 | ###发起请求 44 | 45 | 我们定义一个合法的http地址,如 46 | ```java 47 | String url = "http://baidu.com"; 48 | ``` 49 | 50 | 发起异步请求: 51 | ```java 52 | liteHttp.executeAsync(new StringRequest(url)); 53 | ``` 54 | 55 | 异步获取原始byte: 56 | ```java 57 | liteHttp.executeAsync(new BytesRequest(url)); 58 | ``` 59 | 60 | 异步加载一张位图: 61 | ```java 62 | String saveToPath = "/sdcard/a.png"; 63 | liteHttp.executeAsync(new BitmapRequest(url,saveToPath)); 64 | ``` 65 | saveToPath用来输入一个你指定的文件位置,位图将会保存到这里,不传入路径则分两种情况: 66 | - 缓存未启用:仅载入内存,不做文件存储。 67 | - 缓存开启:保存默认位置,默认存储位置和下面[下载文件]的规则一致。 68 | 69 | 异步下载一个文件: 70 | ```java 71 | liteHttp.executeAsync(new FileRequest(url,saveToPath)); 72 | ``` 73 | saveToPath用来输入一个你指定的文件位置,文件将会保存到这里,传入 null 则保存缓存默认位置。 74 | 75 | 默认位置规则: 76 | - 如果为请求设置了 Cache-Key,则取其为文件名字 77 | - 反之根据 Url 生成文件名字 78 | 文件夹位置在HttpConfig设置。 79 | 80 | 我们知道了怎么发起异步请求,那么请求是成功还是失败,成功如何获取结果,失败如何获取异常? 81 | 82 | ###处理结果 83 | 获取 String 的请求: 84 | ```java 85 | liteHttp.executeAsync(new StringRequest(url).setHttpListener(new HttpListener() { 86 | @Override 87 | public void onSuccess(String s, Response response) { 88 | // 成功:主线程回调,反馈一个string 89 | } 90 | 91 | @Override 92 | public void onFailure(HttpException e, Response response) { 93 | // 失败:主线程回调,反馈异常 94 | } 95 | })); 96 | ``` 97 | 下载 File 的请求: 98 | ```java 99 | liteHttp.executeAsync(new FileRequest(url,saveToPath).setHttpListener( 100 | new HttpListener(true, true, true) { 101 | 102 | @Override 103 | public void onSuccess(File file, Response response) { 104 | } 105 | 106 | @Override 107 | public void onFailure(HttpException e, Response response) { 108 | } 109 | 110 | @Override 111 | public void onLoading(AbstractRequest request, long total, long len) { 112 | // 进度通知 113 | } 114 | }) 115 | ); 116 | ``` 117 | 其他模式的请求,用法一样,这里不再多举。 118 | 119 | 值得注意的是 HttpListener 有多个参数可以设置: 120 | HttpListener(boolean runOnUiThread, boolean readingNotify, boolean uploadingNotify) 121 | 分别用于设置: 122 | - 开始、成功、失败、重试、上传、下载等所有回调是否在主线程(子线程回调性能更高,但不可操作UI) 123 | - 是否开启下载进度通知 124 | - 是否开启上传进度通知 125 | 126 | 注意,刚才提到,上传和下载同时是否在主线程被回调取决于第一个参数。 127 | -------------------------------------------------------------------------------- /docs/2-async-request.md: -------------------------------------------------------------------------------- 1 | # Android网络通信框架 LiteHttp2.0 实用教程 2 | 3 | 标签(空格分隔): litehttp教程 android网络通信教程 android http http最佳实践 4 | 5 | --- 6 | 7 |     本系列文章面向各级别尤其中高级android开发者,将展示开源网络通信框架LiteHttp的核心用法,讲解其关键功能的运作原理。 8 |     希望可以让开发者既能熟练使用、修改开源HTTP框架高效完成日常开发任务,又能深入理解litehttp类库本身以及android网络通信相关知识。同时传达了一些框架作者在日常开发中的一些最佳实践,仅作抛砖引玉。 9 | 10 | ##第二节:异步与同步请求 11 | 12 | ###异步请求 13 | 异步请求有两种 14 | 15 | ```java 16 | // 1.0 init request 17 | final StringRequest request = new StringRequest(url).setHttpListener( 18 | new HttpListener() { 19 | @Override 20 | public void onSuccess(String s, Response response) { 21 | HttpUtil.showTips(activity, "LiteHttp2.0", s); 22 | response.printInfo(); 23 | } 24 | 25 | @Override 26 | public void onFailure(HttpException e, Response response) { 27 | HttpUtil.showTips(activity, "LiteHttp2.0", e.toString()); 28 | } 29 | } 30 | ); 31 | 32 | // 1.1 execute async 33 | liteHttp.executeAsync(request); 34 | 35 | // 1.2 perform async 36 | FutureTask task = liteHttp.performAsync(request); 37 | ``` 38 | 39 | 简单自定义配置: 40 | ```java 41 | HttpConfig config = new HttpConfig(activity); 42 | 43 | // set app context 44 | config.setContext(activity); 45 | 46 | // custom User-Agent 47 | config.setUserAgent("Mozilla/5.0 (...)"); 48 | 49 | // connect timeout: 10s, socket timeout: 10s 50 | config.setTimeOut(10000, 10000); 51 | 52 | // new with config 53 | LiteHttp liteHttp = LiteHttp.newApacheHttpClient(config); 54 | ``` 55 | 56 | 这个案例示范了context(用于网络状态判断,获取网络类型),User-Agent,连接、读取超时参数配置。 57 | 更多的配置项有达23+项之多,非常的灵活,后边会有专门章节详细说明。 58 | 59 | ###初步使用 60 | 61 | 我们定义一个合法的http地址,如 62 | ```java 63 | String url = "http://baidu.com"; 64 | ``` 65 | 66 | 发起异步请求: 67 | ```java 68 | liteHttp.executeAsync(new StringRequest(url)); 69 | ``` 70 | 71 | 异步获取原始byte: 72 | ```java 73 | liteHttp.executeAsync(new BytesRequest(url)); 74 | ``` 75 | 76 | 异步加载一张位图: 77 | ```java 78 | String saveToPath = "/sdcard/a.png"; 79 | liteHttp.executeAsync(new BitmapRequest(url,saveToPath)); 80 | ``` 81 | saveToPath用来输入一个你指定的文件位置,位图将会保存到这里,不传入路径则分两种情况: 82 | - 缓存未启用:仅载入内存,不做文件存储。 83 | - 缓存开启:保存默认位置,默认存储位置和下面[下载文件]的规则一致。 84 | 85 | 异步下载一个文件: 86 | ```java 87 | liteHttp.executeAsync(new FileRequest(url,saveToPath)); 88 | ``` 89 | saveToPath用来输入一个你指定的文件位置,文件将会保存到这里,传入 null 则保存缓存默认位置。 90 | 91 | 默认位置规则: 92 | - 如果为请求设置了 Cache-Key,则取其为文件名字 93 | - 反之根据 Url 生成文件名字 94 | 文件夹位置在HttpConfig设置。 95 | 96 | 我们知道了怎么发起异步请求,那么请求是成功还是失败,成功如何获取结果,失败如何获取异常? 97 | 98 | ###处理结果 99 | 获取 String 的请求: 100 | ```java 101 | liteHttp.executeAsync(new StringRequest(url).setHttpListener(new HttpListener() { 102 | @Override 103 | public void onSuccess(String s, Response response) { 104 | // 成功:主线程回调,反馈一个string 105 | } 106 | 107 | @Override 108 | public void onFailure(HttpException e, Response response) { 109 | // 失败:主线程回调,反馈异常 110 | } 111 | })); 112 | ``` 113 | 下载 File 的请求: 114 | ```java 115 | liteHttp.executeAsync(new FileRequest(url,saveToPath).setHttpListener( 116 | new HttpListener(true, true, true) { 117 | 118 | @Override 119 | public void onSuccess(File file, Response response) { 120 | } 121 | 122 | @Override 123 | public void onFailure(HttpException e, Response response) { 124 | } 125 | 126 | @Override 127 | public void onLoading(AbstractRequest request, long total, long len) { 128 | // 进度通知 129 | } 130 | }) 131 | ); 132 | ``` 133 | 其他模式的请求,用法一样,这里不再多举。 134 | 135 | 值得注意的是 HttpListener 有多个参数可以设置: 136 | HttpListener(boolean runOnUiThread, boolean readingNotify, boolean uploadingNotify) 137 | 分别用于设置: 138 | - 开始、成功、失败、重试、上传、下载等所有回调是否在主线程(子线程回调性能更高,但不可操作UI) 139 | - 是否开启下载进度通知 140 | - 是否开启上传进度通知 141 | 142 | 注意,刚才提到,上传和下载同时是否在主线程被回调取决于第一个参数。 143 | -------------------------------------------------------------------------------- /docs/lite-http-0-大纲.md: -------------------------------------------------------------------------------- 1 | # Android网络通信框架LiteHttp 开篇简介和大纲目录 2 | 3 | 标签: litehttp2.x版本系列教程 4 | 5 | --- 6 | 官网: http://litesuits.com 7 | 8 | QQ群: [大群 47357508][1] , [二群 42960650][2] 9 | 10 | [Android网络框架为什么可以选用lite-http?][3] 11 | 12 | [lite-http 初步使用 和 快速起步上手][4] 13 | 14 | 本系列文章面向android开发者,展示开源网络通信框架LiteHttp的主要用法,并讲解其关键功能的运作原理,同时传达了一些框架作者在日常开发中的一些最佳实践和经验。 15 | 16 | --- 17 | # LiteHttp之开篇简介和大纲目录 18 | 19 | ### 1. lite-http是什么? (・̆⍛・̆) 20 | 21 | > LiteHttp是一款简单、智能、灵活的HTTP框架库,它在请求和响应层面做到了全自动构建和解析,主要用于Android快速开发。 22 | 23 | ### 2. 为什么选lite-http? (•́ ₃ •̀) 24 | 25 | 简单、强大,线程无关,一行代码搞定API请求和数据转化: 26 | ```java 27 | User user = liteHttp.get(url, User.class); 28 | ``` 29 | 30 | 当然也可以开启线程异步下载文件: 31 | ```java 32 | liteHttp.executeAsync(new FileRequest(url,path).setHttpListener( 33 | new HttpListener(true, true, true) { 34 | 35 | @Override 36 | public void onLoading(AbstractRequest request, long total, long len) { 37 | // 进度通知 38 | } 39 | 40 | }) 41 | ); 42 | ``` 43 | 44 | 通过注解约定完成异步请求: 45 | ```java 46 | @HttpUri(loginUrl) 47 | class LoginParam extends HttpRichParamModel { 48 | private String name; 49 | private String password; 50 | 51 | public LoginParam(String name, String password) { 52 | this.name = name; 53 | this.password = password; 54 | } 55 | } 56 | liteHttp.executeAsync(new LoginParam("lucy", "123456")); 57 | ``` 58 | 将构建类似下面请求:http://xxx?name=lucy&password=123456 59 | 60 | 案例详情可见我另一篇lite-http引言文章:[LiteHttp 引言:开发者为什么要选LiteHttp??][5] 61 | 62 | ### 3. lite-http有什么特点? (´ڡ`) 63 | 64 | - 轻量级:微小的内存开销与Jar包体积,99K左右。 65 | 66 | - 单线程:请求本身具有线程无关特性,基于当前线程高效率运作。 67 | 68 | - 全支持:GET, POST, PUT, DELETE, HEAD, TRACE, OPTIONS, PATCH。 69 | 70 | - 全自动:一行代码自动完成Model与Parameter、Json与Model。 71 | 72 | - 可配置:更多更灵活的配置选择项,多达 23+ 项。 73 | 74 | - 多态化:更加直观的API,输入和输出更加明确。 75 | 76 | - 强并发:自带强大的并发调度器,有效控制任务调度与队列控制策略。 77 | 78 | - 注解化:通过注解约定参数,URL、Method、ID、TAG等都可约定。 79 | 80 | - 易拓展:自定义DataParser将网络数据流转化为你想要的数据类型。 81 | 82 | - 可替换:基于接口,轻松替换网络连接实现方式和Json序列化库。 83 | 84 | - 多层缓存:内存命中更高效!多种缓存模式,支持设置缓存有效期。 85 | 86 | - 回调灵活:可选择当前或UI线程执行回调,开始结束、成败、上传、下载进度等都可监听。 87 | 88 | - 文件上传:支持单个、多个大文件上传。 89 | 90 | - 文件下载:支持文件、Bimtap下载及其进度通知。 91 | 92 | - 网络禁用:快速禁用一种、多种网络环境,比如指定禁用 2G,3G 。 93 | 94 | - 数据统计:链接、读取时长统计,以及流量统计。 95 | 96 | - 异常体系:统一、简明、清晰地抛出三类异常:客户端、网络、服务器,且异常都可精确细分。 97 | 98 | - GZIP压缩:Request, Response 自动 GZIP 压缩节省流量。 99 | 100 | - 自动重试:结合探测异常类型和当前网络状况,智能执行重试策略。 101 | 102 | - 自动重定向:基于 30X 状态的重试,且可设置最大次数防止过度跳转。 103 | 104 | 105 | ### 4. lite-http的整体架构是怎样的呀? (´ڡ`) 106 | 107 | ![lite-http架构图][6] 108 | 109 | 关于App架构,请看我另一篇文章分享: 110 | [怎样搭高质量的Android项目框架,框架的结构具体描述?][7] 111 | 112 | ### 5. 老湿,来点教学和分析带我飞呗? (◕‸◕) 113 | 114 | 好的 ◝‿◜ ,下面直接给你看,疗效好记得联系我,呵呵哒: 115 | 116 | [1. 初始化和初步使用][8] 117 | 118 | [2. 简化请求和非安全方法的使用][9] 119 | 120 | [3. 自动对象转化][10] 121 | 122 | [4. 自定义DataParser和Json序列化库的替换][11] 123 | 124 | [5. 文件、位图的上传和下载][12] 125 | 126 | [6. 禁用网络和流量、时间统计][13] 127 | 128 | [7. 重试和重定向][14] 129 | 130 | [8. 处理异常和取消请求][15] 131 | 132 | [9. POST方式的多种类型数据传输][16] 133 | 134 | [10. lite-http异步并发与调度策略][17] 135 | 136 | [11. 全局配置与参数设置详解][18] 137 | 138 | [12. 通过注解完成API请求][19] 139 | 140 | [13. 多层缓存机制及用法][20] 141 | 142 | [14. 回调监听器详解][21] 143 | 144 | [15. 并发调度控制器详解][22] 145 | 146 | 147 | [1]: http://shang.qq.com/wpa/qunwpa?idkey=492d63aaffb04b23d8dc4df21f6b594008cbe1a819978659cddab2dbc397684e 148 | [2]: http://shang.qq.com/wpa/qunwpa?idkey=19bf15b9c85ec15c62141dd00618f725e2983803cd2b48566fa0e94964ae8370 149 | [3]: https://zybuluo.com/liter/note/186533 150 | [4]: https://zybuluo.com/liter/note/186560 151 | [5]: https://zybuluo.com/liter/note/186533 152 | [6]: http://litesuits.com/imgs/lite-http-arch.png 153 | [7]: https://zybuluo.com/liter/note/186526 154 | [8]: https://zybuluo.com/liter/note/186560 155 | [9]: https://zybuluo.com/liter/note/186561 156 | [10]: https://zybuluo.com/liter/note/186565 157 | [11]: https://zybuluo.com/liter/note/186583 158 | [12]: https://zybuluo.com/liter/note/186756 159 | [13]: https://zybuluo.com/liter/note/186801 160 | [14]: https://zybuluo.com/liter/note/186860 161 | [15]: https://zybuluo.com/liter/note/186900 162 | [16]: https://zybuluo.com/liter/note/186965 163 | [17]: https://zybuluo.com/liter/note/186998 164 | [18]: https://zybuluo.com/liter/note/187016 165 | [19]: https://zybuluo.com/liter/note/187568 166 | [20]: https://zybuluo.com/liter/note/187894 167 | [21]: https://zybuluo.com/liter/note/187904 168 | [22]: https://zybuluo.com/liter/note/189537 -------------------------------------------------------------------------------- /docs/lite-http-10-异步并发与调度策略.md: -------------------------------------------------------------------------------- 1 | #Android网络通信框架LiteHttp 第十节:异步并发与调度策略 2 | 3 | 标签(空格分隔): litehttp2.x版本系列教程 4 | 5 | --- 6 | 官网: http://litesuits.com 7 | 8 | QQ群: 大群 47357508,二群 42960650 9 | 10 | 本系列文章面向android开发者,展示开源网络通信框架LiteHttp的主要用法,并讲解其关键功能的运作原理,同时传达了一些框架作者在日常开发中的一些最佳实践和经验。 11 | 12 | 本系列文章目录总览: https://zybuluo.com/liter/note/186513 13 | 14 | --- 15 | 16 | #第十节:LiteHttp之异步并发与调度策略 17 | 18 | lite-http 的异步执行和任务调度主要借助于 SmartExecutor 来完成的,关于 SmartExecutor 的介绍和使用后边会有专门的文章来讲解。 19 | 20 | lite-http 因此具备 SmartExecutor 的全部特性: 21 | > 22 | 可定义核心并发线程数,即同一时间并发的请求数量。 23 | > 24 | 可定义等待排队线程数,即超出核心并发数后可排队请求数量。 25 | > 26 | 可定义等待队列进入执行状态的策略:先来先执行,后来先执行。 27 | > 28 | 可定义等待队列满载后处理新请求的策略: 29 | > 30 | - 抛弃队列中最新的任务 31 | - 抛弃队列中最旧的任务 32 | - 抛弃当前新任务 33 | - 直接执行(阻塞当前线程) 34 | - 抛出异常(中断当前线程) 35 | 36 | lite-http拥有一个独立的 SmartExecutor 的实例,在一个 App 中 SmartExecutor 可以有多个实例,每个实例都有独立核心和等待线程数指标,每个实例都有独立的调度和满载处理策略,但它们 **共享一个线程池**。这种机制既满足不同木块对线程控制和任务调度的独立需求,又共享一个池资源。独立又共享,最大程度上节省资源,提升性能。 37 | 38 | 心急的朋友又要喊了: shut up, show me the code! 39 | ```java 40 | // Concurrent and Scheduling 41 | 42 | HttpConfig httpConfig = liteHttp.getConfig(); 43 | // only one task can be executed at the same time 44 | httpConfig.setConcurrentSize(1); 45 | // at most two tasks be hold in waiting queue at the same time 46 | httpConfig.setWaitingQueueSize(2); 47 | // the last waiting task executed first 48 | httpConfig.setSchedulePolicy(SchedulePolicy.LastInFirstRun); 49 | // when task more than 3(current = 1, waiting = 2), new task will be discard. 50 | httpConfig.setOverloadPolicy(OverloadPolicy.DiscardCurrentTask); 51 | ``` 52 | 上面的代码对lite-http进行了并发方面的参数设置: 53 | > 54 | 核心并发数为 1 55 | 等待队列数为 2 56 | 调度采用 后进先执行 策略 57 | 满载时采用 抛弃新任务 策略 58 | 59 | 然后测试: 60 | ```java 61 | for (int i = 0; i < 4; i++) { 62 | liteHttp.executeAsync(new StringRequest(url).setTag(i)); 63 | } 64 | 65 | // submit order : 0 -> 1 -> 2 -> 3 66 | // task 0 is executing, 67 | // 1 and 2 is in waitting queue, 68 | // 3 was discarded. 69 | // real executed order: 0 -> 2 -> 1 70 | ``` 71 | 上面的代码按顺序一次投入了四个请求,那么: 72 | > 73 | 投入任务顺序:0 -> 1 -> 2 -> 3 74 | 任务 0 立即执行 75 | 任务 1 和 2 在排队,按预定策略 2 后进,将先执行 76 | 任务 3 因为队列满载,按预定策略抛弃掉 77 | 实际执行顺序:0 -> 2 -> 1 78 | 79 | 对于 SmartExecutor,不论多少个实例,其控制指标和策略独立,始终共享一个池,避免掉多余开销。 80 | 81 | 理论上,**一个 App 只创建一个线程池** 就足够了,但是现在框架众多,有的独立精悍,有的功能众多,还是要提醒开发者,选用的框架最好知根知底、深入了解。不清楚里面什么机制,更是控制不了就会尴尬,到头来根本不知道自己的 App 里面有几个线程池。 82 | 83 | 84 | 85 | 开发者在构建自己的池子时要注意清闲时活跃线程不要多持,最好不要超过CPU数量,注意控制排队和满载策略,大量并发瞬间起来也能轻松应对。 86 | 87 | 另外,同时并发的线程数量不要过多,最好保持在CPU核数左右,过多了CPU时间片过多的轮转分配造成吞吐量降低,过少了不能充分利用CPU,并发数可以适当比CPU核数多一点没问题。 88 | 89 | 好了,本节先将这么多,更多并发姿势在关于 SmartExecutor 的文章里分享。 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /docs/lite-http-12-通过注解完成API请求.md: -------------------------------------------------------------------------------- 1 | #Android网络通信框架LiteHttp 第十二节:通过注解完成API请求 2 | 3 | 标签(空格分隔): litehttp2.x版本系列教程 4 | 5 | --- 6 | 官网: http://litesuits.com 7 | 8 | QQ群: 大群 47357508,二群 42960650 9 | 10 | 本系列文章面向android开发者,展示开源网络通信框架LiteHttp的主要用法,并讲解其关键功能的运作原理,同时传达了一些框架作者在日常开发中的一些最佳实践和经验。 11 | 12 | 本系列文章目录总览: https://zybuluo.com/liter/note/186513 13 | 14 | --- 15 | #第十二节:LiteHttp之通过注解完成API请求 16 | 17 | 本节强烈推荐通过 RichParamModel 方式构建请求,它大概是长这样子: 18 | ```java 19 | @HttpUri(loginUrl) 20 | class LoginParam extends HttpRichParamModel { 21 | public String name = "lucy"; 22 | public String password = "123456"; 23 | } 24 | liteHttp.executeAsync(new UserRichParam()); 25 | ``` 26 | 表示请求 loginUrl 这个地址,并传递 name 和 password 参数,返回用户 User 对象。 27 | 28 | 关于注解,还得从头说起: 29 | 30 | 在java模型自动转化那一节我们讲过,lite-http 可以把java对象转换为http请求的参数,需要该java类继承 HttpParamModel,实际上 HttpParamModel 还有一个拓展子类 HttpRichParamModel,拓展顾名思义是一个基于原来的增强,开发者连Request都不用写了,直接继承 HttpRichParamModel 通过注解来完成整个http请求的参数约定。 31 | 32 | ## 1. 简单参数 HttpParamModel 33 | 34 | 先看这段代码: 35 | ```java 36 | // Usage of Annotation 37 | public String userUrl = "http://litesuits.com/mockdata/user_get"; 38 | 39 | @HttpUri(userUrl) 40 | @HttpMethod(HttpMethods.Get) 41 | @HttpID(1) 42 | @HttpCacheMode(CacheMode.CacheFirst) 43 | @HttpCacheExpire(value = 1, unit = TimeUnit.MINUTES) 44 | class UserAnnoParam implements HttpParamModel { 45 | public long id = 110; 46 | private String key = "aes"; 47 | } 48 | 49 | liteHttp.executeAsync(new JsonRequest(new UserAnnoParam(), User.class) {} 50 | .setHttpListener(new HttpListener() { 51 | @Override 52 | public void onSuccess(User user, Response response) { 53 | HttpUtil.showTips(activity, "UserAnnoParam", user.toString()); 54 | } 55 | })); 56 | ``` 57 | 58 | 所见即所得,通过这些注解: 59 | > 60 | @HttpUri(userUrl) 61 | @HttpMethod(HttpMethods.Get) 62 | @HttpID(1) 63 | @HttpCacheMode(CacheMode.CacheFirst) 64 | @HttpCacheExpire(value = 1, unit = TimeUnit.MINUTES) 65 | 66 | 上面一段代码,完成了这样一次请求配置: 67 | > 68 | 请求地址为 userUrl 69 | 请求方式为 GET 70 | 请求ID为 1 71 | 请求优先使用缓存 72 | 请求缓存时间为1分钟 73 | 74 | ## 2. 扩展版参数HttpRichParamModel 75 | 76 | 再看一下拓展的参数类如何工作: 77 | ```java 78 | // Best Practice: HTTP Rich Param Model (It is simpler and More Useful) 79 | 80 | @HttpUri(userUrl) 81 | class UserRichParam extends HttpRichParamModel { 82 | public long id = 110; 83 | private String key = "aes"; 84 | } 85 | 86 | // 一句话调用即可 87 | liteHttp.executeAsync(new UserRichParam()); 88 | ``` 89 | 90 | 可见,最后一句执行时连 Request 都没有创建,直接将参数投入执行。 91 | > 92 | 定义RichParam,可指定URL、参数、响应体三个关键事物: 93 | 请求地址: uerUrl 94 | 请求参数: id=110 & key=aes 95 | 请求响应: User 96 | 97 | 更多注解方式有: 98 | > 99 | @HttpSchemeHost("http://litesuits.com") // 定义scheme 100 | @HttpUri("/mockdata/user_get") // 定义uri 或者 path 101 | @HttpMethod(HttpMethods.Get) // 请求方式 102 | @HttpCharSet("UTF-8") // 请求编码 103 | @HttpTag("custom tag") // 打TAG 104 | @HttpCacheMode(CacheMode.CacheFirst) // 缓存模式 105 | @HttpCacheKey("custom-cache-key-name-by-myself") // 缓存文件名字 106 | @HttpCacheExpire(value = 1, unit = TimeUnit.MINUTES) // 缓存时间 107 | @HttpID(2) // 请求ID 108 | @HttpMaxRetry(3) // 重试次数 109 | @HttpMaxRedirect(5) // 重定向次数 110 | 111 | 此外,继承Rich Param的参数类还可以复写下面方法: 112 | > 113 | createHeaders : 创建header 114 | createQueryBuilder: 设置参数构建器 115 | createHttpListener: 创建监听器 116 | createHttpBody: 创建数据体 117 | 118 | createHttpBody是为POST、PUT等方式创建数据体,GET、DELETE等不需要,因其参数直接拼接到URL。 119 | 120 | ## 3. 最佳实践 121 | 最后,通过这句: 122 | > liteHttp.executeAsync(new UserRichParam()); 123 | 124 | 可见 RichParamModel 是可以直接抛入执行的,这就将其和 Request 基本提升到了同一级别。 125 | 在我的 App 里,我是直接用 RichParamModel 的,因为它更直观简单,并且 RichParamModel 可以通过 set 方法设置监听器等参数,所以我也建议开发者使用这个进行请求配置。 126 | 127 | 强烈推荐通过 RichParamModel 方式构建请求。 128 | 129 | -------------------------------------------------------------------------------- /docs/lite-http-13-多层缓存机制及用法.md: -------------------------------------------------------------------------------- 1 | #Android网络通信框架LiteHttp 第十三节:多层缓存机制及用法 2 | 3 | 标签(空格分隔): litehttp2.x版本系列教程 4 | 5 | --- 6 | 官网: http://litesuits.com 7 | 8 | QQ群: 大群 47357508,二群 42960650 9 | 10 | 本系列文章面向android开发者,展示开源网络通信框架LiteHttp的主要用法,并讲解其关键功能的运作原理,同时传达了一些框架作者在日常开发中的一些最佳实践和经验。 11 | 12 | 本系列文章目录总览: https://zybuluo.com/liter/note/186513 13 | 14 | --- 15 | #第十三节:LiteHttp之多层缓存机制及用法 16 | 17 | 先了解下什么是多级缓存,了解或做过图片加载框架的同学可能比较清楚,一般情况下第一级为闪存,第二级为外存,如果非要说第三级那么就是网络了,严格讲网络上的内容不算缓存。 18 | 19 | lite-http设计之时也考虑到了这些,因为大多数API请求信息体不大,几K就算数据量比较大的了,这些请求完全可以缓存到内存。而有些请求占用空间非常大,比如图片、音乐等文件,对于网络框架而言,这些不适合存储到闪存,而需要缓存到本地SD卡等外存设备。 20 | 21 | 如何构建可缓存请求,请看下面代码: 22 | 23 | ```java 24 | // Multi Cache Mechanism 25 | 26 | StringRequest cacheRequest = new StringRequest(url); 27 | 28 | cacheRequest.setCacheMode(CacheMode.CacheFirst); 29 | cacheRequest.setCacheExpire(30, TimeUnit.SECONDS); 30 | cacheRequest.setCacheDir("/sdcard/lite"); 31 | cacheRequest.setCacheKey(null); 32 | 33 | cacheRequest.setHttpListener(new HttpListener() { 34 | @Override 35 | public void onSuccess(String html, Response response) { 36 | String title = response.isCacheHit() ? "Hit Cache(使用缓存)" : "No Cache(未用缓存)"; 37 | HttpUtil.showTips(activity, title, html); 38 | } 39 | }); 40 | liteHttp.executeAsync(cacheRequest); 41 | ``` 42 | 43 | 主要代码为: 44 | > 45 | response.isCacheHit(): 判断是否命中缓存 46 | > 47 | setCacheExpire: 设置缓存有效时间,默认为-1,永久不超时。 48 | setCacheDir: 设置放置缓存的文件夹 49 | setCacheKey: 设置缓存文件名,不设置则框架自动产生。 50 | setCacheMode: 设置缓存类型,CacheMode有四种,默认NetOnly方式。 51 | > 52 | - NetOnly 即直接联网,不使用缓存; 53 | - NetFirst 优先网络获取,失败后取缓存; 54 | - CacheFirst 即优先用缓存,失败后连接网络; 55 | - CacheOnly 即只使用缓存,不连接网络。 56 | 57 | 58 | 另外,还有一种通过注解设置缓存方式: 59 | 60 | ```java 61 | @HttpUri(userUrl) 62 | @HttpCacheMode(CacheMode.CacheFirst) 63 | @HttpCacheExpire(value = 1, unit = TimeUnit.MINUTES) 64 | class UserAnnoParam implements HttpParamModel { 65 | public long id = 110; 66 | private String key = "aes"; 67 | } 68 | ``` 69 | 70 | 或者 71 | ```java 72 | 73 | // 其他更多注解还有: 74 | @HttpUri(userUrl) // 定义uri 或者 path 75 | @HttpCacheMode(CacheMode.CacheFirst) // 缓存模式 76 | @HttpCacheExpire(value = 1, unit = TimeUnit.MINUTES) // 缓存时间 77 | class TEST extends HttpRichParamModel { } 78 | 79 | liteHttp.executeAsync(new TEST()); 80 | ``` 81 | 82 | 另外,lite-http还提供了一下方法来清除缓存: 83 | > 84 | - 清除某个请求的缓存,包括闪存和文件缓存: 85 | liteHttp.cleanCacheForRequest(request) 86 | - 清除全部闪存缓存 87 | liteHttp.clearMemCache() 88 | - 删除当前缓存文件夹下面所有文件 89 | liteHttp.deleteCachedFiles() 90 | 91 | 92 | 好,本节至此完。 93 | -------------------------------------------------------------------------------- /docs/lite-http-2-简化请求和非安全方法的使用.md: -------------------------------------------------------------------------------- 1 | # Android网络通信框架LiteHttp 第二节:简化请求和非安全方法的使用 2 | 3 | 标签(空格分隔): litehttp2.x版本系列教程 4 | 5 | --- 6 | 官网: http://litesuits.com 7 | 8 | QQ群: 大群 47357508,二群 42960650 9 | 10 | 本系列文章面向android开发者,展示开源网络通信框架LiteHttp的主要用法,并讲解其关键功能的运作原理,同时传达了一些框架作者在日常开发中的一些最佳实践和经验。 11 | 12 | 本系列文章目录总览: https://zybuluo.com/liter/note/186513 13 | 14 | --- 15 | 16 | #第二节:LiteHttp之简化请求和非安全方法的使用 17 | 18 | 方便测试,先随意定义一些合法的URL: 19 | ```java 20 | public static final String url = "http://baidu.com"; 21 | public static final String httpsUrl = "https://baidu.com"; 22 | public static final String userUrl = "http://litesuits.com/mockdata/user_get"; 23 | ``` 24 | ## 1. 简化的请求 25 | 26 | 发起同步请求时,部分请求可以被简化。 27 | GET方式获取API返回的String: 28 | ```java 29 | String html = liteHttp.get(url); 30 | ``` 31 | 32 | GET方式直接获取Java Model: 33 | ```java 34 | User user = liteHttp.get(userUrl, User.class); 35 | ``` 36 | 37 | POST方式获取String: 38 | ```java 39 | String result = liteHttp.post(new StringRequest(httpsUrl)); 40 | ``` 41 | 42 | HEAD方式获取头信息: 43 | ```java 44 | NameValuePair[] headers = liteHttp.head(new StringRequest(url)); 45 | ``` 46 | 47 | 等等...可自行查看源码了解更多。 48 | 49 | ## 2. 非安全的请求 50 | 51 | 有时候开发者在某种情况下需要抛出异常中断后面代码,或者某场景下需要自己捕获异常,那么需要发送非安全的请求。 52 | 53 | ```java 54 | // http scheme error 55 | try { 56 | Response response = liteHttp.executeOrThrow(new BytesRequest("haha://hehe")); 57 | // do something... 58 | } catch (HttpException e) { 59 | e.printStackTrace(); 60 | } 61 | 62 | // java model translate error 63 | try { 64 | User user = liteHttp.performOrThrow(new JsonAbsRequest("http://thanku.love") {}); 65 | } catch (final HttpException e) { 66 | e.printStackTrace(); 67 | } 68 | ``` 69 | 70 | ## 3. https 请求 71 | 72 | ```java 73 | liteHttp.executeAsync(new StringRequest(httpsUrl).setHttpListener( 74 | new HttpListener() { 75 | @Override 76 | public void onSuccess(String s, Response response) { 77 | 78 | } 79 | } 80 | )); 81 | ``` -------------------------------------------------------------------------------- /docs/lite-http-3-自动对象转化.md: -------------------------------------------------------------------------------- 1 | #Android网络通信框架LiteHttp 第三节:自动对象转化 2 | 3 | 标签(空格分隔): litehttp2.x版本系列教程 4 | 5 | --- 6 | 官网: http://litesuits.com 7 | 8 | QQ群: 大群 47357508,二群 42960650 9 | 10 | 本系列文章面向android开发者,展示开源网络通信框架LiteHttp的主要用法,并讲解其关键功能的运作原理,同时传达了一些框架作者在日常开发中的一些最佳实践和经验。 11 | 12 | 本系列文章目录总览: https://zybuluo.com/liter/note/186513 13 | 14 | --- 15 | 16 | #第三节:LiteHttp之自动对象转化 17 | 18 | 下面是一个真实有效的API地址: 19 | ```java 20 | public static final String userUrl = "http://litesuits.com/mockdata/user_get"; 21 | ``` 22 | 它的响应体是个Json结构的字符串: 23 | ```json 24 | { 25 | "api": "com.xx.get.userinfo", 26 | "v": "1.0", 27 | "result": { 28 | "code": 200, 29 | "message": "success" 30 | }, 31 | "data": { 32 | "age": 18, 33 | "name": "qingtianzhu", 34 | "girl_friends": [ 35 | "xiaoli", 36 | "fengjie", 37 | "lucy" 38 | ] 39 | } 40 | } 41 | ``` 42 | 43 | ## 1. java对象转为http参数 44 | 假设是一个GET请求,就是说将参数拼接在URL里,类似:http://{userUrl}?id=168&key=md5,自动拼接参数的示范代码如下: 45 | ```java 46 | /** 47 | * Param Model: will be converted to: http://...?id=168&key=md5 48 | */ 49 | class UserParam implements HttpParamModel { 50 | // static final property will be ignored. 51 | private static final long serialVersionUID = 123L; 52 | private long id; 53 | public String key; 54 | @NonHttpParam 55 | protected String ignored = "Ignored by @NonHttpParam "; 56 | 57 | public UserParam(long id, String key) { 58 | this.id = id; 59 | this.key = key; 60 | } 61 | } 62 | 63 | // build as http://{userUrl}?id=168&key=md5 64 | liteHttp.executeAsync(new StringRequest(userUrl, new UserParam(18, "md5")) 65 | .setHttpListener(new HttpListener() { 66 | @Override 67 | public void onSuccess(String data, Response response) { 68 | Log.i(TAG, "USER: " + data); 69 | } 70 | })); 71 | ``` 72 | 上面示范了将UserParam对象转化为URL参数,并得到String响应的方式,注意: 73 | 74 | - static final 的字段将被忽略; 75 | - @NonHttpParam 标注的字段将被忽略; 76 | - private 等权限修饰符不影响字段转为参数; 77 | - 值为 null 的对象将被忽略,未赋值的基础数据类型传递默认值; 78 | 79 | ## 2. json string转为java对象 80 | 81 | ```java 82 | /** 83 | * Request Model : json string translate to user object 84 | */ 85 | class UserRequest extends JsonAbsRequest { 86 | public UserRequest(String url, Http) { 87 | super(url); 88 | } 89 | } 90 | 91 | // build as http://{userUrl}?id=168&key=md5 92 | UserRequest userRequest = new UserRequest(userUrl, new UserParam(18, "md5")); 93 | userRequest.setHttpListener(new HttpListener() { 94 | @Override 95 | public void onSuccess(User user, Response response) { 96 | // data has been translated to user object 97 | } 98 | }); 99 | liteHttp.executeAsync(userRequest); 100 | ``` 101 | 上面示范了将UserParam对象转化为URL参数,并直接得到User响应对象的方式,注意: 102 | 103 | - 参数类 UserParam 实现 HttpParamModel 104 | - 请求类 UserRequest 继承 JsonAbsRequest,当然也可以简化为: 105 | ```java 106 | User user = liteHttp.executeAsync(new JsonAbsRequest(userUrl) {}); 107 | ``` 108 | - User类无要求,建议统一继承基类,比如这里的User: 109 | ```java 110 | /** 111 | * base model 112 | */ 113 | public abstract class BaseModel implements Serializable { 114 | } 115 | 116 | /** 117 | * api model: base structure 118 | */ 119 | public class ApiModel extends BaseModel { 120 | /** 121 | * 不变的部分:写在API基类中 122 | */ 123 | private String api; 124 | private String v; 125 | 126 | protected int code; 127 | protected String message; 128 | 129 | /** 130 | * 变化的部分:使用泛型,数据类型的确认延迟到子类里。 131 | */ 132 | protected T data; 133 | 134 | // getter setter toString 等方法已删减掉... 135 | } 136 | 137 | /** 138 | * response string will be converted to this model 139 | */ 140 | public class User extends ApiModel { 141 | 142 | // 泛型设置:定义一个公共静态内部类(也可以定义外部类) 143 | public static class Data extends BaseModel{ 144 | public int age; 145 | public String name; 146 | public ArrayList girl_friends; 147 | 148 | // getter setter toString 等方法已删减掉... 149 | } 150 | } 151 | ``` 152 | 153 | Model Parameter String 之间的转化比较灵活,请各位玩家多看源码和案例,依据实际需求,挖掘更多玩法。 154 | -------------------------------------------------------------------------------- /docs/lite-http-6-禁用网络和流量&耗时统计.md: -------------------------------------------------------------------------------- 1 | #Android网络通信框架LiteHttp 第六节:禁用网络和流量&耗时统计 2 | 3 | 标签(空格分隔): litehttp2.x版本系列教程 4 | 5 | --- 6 | 官网: http://litesuits.com 7 | 8 | QQ群: 大群 47357508,二群 42960650 9 | 10 | 本系列文章面向android开发者,展示开源网络通信框架LiteHttp的主要用法,并讲解其关键功能的运作原理,同时传达了一些框架作者在日常开发中的一些最佳实践和经验。 11 | 12 | 本系列文章目录总览: https://zybuluo.com/liter/note/186513 13 | 14 | --- 15 | 16 | #第六节:LiteHttp之禁用网络和流量&耗时统计 17 | 18 | ## 1. 禁用网络 19 | 20 | 开发者可以通过lite-http的config来设置禁用某种网络,比如我们将移动网络和wifi都禁用: 21 | ```java 22 | // disable some network 23 | HttpConfig config = liteHttp.getConfig(); 24 | 25 | // must set context 26 | config.setContext(activity); 27 | 28 | // disable mobile(2G/3G/4G) and wifi network 29 | config.setDisableNetworkFlags(HttpConfig.FLAG_NET_DISABLE_MOBILE | HttpConfig.FLAG_NET_DISABLE_WIFI); 30 | 31 | liteHttp.executeAsync(new StringRequest(url).setHttpListener(new HttpListener() { 32 | @Override 33 | public void onSuccess(String s, Response response) { 34 | HttpUtil.showTips(activity, "LiteHttp2.0", s); 35 | } 36 | 37 | @Override 38 | public void onFailure(HttpException e, Response response) { 39 | HttpUtil.showTips(activity, "LiteHttp2.0", e.toString()); 40 | } 41 | })); 42 | ``` 43 | 这样不管是sim卡网络还是无线wifi下发送请求都会失败,onFailure会触发。 44 | 恢复可用状态: 45 | ```java 46 | // enable network 47 | HttpConfig config = liteHttp.getConfig(); 48 | 49 | // enable all 50 | config.setDisableNetworkFlags(HttpConfig.FLAG_NET_DISABLE_NONE); 51 | ``` 52 | 53 | ## 2. 流量和耗时统计 54 | 55 | 只需要从配置打开统计开关即可: 56 | ```java 57 | // Traffic/Time Statistics 58 | String picUrl = "http://pic.33.la/20140403sj/1638.jpg"; 59 | 60 | // turn on 61 | liteHttp.getConfig().setDoStatistics(true); 62 | 63 | liteHttp.executeAsync(new FileRequest(picUrl).setHttpListener(new HttpListener() { 64 | @Override 65 | public void onSuccess(File file, Response response) { 66 | String msg = "This request take time:" + response.getUseTime() 67 | + ", readed length:" + response.getReadedLength(); 68 | msg += " Global " + liteHttp.getStatisticsInfo(); 69 | HttpUtil.showTips(activity, "LiteHttp2.0", msg); 70 | } 71 | 72 | @Override 73 | public void onFailure(HttpException e, Response response) { 74 | HttpUtil.showTips(activity, "LiteHttp2.0", e.toString()); 75 | } 76 | })); 77 | ``` 78 | 更多数据统计: 79 | > 80 | response.getRedirectTimes(); // 重定向的次数 81 | response.getRetryTimes(); // 重试的次数 82 | response.getUseTime(); // 本次请求耗时 83 | response.getContentLength(); // header中的数据长度(Content-Length) 84 | response.getReadedLength(); // 实际读取的数据长度 85 | 86 | 整体数据统计: 87 | > 88 | StatisticsInfo sta = liteHttp.getStatisticsInfo(); 89 | sta.getConnectTime(); // litehttp 实例化后所有请求耗时累计 90 | sta.getDataLength(); // litehttp 实例化后读取数据长度累计 91 | 92 | -------------------------------------------------------------------------------- /docs/lite-http-7-重试和重定向.md: -------------------------------------------------------------------------------- 1 | #Android网络通信框架LiteHttp 第七节:重试和重定向 2 | 3 | 标签(空格分隔): litehttp2.x版本系列教程 4 | 5 | --- 6 | 官网: http://litesuits.com 7 | 8 | QQ群: 大群 47357508,二群 42960650 9 | 10 | 本系列文章面向android开发者,展示开源网络通信框架LiteHttp的主要用法,并讲解其关键功能的运作原理,同时传达了一些框架作者在日常开发中的一些最佳实践和经验。 11 | 12 | 本系列文章目录总览: https://zybuluo.com/liter/note/186513 13 | 14 | --- 15 | #第七节:LiteHttp之重试和重定向 16 | 17 | ## 1. 重试和重定向 18 | 19 | 先准备一个可以重定向的地址: 20 | ```java 21 | public String redirectUrl = "http://www.baidu.com/link?url=Lqc3GptP8u05JCRDsk0jqsAvIZh9WdtO_RkXYMYRQEm"; 22 | ``` 23 | 设置最大跳转和重试次数即可,然后开跳: 24 | ```java 25 | // Retry/Redirect 26 | 27 | // make request 28 | StringRequest redirect = new StringRequest(redirectUrl) 29 | .setMaxRetryTimes(1) // maximum retry times 30 | .setMaxRedirectTimes(5) // maximum redirect times 31 | .setHttpListener(new HttpListener() { 32 | 33 | @Override 34 | public void onRedirect(AbstractRequest request, int max, int times) { 35 | Toast.makeText(activity, "Redirect max num: " + max + " , times: " + times 36 | + "\n GO-TO: " + request.getUri(), Toast.LENGTH_LONG).show(); 37 | } 38 | 39 | @Override 40 | public void onRetry(AbstractRequest request, int max, int times) { 41 | Toast.makeText(activity, "Retry Now! max num: " + max + " , times: " + times 42 | , Toast.LENGTH_LONG).show(); 43 | 44 | } 45 | 46 | @Override 47 | public void onSuccess(String s, Response response) { 48 | HttpUtil.showTips(activity, "LiteHttp2.0", "Content Length: " + s.length()); 49 | } 50 | }); 51 | 52 | liteHttp.executeAsync(redirect); 53 | ``` 54 | 也可以设置全局重试和重定向次数: 55 | ```java 56 | // default retry times 57 | liteHttp.getConfig().setDefaultMaxRetryTimes(2); 58 | // default redirect times 59 | liteHttp.getConfig().setDefaultMaxRedirectTimes(4); 60 | ``` 61 | 如果请求本身设置了最大重试和重定向次数,以请求本身设置为准,如果未设置,则取全局默认值。 62 | 63 | ## 2. 关于重试的更多知识 64 | 65 | 重试出现的原因比较复杂或隐晦,网络状态不良时可能会触发,测试中难以必现。 66 | 67 | 当出现以下异常时,立即结束不作重试: 68 | > 69 | UnknownHostException 70 | FileNotFoundException 71 | SSLException 72 | ConnectException 73 | 74 | 当出现以下异常时,重试发生可能性较大: 75 | > 76 | NoHttpResponseException 77 | SocketException 78 | SocketTimeoutException 79 | ConnectTimeoutException 80 | 81 | 当未传入context时,线程睡眠指定时间,睡眠时间可以在config中设置,默认时间3000毫秒: 82 | > 83 | // default retry waitting time 84 | liteHttp.getConfig().setForRetry(1500, false); 85 | 86 | 传入context时,lite-http便可以自己判断网络状态,如果网络是连接中的线程不作睡眠立即重试,当系统网络处于连接中、扫描等状态时,睡眠等待指定时间后重试。 87 | 88 | ## 3. 关于重定向的原理和过程 89 | 90 | 当请求状态码为 **30x** 时,应该处理重定向的情况。 91 | 获取 header 中 location 字段的值,即为重定向新地址。 92 | 一般情况下新地址可能不包含 scheme 和 host 信息,因此需要我们自己拼接。 93 | 当重试大于最大次数,给予抛出异常处理。 94 | 95 | 框架主要代码如下: 96 | ```java 97 | if (response.getRedirectTimes() < maxRedirectTimes) { 98 | // get the location header to find out where to redirect to 99 | Header locationHeader = ares.getFirstHeader(Consts.REDIRECT_LOCATION); 100 | if (locationHeader != null) { 101 | String location = locationHeader.getValue(); 102 | if (location != null && location.length() > 0) { 103 | if (!location.toLowerCase().startsWith("http")) { 104 | URI uri = new URI(request.getFullUri()); 105 | URI redirect = new URI(uri.getScheme(), uri.getHost(), location, null); 106 | location = redirect.toString(); 107 | } 108 | response.setRedirectTimes(response.getRedirectTimes() + 1); 109 | request.setUri(location); 110 | if (HttpLog.isPrint) { 111 | HttpLog.i(TAG, "Redirect to : " + location); 112 | } 113 | if (listener != null) { 114 | listener.notifyCallRedirect(request, maxRedirectTimes, response.getRedirectTimes()); 115 | } 116 | connectWithRetries(request, response); 117 | return; 118 | } 119 | } 120 | throw new HttpServerException(httpStatus); 121 | } else { 122 | throw new HttpServerException(ServerException.RedirectTooMuch); 123 | } 124 | ``` 125 | 126 | 更多知识,多看源码,抽空造个小轮子,来得更直接。 -------------------------------------------------------------------------------- /docs/lite-http-引言.md: -------------------------------------------------------------------------------- 1 | # LiteHttp 引言:开发者为什么要选LiteHttp? 2 | 3 | 标签(空格分隔): litehttp2.x版本系列教程 4 | 5 | --- 6 | 官网: http://litesuits.com 7 | QQ群: 大群 47357508,二群 42960650 8 | 9 | 本系列文章目录总览: https://zybuluo.com/liter/note/186513 10 | 11 | --- 12 | 13 | # 开发者为什么要选LiteHttp? 14 | 15 | 我们来看一个普通android网络应用上,最基础的http连接和json解析方式,一个简单例子。 16 | 17 | 从服务器获取 id=168 的用户的信息,User 的 json 结构: 18 | ```json 19 | { 20 | "api": "com.xx.get.userinfo", 21 | "v": "1.0", 22 | "result": { 23 | "code": 200, 24 | "message": "success" 25 | }, 26 | "data": { 27 | "age": 18, 28 | "name": "qingtianzhu", 29 | "girl_friends": [ 30 | "xiaoli", 31 | "fengjie", 32 | "lucy" 33 | ] 34 | } 35 | } 36 | ``` 37 | 38 | api, v, result为必备基础信息,完成这个任务一般分三步: 39 | 40 | **1. 组织api的url地址和参数(简单),比如:** 41 | ```java 42 | String url = "http://litesuits.github.io/mockdata/user?userid=168"; 43 | ``` 44 | 45 | **2. http连接网络获取api信息(封装后还算简单),典型代码:** 46 | ```java 47 | /** 48 | * 关闭流顺序:先打开的后关闭;被依赖的后关闭。 49 | * @return string info 50 | */ 51 | public static String sendHttpRequst(String apiUrl) { 52 | HttpURLConnection conn = null; 53 | InputStream is = null; 54 | ByteArrayOutputStream baos = null; 55 | try { 56 | URL url = new URL(apiUrl); 57 | conn = (HttpURLConnection) url.openConnection(); 58 | conn.connect(); 59 | is = conn.getInputStream(); 60 | int len = conn.getContentLength(); 61 | if (len < 1) len = 1024; 62 | baos = new ByteArrayOutputStream(len); 63 | byte[] buffer = new byte[1024]; 64 | len = 0; 65 | while ((len = is.read(buffer)) != -1) { 66 | baos.write(buffer, 0, len); 67 | } 68 | return baos.toString(); 69 | } catch (MalformedURLException e) { 70 | e.printStackTrace(); 71 | } catch (IOException e) { 72 | e.printStackTrace(); 73 | } finally { 74 | try { 75 | if (baos != null) baos.close(); 76 | if (is != null) is.close(); 77 | } catch (IOException e) { 78 | e.printStackTrace(); 79 | } 80 | if (conn != null) conn.disconnect(); 81 | } 82 | return null; 83 | } 84 | ``` 85 | 86 | **3. 解析服务器反馈的string(比较头疼):** 87 | ```java 88 | public static User parseJsonToUser(String json) { 89 | User user = new User(); 90 | if (json != null) { 91 | try { 92 | JSONObject jsonObj = new JSONObject(json); 93 | JSONObject result = jsonObj.optJSONObject("result"); 94 | JSONObject data = jsonObj.optJSONObject("data"); 95 | JSONArray arr = null; 96 | if (data != null) arr = data.optJSONArray("girl_friends"); 97 | user.result = new User.Result(); 98 | user.data = new User.UserInfo(); 99 | user.data.girl_friends = new ArrayList(); 100 | if (jsonObj != null) { 101 | user.api = jsonObj.optString("api"); 102 | user.v = jsonObj.optString("v"); 103 | } 104 | if (result != null) { 105 | user.result.code = result.optInt("code"); 106 | user.result.message = result.optString("message"); 107 | } 108 | if (data != null) { 109 | user.data.age = data.optInt("age"); 110 | user.data.name = data.optString("name"); 111 | } 112 | if (arr != null) { 113 | for (int i = 0, size = arr.length(); i < size; i++) { 114 | user.data.girl_friends.add(arr.optString(i)); 115 | } 116 | } 117 | } catch (JSONException e) { 118 | e.printStackTrace(); 119 | } 120 | } 121 | return user; 122 | } 123 | ``` 124 | 125 | 那么我们看到第3步在User这个类仅仅有3个属性的情况下,就写了约40行代码,如果User有几十个属性,应用中又有几十个类型User的Model,那么代码量将会指数级暴增,这种方式相对会耗费较大的劳动力。 126 | 127 | **那么,就此转入正题** 128 | 129 | 看看lite-http是怎么完成这个任务的: 130 | ```java 131 | User user = liteHttp.get(url, User.class); 132 | ``` 133 | Github地址:https://github.com/litesuits/android-lite-http 134 | 135 | 项目中有20+个使用案例(Samples),带你飞。 136 | -------------------------------------------------------------------------------- /downloads/gson-2.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/downloads/gson-2.3.jar -------------------------------------------------------------------------------- /downloads/lite-go-1.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/downloads/lite-go-1.0.0.jar -------------------------------------------------------------------------------- /downloads/lite-http-3.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/downloads/lite-http-3.0.0.jar -------------------------------------------------------------------------------- /downloads/lite-http-3.0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/downloads/lite-http-3.0.1.jar -------------------------------------------------------------------------------- /downloads/lite-http-3.1.3.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/downloads/lite-http-3.1.3.6.jar -------------------------------------------------------------------------------- /downloads/并发需要依赖lite-go组件.md: -------------------------------------------------------------------------------- 1 | 并发需要依赖lite-go组件 2 | Json解析默认使用Google的Gson库,可以通过Json.set(Json fastJsonImpl)自己设置为FastJson等类库解析。 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /litehttp-sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /litehttp-sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.litesuits.http.sample" 9 | minSdkVersion 9 10 | targetSdkVersion 22 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | // compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile project(':litehttp') 26 | compile project(':apache-client') 27 | } 28 | -------------------------------------------------------------------------------- /litehttp-sample/libs/fastjson-1.2.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/litehttp-sample/libs/fastjson-1.2.5.jar -------------------------------------------------------------------------------- /litehttp-sample/src/androidTest/java/com/litesuits/http/sample/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.sample; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /litehttp-sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /litehttp-sample/src/main/java/com/litesuits/http/custom/CustomJSONParser.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.custom; 2 | 3 | import com.litesuits.http.parser.MemCacheableParser; 4 | import org.json.JSONException; 5 | import org.json.JSONObject; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | /** 11 | * parse stream to JSONObject 12 | */ 13 | public class CustomJSONParser extends MemCacheableParser { 14 | String json; 15 | 16 | /** 17 | * 实现远程网络流解析 18 | */ 19 | @Override 20 | protected JSONObject parseNetStream(InputStream stream, long totalLength, 21 | String charSet) throws IOException { 22 | return streamToJson(stream, totalLength, charSet); 23 | } 24 | 25 | /** 26 | * 实现本地文件流解析 27 | */ 28 | @Override 29 | protected JSONObject parseDiskCache(InputStream stream, long length) throws IOException { 30 | return streamToJson(stream, length, charSet); 31 | } 32 | 33 | /** 34 | * 实现文件缓存 35 | */ 36 | @Override 37 | protected boolean tryKeepToCache(JSONObject data) throws IOException { 38 | return keepToCache(json); 39 | } 40 | 41 | /** 42 | * 1. 将 stream 转换为 String 43 | * 2. String 转为 JSONObject 44 | */ 45 | protected JSONObject streamToJson(InputStream is, long length, String charSet) throws IOException { 46 | this.json = streamToString(is, length, charSet); 47 | try { 48 | return new JSONObject(json); 49 | } catch (JSONException e) { 50 | e.printStackTrace(); 51 | } 52 | return null; 53 | } 54 | } -------------------------------------------------------------------------------- /litehttp-sample/src/main/java/com/litesuits/http/custom/FastJson.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.custom; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.litesuits.http.data.Json; 5 | 6 | import java.lang.reflect.Type; 7 | 8 | public class FastJson extends Json { 9 | private static final String TAG = FastJson.class.getSimpleName(); 10 | 11 | @Override 12 | public String toJson(Object src) { 13 | return JSON.toJSONString(src); 14 | } 15 | 16 | @Override 17 | public T toObject(String json, Class claxx) { 18 | return JSON.parseObject(json, claxx); 19 | } 20 | 21 | @Override 22 | public T toObject(String s, Type type) { 23 | return JSON.parseObject(s, type); 24 | } 25 | 26 | @Override 27 | public T toObject(byte[] bytes, Class claxx) { 28 | return JSON.parseObject(bytes, claxx); 29 | } 30 | } -------------------------------------------------------------------------------- /litehttp-sample/src/main/java/com/litesuits/http/custom/MyHttpExceptHandler.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.custom; 2 | 3 | import android.app.Activity; 4 | import com.litesuits.http.data.HttpStatus; 5 | import com.litesuits.http.exception.*; 6 | import com.litesuits.http.exception.handler.HttpExceptionHandler; 7 | import com.litesuits.http.utils.HttpUtil; 8 | 9 | public class MyHttpExceptHandler extends HttpExceptionHandler { 10 | private Activity activity; 11 | 12 | public MyHttpExceptHandler(Activity activity) { 13 | this.activity = activity; 14 | } 15 | 16 | @Override 17 | protected void onClientException(HttpClientException e, ClientException type) { 18 | switch (e.getExceptionType()) { 19 | case UrlIsNull: 20 | break; 21 | case ContextNeeded: 22 | // some action need app context 23 | break; 24 | case PermissionDenied: 25 | break; 26 | case SomeOtherException: 27 | break; 28 | } 29 | HttpUtil.showTips(activity, "LiteHttp2.0", "Client Exception:\n" + e.toString()); 30 | activity = null; 31 | } 32 | 33 | @Override 34 | protected void onNetException(HttpNetException e, NetException type) { 35 | switch (e.getExceptionType()) { 36 | case NetworkNotAvilable: 37 | break; 38 | case NetworkUnstable: 39 | // maybe retried but fail 40 | break; 41 | case NetworkDisabled: 42 | break; 43 | default: 44 | break; 45 | } 46 | HttpUtil.showTips(activity, "LiteHttp2.0", "Network Exception:\n" + e.toString()); 47 | activity = null; 48 | } 49 | 50 | @Override 51 | protected void onServerException(HttpServerException e, ServerException type, 52 | HttpStatus status) { 53 | switch (e.getExceptionType()) { 54 | case ServerInnerError: 55 | // status code 5XX error 56 | break; 57 | case ServerRejectClient: 58 | // status code 4XX error 59 | break; 60 | case RedirectTooMuch: 61 | break; 62 | default: 63 | break; 64 | } 65 | HttpUtil.showTips(activity, "LiteHttp2.0", "Server Exception:\n" + e.toString()); 66 | activity = null; 67 | } 68 | } -------------------------------------------------------------------------------- /litehttp-sample/src/main/java/com/litesuits/http/model/ApiModel.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.model; 2 | 3 | /** 4 | * @author MaTianyu @http://litesuits.com 5 | * @date 2015-10-03 6 | */ 7 | public class ApiModel extends BaseModel { 8 | 9 | /** 10 | * 不变的部分:写在API基类中 11 | */ 12 | public String api; 13 | public String v; 14 | 15 | public int code; 16 | public String message; 17 | 18 | /** 19 | * 变化的部分:使用泛型,数据类型的确认延迟到子类里。 20 | */ 21 | public T data; 22 | 23 | public String getApi() { 24 | return api; 25 | } 26 | 27 | public ApiModel setApi(String api) { 28 | this.api = api; 29 | return this; 30 | } 31 | 32 | public String getV() { 33 | return v; 34 | } 35 | 36 | public ApiModel setV(String v) { 37 | this.v = v; 38 | return this; 39 | } 40 | 41 | public int getCode() { 42 | return code; 43 | } 44 | 45 | public ApiModel setCode(int code) { 46 | this.code = code; 47 | return this; 48 | } 49 | 50 | public String getMessage() { 51 | return message; 52 | } 53 | 54 | public ApiModel setMessage(String message) { 55 | this.message = message; 56 | return this; 57 | } 58 | 59 | public T getData() { 60 | return data; 61 | } 62 | 63 | public ApiModel setData(T data) { 64 | this.data = data; 65 | return this; 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | return "ApiModel{" + 71 | "api='" + api + '\'' + 72 | ", v='" + v + '\'' + 73 | ", code=" + code + 74 | ", message='" + message + '\'' + 75 | ", data=" + data + 76 | "} "; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /litehttp-sample/src/main/java/com/litesuits/http/model/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * base model 7 | */ 8 | public abstract class BaseModel implements Serializable {} -------------------------------------------------------------------------------- /litehttp-sample/src/main/java/com/litesuits/http/model/User.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.model; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * response string will be converted to this model 7 | */ 8 | public class User extends ApiModel { 9 | 10 | public static class Data extends BaseModel{ 11 | private int age; 12 | private String name; 13 | private ArrayList girl_friends; 14 | 15 | public int getAge() { 16 | return age; 17 | } 18 | 19 | public Data setAge(int age) { 20 | this.age = age; 21 | return this; 22 | } 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | public Data setName(String name) { 29 | this.name = name; 30 | return this; 31 | } 32 | 33 | public ArrayList getGirl_friends() { 34 | return girl_friends; 35 | } 36 | 37 | public Data setGirl_friends(ArrayList girl_friends) { 38 | this.girl_friends = girl_friends; 39 | return this; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "Data{" + 45 | "age=" + age + 46 | ", name='" + name + '\'' + 47 | ", girl_friends=" + girl_friends + 48 | "} " ; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /litehttp-sample/src/main/java/com/litesuits/http/model/api/RichParam.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.model.api; 2 | 3 | import com.litesuits.http.annotation.HttpCacheExpire; 4 | import com.litesuits.http.annotation.HttpCacheMode; 5 | import com.litesuits.http.annotation.HttpMethod; 6 | import com.litesuits.http.annotation.HttpUri; 7 | import com.litesuits.http.model.User; 8 | import com.litesuits.http.request.content.HttpBody; 9 | import com.litesuits.http.request.content.UrlEncodedFormBody; 10 | import com.litesuits.http.request.param.CacheMode; 11 | import com.litesuits.http.request.param.HttpMethods; 12 | import com.litesuits.http.request.param.HttpRichParamModel; 13 | import com.litesuits.http.request.query.ModelQueryBuilder; 14 | import com.litesuits.http.request.query.SimpleQueryBuilder; 15 | import com.litesuits.http.sample.MainActivity; 16 | 17 | import java.util.concurrent.TimeUnit; 18 | 19 | /** 20 | * POST request, HTTP body:UrlEncodedForm: [id=000&key=xxx] 21 | * use cache 22 | */ 23 | @HttpUri(MainActivity.userUrl) 24 | @HttpMethod(HttpMethods.Get) 25 | @HttpCacheMode(CacheMode.CacheFirst) 26 | @HttpCacheExpire(value = 10, unit = TimeUnit.SECONDS) 27 | public class RichParam extends HttpRichParamModel { 28 | 29 | private static final ModelQueryBuilder MODEL_QUERY_BUILDER = new SimpleQueryBuilder(); 30 | 31 | public long id; 32 | public String key; 33 | 34 | public RichParam(long id, String key) { 35 | this.id = id; 36 | this.key = key; 37 | } 38 | 39 | @Override 40 | protected HttpBody createHttpBody() { 41 | return new UrlEncodedFormBody(getModelQueryBuilder().buildPrimaryPairSafely(this)); 42 | } 43 | 44 | @Override 45 | protected ModelQueryBuilder createQueryBuilder() { 46 | return MODEL_QUERY_BUILDER; 47 | } 48 | } -------------------------------------------------------------------------------- /litehttp-sample/src/main/java/com/litesuits/http/model/api/UserParam.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.model.api; 2 | 3 | import com.litesuits.http.request.param.HttpParam; 4 | import com.litesuits.http.request.param.HttpParamModel; 5 | import com.litesuits.http.request.param.NonHttpParam; 6 | 7 | /** 8 | * Param Model: will be converted to: http://...?id=168&key=md5 9 | */ 10 | public class UserParam implements HttpParamModel { 11 | // static final property will be ignored. 12 | private static final long serialVersionUID = 2451716801614350437L; 13 | 14 | private String uri; 15 | 16 | @HttpParam("id") 17 | private long id; 18 | 19 | public String key; 20 | 21 | @NonHttpParam// lite http ignore 22 | private transient String beIgnored = "Ignored by @NonHttpParam "; 23 | 24 | public UserParam(long id, String key) { 25 | this.id = id; 26 | this.key = key; 27 | } 28 | } -------------------------------------------------------------------------------- /litehttp-sample/src/main/java/com/litesuits/http/sample/Test.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.sample; 2 | 3 | /** 4 | * @author 氢一 @http://litesuits.com 5 | * @date 2016-06-16 6 | */ 7 | 8 | public class Test { 9 | public static void main(String[] args) { 10 | String s = null; 11 | String b = null; 12 | String sb = s + b; 13 | System.out.println(sb); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /litehttp-sample/src/main/res/drawable/selector_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /litehttp-sample/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | 23 | 24 | 25 | 33 | 34 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /litehttp-sample/src/main/res/layout/list_item.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /litehttp-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/litehttp-sample/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /litehttp-sample/src/main/res/values-zh/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | LiteHttp 3 4 | LiteLib: HTTP-V3 5 | 通过日志和源码看详情. 6 | 7 | 8 | 0. 快速配置(可忽略) 9 | 1. 发起异步请求 10 | 2. 发起同步请求 11 | 3. 同步请求简化 12 | 4. 可抛出异常的请求 13 | 5. HTTPS请求 14 | 6. 全自动模型转换 15 | 7. 自定义数据解析 16 | 8. 替换Json序列化库 17 | 9. 文件、位图下载 18 | 10. 文件上传 19 | 11. 禁用网络 20 | 12. 流量、时长统计 21 | 13. 重试和重定向 22 | 14. 最佳实践:异常处理 23 | 15. 最佳实践:取消请求 24 | 25 | 16. POST多形态数据 26 | 17. 并发与调度策略 27 | 18. 参数配置详解 28 | 19. 使用注解 29 | 20. 双层缓存机制 30 | 21. 回调机制详解 31 | 22. 最佳实践:使用SmartExecutor 32 | 23. 最佳实践:全自动转换复杂对象 33 | 24. 最佳实践:使用富 HTTP 参数 34 | 35 | 36 | 37 | 38 | 1. 字符串上传 39 | 2. UrlEncodedForm上传 40 | 3. 对象自动转JSON上传 41 | 4. 对象序列化后上传 42 | 5. 字节上传 43 | 6. 单文件上传 44 | 7. 单输入流上传 45 | 8. 多文件(表单)上传 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /litehttp-sample/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /litehttp-sample/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /litehttp-sample/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | LiteHttp 3 3 | LiteLib: HTTP-V3 4 | see more via code and log. 5 | 6 | 0. Quickly Config(Can be Ignored) 7 | 1. Asynchronous Request 8 | 2. Synchronous Request 9 | 3. Simple Synchronous Request 10 | 4. Exception Thrown Request 11 | 5. HTTPS Reqeust 12 | 6. Automatic Model Conversion 13 | 7. Custom Data Parser 14 | 8. Replace Json Library 15 | 9. File/Bitmap Download 16 | 10. File Upload 17 | 11. Disable Some Network 18 | 12. Traffic/Time Statistics 19 | 13. Retry/Redirect 20 | 14. Best Practice: Exception Handling 21 | 15. Best Practice: Cancel Request 22 | 23 | 16. POST Multi-Form Data 24 | 17. Concurrent and Scheduling 25 | 18. Detail of Config 26 | 19. Usage of Annotation 27 | 20. Multi Cache Mechanism 28 | 21. CallBack Mechanism 29 | 22. Best Practice: SmartExecutor 30 | 23. Best Practice: Auto-Conversion of Complex Model 31 | 24. Best Practice: HTTP Rich Param Model 32 | 33 | 34 | 35 | 1. String Data 36 | 2. UrlEncodedForm Data 37 | 3. Json Data 38 | 4. Serializable Data 39 | 5. ByteArray Data 40 | 6. File 41 | 7. InputStream 42 | 8. Multipart Entity Data 43 | 44 | 45 | -------------------------------------------------------------------------------- /litehttp-sample/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /litehttp-sample/src/test/java/com/litesuits/http/sample/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.sample; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /litehttp/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /litehttp/build.gradle: -------------------------------------------------------------------------------- 1 | import proguard.gradle.ProGuardTask 2 | 3 | apply plugin: 'com.android.library' 4 | 5 | 6 | def liteHttpVersion = '3.1.3.6' 7 | 8 | 9 | android { 10 | compileSdkVersion 22 11 | buildToolsVersion '23.0.3' 12 | 13 | defaultConfig { 14 | minSdkVersion 9 15 | targetSdkVersion 22 16 | versionCode 4 17 | versionName liteHttpVersion 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | } 26 | 27 | dependencies { 28 | compile fileTree(dir: 'libs', include: ['*.jar']) 29 | testCompile 'junit:junit:4.12' 30 | } 31 | 32 | task cleanJars(type: Delete) { 33 | delete 'build/libs/*.*' 34 | } 35 | 36 | task cleanBuildDir(type: Delete) { 37 | delete rootProject.buildDir 38 | } 39 | 40 | def jarPath = 'build/libs/'; 41 | def jarName = 'lite-http-' + liteHttpVersion + '.jar'; 42 | def jarProName = 'lite-http-pro-' + liteHttpVersion + '.jar'; 43 | 44 | task makeJar(type: Jar, dependsOn: ['assembleRelease']) { 45 | archiveName jarName; 46 | destinationDir = file('build/libs') 47 | from('build/intermediates/classes/release/') 48 | exclude('test/', 'BuildConfig.class', 'R.class', 'R\$*.class', 'META-INF/') 49 | } 50 | 51 | def androidSDKDir = plugins.getPlugin('com.android.library').sdkHandler.getSdkFolder() 52 | def androidJarDir = androidSDKDir.toString() + '/platforms/' + android.compileSdkVersion + '/android.jar' 53 | 54 | task makeProguardJar(type: ProGuardTask, dependsOn: ['makeJar']) { 55 | libraryjars(androidJarDir) 56 | configuration 'proguard-rules.pro' 57 | injars(jarPath + jarName) 58 | outjars(jarPath + jarProName) 59 | } 60 | 61 | 62 | -------------------------------------------------------------------------------- /litehttp/libs/fastjson-1.2.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/litehttp/libs/fastjson-1.2.5.jar -------------------------------------------------------------------------------- /litehttp/libs/gson-2.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/litehttp/libs/gson-2.3.jar -------------------------------------------------------------------------------- /litehttp/libs/lite-go-1.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/litehttp/libs/lite-go-1.0.0.jar -------------------------------------------------------------------------------- /litehttp/libs/lite-http-3.1.3.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/litehttp/libs/lite-http-3.1.3.5.jar -------------------------------------------------------------------------------- /litehttp/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/matianyu/develop/android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/* 19 | -optimizationpasses 7 20 | -allowaccessmodification 21 | -dontpreverify 22 | 23 | # The remainder of this file is identical to the non-optimized version 24 | # of the Proguard configuration file (except that the other file has 25 | # flags to turn off optimization). 26 | 27 | -dontusemixedcaseclassnames 28 | -dontskipnonpubliclibraryclasses 29 | -verbose 30 | 31 | # 使用注解 32 | -keepattributes *Annotation*,Signature,Exceptions 33 | 34 | # 保持混淆时类的实名及行号(--------------- 调试时打开 --------------) 35 | #-keepattributes SourceFile,LineNumberTable 36 | 37 | # 开发者需要调用,不可以混淆 38 | -keep public class com.litesuits.http.* { *; } 39 | -keep public class com.litesuits.http.response.Response { *; } 40 | -keep public class com.litesuits.http.utils.HttpUtil { *; } 41 | -keep public class com.litesuits.http.annotation.* { *; } 42 | -keep public class com.litesuits.http.concurrent.* { *; } 43 | -keep public class com.litesuits.http.data.* { *; } 44 | -keep public class com.litesuits.http.listener.* { *; } 45 | -keep public class com.litesuits.http.log.* { *; } 46 | -keep public class com.litesuits.http.parser.* { *; } 47 | -keep public class com.litesuits.http.exception.** { *; } 48 | -keep public class com.litesuits.http.request.** { *; } 49 | # LiteHttp Http状态用了反射,不可混淆。 50 | -keep class com.litesuits.http.data.HttpStatus { *; } 51 | # http参数不可混淆 52 | -keep public class * implements com.litesuits.http.request.param.HttpParamModel { *; } 53 | 54 | # 枚举须保住 see http://proguard.sourceforge.net/manual/examples.html#enumerations 55 | -keepclassmembers enum * { 56 | **[] $VALUES; 57 | public *; 58 | } 59 | 60 | ##---------------Begin: proguard configuration for Gson ---------- 61 | # Gson uses generic type information stored in a class file when working with fields. Proguard 62 | # removes such information by default, so configure it to keep all of it. 63 | -keep class com.google.gson.** { *; } 64 | # Gson specific classes 65 | -keep class sun.misc.Unsafe { *; } 66 | -keep class com.google.gson.stream.** { *; } 67 | # Application classes that will be serialized/deserialized over Gson 68 | -keep class com.google.gson.examples.android.model.** { *; } 69 | ##---------------End: proguard configuration for Gson ---------- 70 | 71 | # HTTP混淆建议: 72 | # 1. 最好保证每一个HTTP参数类(Java Model)不被混淆 73 | # 2. 最好保证每一个HTTP响应类(Java Model)不被混淆 -------------------------------------------------------------------------------- /litehttp/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/HttpCache.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http; 2 | 3 | public class HttpCache { 4 | T data; 5 | String key; 6 | long time; 7 | long length; 8 | String charSet; 9 | } -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/HttpClient.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http; 2 | 3 | import com.litesuits.http.request.AbstractRequest; 4 | import com.litesuits.http.response.InternalResponse; 5 | 6 | /** 7 | * @author 氢一 @http://def.so 8 | * @date 2016-04-04 9 | */ 10 | public interface HttpClient { 11 | public void config(HttpConfig config); 12 | public void connect(AbstractRequest request, InternalResponse response) throws Exception; 13 | } 14 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/annotation/HttpBaseUrl.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author MaTianyu 10 | * @date 2015-04-26 11 | */ 12 | @Target(ElementType.TYPE) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface HttpBaseUrl { 15 | String value(); 16 | } 17 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/annotation/HttpCacheExpire.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /** 10 | * @author MaTianyu 11 | * @date 2015-04-26 12 | */ 13 | @Target(ElementType.TYPE) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface HttpCacheExpire { 16 | long value(); 17 | 18 | TimeUnit unit(); 19 | } 20 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/annotation/HttpCacheKey.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author MaTianyu 10 | * @date 2015-04-26 11 | */ 12 | @Target(ElementType.TYPE) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface HttpCacheKey { 15 | String value(); 16 | } 17 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/annotation/HttpCacheMode.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.annotation; 2 | 3 | import com.litesuits.http.request.param.CacheMode; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * @author MaTianyu 12 | * @date 2015-04-26 13 | */ 14 | @Target(ElementType.TYPE) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface HttpCacheMode { 17 | CacheMode value(); 18 | } 19 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/annotation/HttpCharSet.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author MaTianyu 10 | * @date 2015-04-26 11 | */ 12 | @Target(ElementType.TYPE) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface HttpCharSet { 15 | String value(); 16 | } 17 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/annotation/HttpID.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author MaTianyu 10 | * @date 2015-04-26 11 | */ 12 | @Target(ElementType.TYPE) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface HttpID { 15 | long value(); 16 | } 17 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/annotation/HttpMaxRedirect.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author MaTianyu 10 | * @date 2015-04-26 11 | */ 12 | @Target(ElementType.TYPE) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface HttpMaxRedirect { 15 | int value(); 16 | } 17 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/annotation/HttpMaxRetry.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author MaTianyu 10 | * @date 2015-04-26 11 | */ 12 | @Target(ElementType.TYPE) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface HttpMaxRetry { 15 | int value(); 16 | } 17 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/annotation/HttpMethod.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.annotation; 2 | 3 | import com.litesuits.http.request.param.HttpMethods; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * @author MaTianyu 12 | * @date 2015-04-26 13 | */ 14 | @Target(ElementType.TYPE) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface HttpMethod { 17 | HttpMethods value(); 18 | } 19 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/annotation/HttpTag.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author MaTianyu 10 | * @date 2015-04-26 11 | */ 12 | @Target(ElementType.TYPE) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface HttpTag { 15 | String value(); 16 | } 17 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/annotation/HttpUri.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author MaTianyu 10 | * @date 2015-04-26 11 | */ 12 | @Target(ElementType.TYPE) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface HttpUri { 15 | String value(); 16 | } 17 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/data/Charsets.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.data; 2 | 3 | import java.nio.charset.Charset; 4 | 5 | /** 6 | * useful charsets 7 | * 8 | * @author MaTianyu 9 | * 2014-1-19上午1:21:18 10 | */ 11 | public class Charsets { 12 | public static final String ASCII = "ASCII"; 13 | public static final String US_ASCII = "US-ASCII"; 14 | 15 | public static final String ISO_8859_1 = "ISO-8859-1"; 16 | 17 | public static final String Unicode = "Unicode"; 18 | 19 | public static final String BIG5 = "BIG5"; 20 | 21 | public static final String UTF_8 = "UTF-8"; 22 | public static final String UTF_16 = "UTF-16"; 23 | 24 | public static final String GB2312 = "GB2312"; 25 | public static final String GBK = "GBK"; 26 | public static final String GB18030 = "GB18030"; 27 | 28 | public static Charset getCharset(String charsetName){ 29 | return Charset.forName(charsetName); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/data/Consts.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.data; 2 | 3 | /** 4 | * @author MaTianyu 5 | * @date 14-7-29 6 | */ 7 | public class Consts { 8 | public static final String CHUNK_CODING = "chunked"; 9 | public static final String IDENTITY_CODING = "identity"; 10 | public static final String UTF_8 = "UTF-8"; 11 | public static final String UTF_16 = "UTF-16"; 12 | public static final String US_ASCII = "US-ASCII"; 13 | public static final String ASCII = "ASCII"; 14 | public static final String ISO_8859_1 = "ISO-8859-1"; 15 | public static final String DEFAULT_CONTENT_CHARSET = "ISO-8859-1"; 16 | public static final String DEFAULT_PROTOCOL_CHARSET = "US-ASCII"; 17 | 18 | public static final String SCHEME_HTTP = "http"; 19 | public static final String SCHEME_HTTPS = "https"; 20 | public static final String CODE_CHARSET = UTF_8; 21 | public static final String EQUALS = "="; 22 | public static final String AND = "&"; 23 | public static final String NONE_SPLIT = ""; 24 | public static final String ONE_LEVEL_SPLIT = AND; 25 | public static final String SECOND_LEVEL_SPLIT = ","; 26 | public static final String ARRAY_ECLOSING_LEFT = "["; 27 | public static final String ARRAY_ECLOSING_RIGHT = "]"; 28 | public static final String KV_ECLOSING_LEFT = "{"; 29 | public static final String KV_ECLOSING_RIGHT = "}"; 30 | 31 | public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding"; 32 | public static final String ENCODING_GZIP = "gzip"; 33 | public static final String REDIRECT_LOCATION = "Location"; 34 | 35 | public static final String TRANSFER_ENCODING = "Transfer-Encoding"; 36 | public static final String CONTENT_LEN = "Content-Length"; 37 | public static final String CONTENT_TYPE = "Content-Type"; 38 | public static final String CONTENT_ENCODING = "Content-Encoding"; 39 | public static final String EXPECT_DIRECTIVE = "Expect"; 40 | public static final String CONN_DIRECTIVE = "Connection"; 41 | public static final String TARGET_HOST = "Host"; 42 | public static final String USER_AGENT = "User-Agent"; 43 | public static final String DATE_HEADER = "Date"; 44 | public static final String SERVER_HEADER = "Server"; 45 | 46 | public static final String EXPECT_CONTINUE = "100-Continue"; 47 | public static final String CONN_CLOSE = "Close"; 48 | public static final String CONN_KEEP_ALIVE = "Keep-Alive"; 49 | 50 | public static final String DEFAULT_CHARSET = Charsets.UTF_8; 51 | public final static String CHARSET_PARAM = "; charset="; 52 | public final static String BOUNDARY_PARAM = "; boundary="; 53 | public static final String MIME_TYPE_TEXT = "text/plain"; 54 | public static final String MIME_TYPE_JSON = "application/json"; 55 | public static final String MIME_TYPE_OCTET_STREAM = "application/octet-stream"; 56 | public static final String MIME_TYPE_FORM_URLENCODE = "application/x-www-form-urlencoded"; 57 | public static final String MIME_TYPE_FORM_DATA = "multipart/form-data"; 58 | 59 | public static final String DEFAULT_CONTENT_TYPE = MIME_TYPE_TEXT + CHARSET_PARAM + DEFAULT_CHARSET; 60 | } 61 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/data/FastJson.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.data; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | 5 | import java.lang.reflect.Type; 6 | 7 | public class FastJson extends Json { 8 | private static final String TAG = FastJson.class.getSimpleName(); 9 | 10 | @Override 11 | public String toJson(Object src) { 12 | return JSON.toJSONString(src); 13 | } 14 | 15 | @Override 16 | public T toObject(String json, Class claxx) { 17 | return JSON.parseObject(json, claxx); 18 | } 19 | 20 | @Override 21 | public T toObject(String s, Type type) { 22 | return JSON.parseObject(s, type); 23 | } 24 | 25 | @Override 26 | public T toObject(byte[] bytes, Class claxx) { 27 | return JSON.parseObject(bytes, claxx); 28 | } 29 | } -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/data/GsonImpl.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.data; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import java.lang.reflect.Type; 6 | 7 | /** 8 | * google gson 9 | * 10 | * @author MaTianyu 11 | * 2014-2-26下午11:13:39 12 | */ 13 | public class GsonImpl extends Json { 14 | private Gson gson = new Gson(); 15 | 16 | @Override 17 | public String toJson(Object src) { 18 | return gson.toJson(src); 19 | } 20 | 21 | @Override 22 | public T toObject(String json, Class claxx) { 23 | return gson.fromJson(json, claxx); 24 | } 25 | 26 | @Override 27 | public T toObject(String json, Type type) { 28 | return gson.fromJson(json, type); 29 | } 30 | 31 | @Override 32 | public T toObject(byte[] bytes, Class claxx) { 33 | return gson.fromJson(new String(bytes), claxx); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/data/Json.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.data; 2 | 3 | import java.lang.reflect.Type; 4 | 5 | /** 6 | * with this, we can change json handler easily. 7 | * alibaba fastjson can not handle private attribute that without getter method. 8 | * so we choice the google gson. 9 | * 10 | * @author MaTianyu 11 | * 2014-1-14下午11:32:32 12 | */ 13 | public abstract class Json { 14 | private static Json json; 15 | 16 | /** 17 | * set new json instance 18 | * 19 | * @param json new instance 20 | * @return new instance 21 | */ 22 | public static Json set(Json json) { 23 | Json.json = json; 24 | return Json.json; 25 | } 26 | 27 | /** 28 | * set default json handler: Google Gson 29 | */ 30 | public static Json setDefault() { 31 | Json.json = new GsonImpl(); 32 | return Json.json; 33 | } 34 | 35 | /** 36 | * get default json handler 37 | * 38 | * @return Json 39 | */ 40 | public static Json get() { 41 | if (json == null) { 42 | //json = new FastJson(); 43 | json = new GsonImpl(); 44 | } 45 | return json; 46 | } 47 | 48 | public abstract String toJson(Object src); 49 | 50 | public abstract T toObject(String json, Class claxx); 51 | 52 | public abstract T toObject(String json, Type claxx); 53 | 54 | public abstract T toObject(byte[] bytes, Class claxx); 55 | } 56 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/data/NameValuePair.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.data; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * kv pair 7 | * 8 | * @author MaTianyu 9 | * 2014-1-18上午3:19:12 10 | */ 11 | public class NameValuePair implements Serializable { 12 | private static final long serialVersionUID = -1339856642868580559L; 13 | private final String name; 14 | private final String value; 15 | 16 | public NameValuePair(String name, String value) { 17 | this.name = name; 18 | this.value = value; 19 | } 20 | 21 | public String getName() { 22 | return this.name; 23 | } 24 | 25 | public String getValue() { 26 | return this.value; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return String.format("%-20s", this.name) + "= " + this.value; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/data/StatisticsInfo.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.data; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | public class StatisticsInfo { 6 | private AtomicLong connectTime = new AtomicLong(); 7 | private AtomicLong dataLength = new AtomicLong(); 8 | 9 | public void addConnectTime(long time) { 10 | connectTime.addAndGet(time); 11 | } 12 | 13 | public void addDataLength(long len) { 14 | dataLength.addAndGet(len); 15 | } 16 | 17 | public long getConnectTime() { 18 | return connectTime.longValue(); 19 | } 20 | 21 | public long getDataLength() { 22 | return dataLength.longValue(); 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return "StatisticsInfo{" + 28 | "connectTime=" + connectTime + 29 | ", dataLength=" + dataLength + 30 | '}'; 31 | } 32 | } -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/exception/ClientException.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.exception; 2 | 3 | public enum ClientException { 4 | UrlIsNull("Url is Null!", "Url 为空!"), 5 | IllegalScheme("illegal scheme!", "非法的Scheme"), 6 | ContextNeeded("(Detect or Disable Network, etc) Need Context.", "(探测和禁用网络等)需要 Context"), 7 | PermissionDenied("Missing NETWORK-ACCESS Permission in Manifest?", "未获取访问网络或SD卡权限"), 8 | SomeOtherException("Client Exception", "客户端发生异常"); 9 | 10 | private static final String TAG = ClientException.class.getName(); 11 | public String reason; 12 | public String chiReason; 13 | 14 | ClientException(String name, String chiName) { 15 | this.reason = name; 16 | this.chiReason = chiName; 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return TAG + ": " + this.reason + " (" + this.chiReason + ")"; 22 | } 23 | } -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/exception/HttpClientException.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.exception; 2 | 3 | /** 4 | * exception with bad request. 5 | *

6 | * Start--1(build request)-->Reqeust--2(connect network)-->Response--3(handle response)-->End 7 | * 8 | * @author MaTianyu 9 | * 2014-1-2上午12:53:13 10 | */ 11 | public class HttpClientException extends HttpException { 12 | private static final long serialVersionUID = -1710690396078830713L; 13 | private ClientException exceptionType; 14 | 15 | public HttpClientException(ClientException clientExp) { 16 | super(clientExp.toString()); 17 | exceptionType = clientExp; 18 | } 19 | 20 | public HttpClientException(Throwable cause) { 21 | super(cause.toString(), cause); 22 | exceptionType = ClientException.SomeOtherException; 23 | } 24 | 25 | public HttpClientException(Throwable cause, ClientException type) { 26 | super(cause.toString(), cause); 27 | exceptionType = type; 28 | } 29 | 30 | public ClientException getExceptionType() { 31 | return exceptionType; 32 | } 33 | 34 | public void setExceptionType(ClientException exceptionType) { 35 | this.exceptionType = exceptionType; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return exceptionType.toString(); 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/exception/HttpException.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.exception; 2 | 3 | /** 4 | * Base HttpException 5 | * Start--1(build request)-->Reqeust--2(connect network)-->Response--3(handle response)-->End 6 | * 7 | * @author MaTianyu 8 | * 2014-1-2上午12:51:38 9 | */ 10 | public abstract class HttpException extends Exception { 11 | private static final long serialVersionUID = -8585446012573642784L; 12 | public static boolean printStackTrace = true; 13 | protected boolean handled = true; 14 | 15 | public boolean isHandled() { 16 | return handled; 17 | } 18 | 19 | public T setHandled(boolean handled) { 20 | this.handled = handled; 21 | return (T) this; 22 | } 23 | 24 | public HttpException() {} 25 | 26 | public HttpException(String name) { 27 | super(name); 28 | } 29 | 30 | public HttpException(String name, Throwable cause) { 31 | super(name, cause); 32 | } 33 | 34 | public HttpException(Throwable cause) { 35 | super(cause); 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "HttpException{" + 41 | "handled=" + handled + 42 | "} " + super.toString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/exception/HttpNetException.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.exception; 2 | 3 | /** 4 | * exception when network error happened. 5 | * 6 | * @author MaTianyu 7 | * 2014-1-2上午12:53:13 8 | */ 9 | public class HttpNetException extends HttpException { 10 | private static final long serialVersionUID = 4961807092977094093L; 11 | private NetException exceptionType; 12 | //Network is unreachable 13 | public HttpNetException(NetException netExp) { 14 | super(netExp.toString()); 15 | exceptionType = netExp; 16 | } 17 | 18 | /** 19 | * 包括其他异常,网络不稳定因素或者防火墙限制 20 | * 21 | * @param cause 22 | */ 23 | public HttpNetException(Throwable cause) { 24 | super(cause.toString(), cause); 25 | exceptionType = NetException.NetworkUnstable; 26 | } 27 | 28 | public NetException getExceptionType() { 29 | return exceptionType; 30 | } 31 | 32 | public void setExceptionType(NetException exceptionType) { 33 | this.exceptionType = exceptionType; 34 | } 35 | 36 | 37 | 38 | @Override 39 | public String toString() { 40 | return exceptionType.toString(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/exception/HttpServerException.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.exception; 2 | 3 | import com.litesuits.http.data.HttpStatus; 4 | 5 | /** 6 | * exception that happen in server. 7 | * 8 | * @author MaTianyu 9 | * 2014-1-2上午12:53:13 10 | */ 11 | public class HttpServerException extends HttpException { 12 | private static final long serialVersionUID = 3695887939006497385L; 13 | private ServerException exceptionType; 14 | private HttpStatus status; 15 | 16 | public HttpServerException(ServerException e) { 17 | super(e.toString()); 18 | exceptionType = e; 19 | } 20 | 21 | public HttpServerException(HttpStatus status) { 22 | super(status.toString()); 23 | this.status = status; 24 | if (status.getCode() >= 500) { 25 | exceptionType = ServerException.ServerInnerError; 26 | } else { 27 | exceptionType = ServerException.ServerRejectClient; 28 | } 29 | } 30 | 31 | public ServerException getExceptionType() { 32 | return exceptionType; 33 | } 34 | 35 | public void setExceptionType(ServerException exceptionType) { 36 | this.exceptionType = exceptionType; 37 | } 38 | 39 | public HttpStatus getHttpStatus() { 40 | return status; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return exceptionType + ", " + status; 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/exception/NetException.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.exception; 2 | 3 | public enum NetException { 4 | NetworkNotAvilable("Network Is Not Avilable", "未连接网络"), 5 | NetworkUnstable("Network Is Unstable", "网络不稳定"), 6 | NetworkDisabled("Current Network Is Disabled By Your Setting", "已禁用该网络类型"), 7 | NetworkUnreachable("Network is unreachable", "网络无法访问"); 8 | 9 | private static final String TAG = NetException.class.getName(); 10 | public String reason; 11 | public String chiReason; 12 | 13 | NetException(String name, String chiName) { 14 | this.reason = name; 15 | this.chiReason = chiName; 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return TAG + ": " + this.reason + " (" + this.chiReason + ")"; 21 | } 22 | } -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/exception/ServerException.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.exception; 2 | 3 | public enum ServerException { 4 | //500 error 5 | ServerInnerError("Server Inner Exception", "服务器内部异常"), 6 | //400 error 7 | ServerRejectClient("Server Reject Client Exception", "服务器拒绝或无法提供服务"), 8 | //redirect too many 9 | RedirectTooMuch("Server RedirectTooMuch", "重定向次数过多"); 10 | 11 | private static final String TAG = ServerException.class.getName(); 12 | public String reason; 13 | public String chiReason; 14 | 15 | ServerException(String name, String chiName) { 16 | this.reason = name; 17 | this.chiReason = chiName; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return TAG +": " + this.reason + " (" + this.chiReason + ")"; 23 | } 24 | } -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/exception/handler/HttpExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.exception.handler; 2 | 3 | import com.litesuits.http.data.HttpStatus; 4 | import com.litesuits.http.exception.*; 5 | 6 | /** 7 | * Handle Response on UI Thread 8 | * 9 | * @author MaTianyu 10 | * 2014-2-26下午9:02:09 11 | */ 12 | public abstract class HttpExceptionHandler { 13 | 14 | public HttpExceptionHandler handleException(HttpException e) { 15 | if (e != null) { 16 | if (e instanceof HttpClientException) { 17 | HttpClientException ce = ((HttpClientException) e); 18 | onClientException(ce, ce.getExceptionType()); 19 | } else if (e instanceof HttpNetException) { 20 | HttpNetException ne = ((HttpNetException) e); 21 | onNetException(ne, ne.getExceptionType()); 22 | } else if (e instanceof HttpServerException) { 23 | HttpServerException se = ((HttpServerException) e); 24 | onServerException(se, se.getExceptionType(), se.getHttpStatus()); 25 | } else { 26 | HttpClientException ce = new HttpClientException(e); 27 | onClientException(ce, ce.getExceptionType()); 28 | } 29 | e.setHandled(true); 30 | } 31 | return this; 32 | } 33 | 34 | /** 35 | * 比如 URL为空,构建参数异常以及请求过程中遇到的其他客户端异常。 36 | * 37 | * @param e 38 | */ 39 | protected abstract void onClientException(HttpClientException e, ClientException type); 40 | 41 | /** 42 | * 比如 无网络,网络不稳定,该网络类型已被禁用等。 43 | * 44 | * @param e 45 | */ 46 | protected abstract void onNetException(HttpNetException e, NetException type); 47 | 48 | /** 49 | * 这个时候,连接是成功的。http header已经返回,但是status code是400~599之间。 50 | * [400-499]:因为客户端原因,服务器拒绝服务 51 | * [500~599]:基本是服务器内部错误或者网关异常造成的 52 | * 53 | * @param e 54 | */ 55 | protected abstract void onServerException(HttpServerException e, ServerException type, HttpStatus status); 56 | } 57 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/impl/huc/RetryHandler.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.impl.huc; 2 | 3 | import android.content.Context; 4 | import com.litesuits.http.exception.HttpNetException; 5 | import com.litesuits.http.exception.NetException; 6 | import com.litesuits.http.log.HttpLog; 7 | import com.litesuits.http.network.Network; 8 | 9 | import javax.net.ssl.SSLException; 10 | import java.io.FileNotFoundException; 11 | import java.io.IOException; 12 | import java.net.*; 13 | import java.util.HashSet; 14 | 15 | /** 16 | * determine whether to send request try again. 17 | * 试验发现,当url非法时,{@link HttpURLConnection}报MalformedURLException异常, 18 | * 而apache httpclient会报IllegalStateException异常。 19 | * 当url非法,和ssl错误时,不用重试。 当有可用网络但连接不稳定时,一般会报IO异常,此种情况尝试重试,以提高成功率。 20 | * 继承StandardHttpRequestRetryHandler因用到其判断请求方式是否幂等和连接是否取消等方法。 21 | * 22 | * @author MaTianyu 23 | * 2014-1-1下午5:03:46 24 | */ 25 | public class RetryHandler { 26 | public static final String TAG = RetryHandler.class.getSimpleName(); 27 | private HashSet> whitelist = new HashSet>(); 28 | private HashSet> blacklist = new HashSet>(); 29 | 30 | private int retrySleepTimeMS; 31 | 32 | /** 33 | * @param retrySleepTimeMS if the network is unstable, wait retrySleepTimeMS then start retry. 34 | */ 35 | public RetryHandler(int retrySleepTimeMS) { 36 | this.retrySleepTimeMS = retrySleepTimeMS; 37 | whitelist.add(SocketException.class); 38 | whitelist.add(SocketTimeoutException.class); 39 | 40 | blacklist.add(MalformedURLException.class); 41 | blacklist.add(UnknownHostException.class); 42 | blacklist.add(FileNotFoundException.class); 43 | blacklist.add(SSLException.class); 44 | } 45 | 46 | public RetryHandler setRetrySleepTimeMS(int retrySleepTimeMS) { 47 | this.retrySleepTimeMS = retrySleepTimeMS; 48 | return this; 49 | } 50 | 51 | public boolean retryRequest(IOException exception, int retryCount, int maxRetries, 52 | Context appContext) throws HttpNetException, InterruptedException { 53 | boolean retry = true; 54 | if (retryCount > maxRetries) { 55 | if (HttpLog.isPrint) { 56 | HttpLog.w(TAG, "retry count > max retry times.."); 57 | } 58 | throw new HttpNetException(exception); 59 | } else if (isInList(blacklist, exception)) { 60 | if (HttpLog.isPrint) { 61 | HttpLog.w(TAG, "exception in blacklist.."); 62 | } 63 | retry = false; 64 | } else if (isInList(whitelist, exception)) { 65 | if (HttpLog.isPrint) { 66 | HttpLog.w(TAG, "exception in whitelist.."); 67 | } 68 | retry = true; 69 | } 70 | if (retry) { 71 | if (appContext != null) { 72 | if (Network.isConnected(appContext)) { 73 | HttpLog.d(TAG, "Network isConnected, retry now"); 74 | } else if (Network.isConnectedOrConnecting(appContext)) { 75 | if (HttpLog.isPrint) { 76 | HttpLog.v(TAG, "Network is Connected Or Connecting, wait for retey : " 77 | + retrySleepTimeMS + " ms"); 78 | } 79 | Thread.sleep(retrySleepTimeMS); 80 | } else { 81 | HttpLog.d(TAG, "Without any Network , immediately cancel retry"); 82 | throw new HttpNetException(NetException.NetworkNotAvilable); 83 | } 84 | } else { 85 | if (HttpLog.isPrint) { 86 | HttpLog.v(TAG, "app context is null.."); 87 | HttpLog.v(TAG, "wait for retry : " + retrySleepTimeMS + " ms"); 88 | } 89 | Thread.sleep(retrySleepTimeMS); 90 | } 91 | } 92 | if (HttpLog.isPrint) { 93 | HttpLog.i(TAG, "retry: " + retry + " , retryCount: " + retryCount + " , exception: " + exception); 94 | } 95 | return retry; 96 | } 97 | 98 | protected boolean isInList(HashSet> list, Throwable error) { 99 | for (Class aList : list) { 100 | if (aList.isInstance(error)) { 101 | return true; 102 | } 103 | } 104 | return false; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/listener/StatisticsListener.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.listener; 2 | 3 | import android.os.SystemClock; 4 | import com.litesuits.http.data.StatisticsInfo; 5 | import com.litesuits.http.request.AbstractRequest; 6 | import com.litesuits.http.response.InternalResponse; 7 | import com.litesuits.http.response.Response; 8 | 9 | public class StatisticsListener { 10 | private static final String TAG = StatisticsListener.class.getSimpleName(); 11 | private StatisticsInfo statisticsInfo; 12 | private InternalResponse internalResponse; 13 | private long total, connect, connectStart, read, readStart, headLen, readLen; 14 | 15 | public StatisticsListener(InternalResponse internalResponse, StatisticsInfo statisticsInfo) { 16 | this.internalResponse = internalResponse; 17 | this.statisticsInfo = statisticsInfo; 18 | } 19 | 20 | public void onStart(AbstractRequest request) { 21 | total = SystemClock.uptimeMillis(); 22 | } 23 | 24 | public void onEnd(Response res) { 25 | if (total > 0) { 26 | total = SystemClock.uptimeMillis() - total; 27 | internalResponse.setUseTime(total); 28 | statisticsInfo.addConnectTime(total); 29 | 30 | headLen = internalResponse.getContentLength(); 31 | readLen = internalResponse.getReadedLength(); 32 | long len = 0; 33 | if (readLen > 0) { 34 | len = readLen; 35 | } 36 | if (len == 0 && headLen > 0) { 37 | len = headLen; 38 | } 39 | statisticsInfo.addDataLength(len); 40 | } 41 | } 42 | 43 | public void onRetry(AbstractRequest req, int max, int now) { 44 | 45 | } 46 | 47 | public void onRedirect(AbstractRequest req) { 48 | 49 | } 50 | 51 | public void onPreConnect(AbstractRequest request) { 52 | connectStart = SystemClock.uptimeMillis(); 53 | } 54 | 55 | public void onAfterConnect(AbstractRequest request) { 56 | connect += SystemClock.uptimeMillis() - connectStart; 57 | } 58 | 59 | public void onPreRead(AbstractRequest request) { 60 | readStart = SystemClock.uptimeMillis(); 61 | } 62 | 63 | public void onAfterRead(AbstractRequest request) { 64 | read += SystemClock.uptimeMillis() - readStart; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return resToString(); 70 | } 71 | 72 | public String resToString() { 73 | return 74 | "\n[length] headerLen: " + headLen 75 | + " B, readedLen: " + readLen + " B, global total len: " 76 | + statisticsInfo.getDataLength() + " B" 77 | + "\n[time] connect : " + connect + " MS, read: " 78 | + read + " MS, total: " + total + " MS, global total time: " 79 | + statisticsInfo.getConnectTime() + " MS"; 80 | } 81 | } -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/parser/DataParser.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.parser; 2 | 3 | import com.litesuits.http.HttpConfig; 4 | import com.litesuits.http.data.Consts; 5 | import com.litesuits.http.listener.HttpListener; 6 | import com.litesuits.http.request.AbstractRequest; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | 12 | /** 13 | * base data parser 14 | * 15 | * @author MaTianyu 16 | * 2014-2-21下午7:26:58 17 | */ 18 | public abstract class DataParser { 19 | protected static final String TAG = DataParser.class.getSimpleName(); 20 | protected T data; 21 | protected long readLength; 22 | protected AbstractRequest request; 23 | protected String charSet = Consts.DEFAULT_CHARSET; 24 | protected int buffSize = HttpConfig.DEFAULT_BUFFER_SIZE; 25 | 26 | /** 27 | * source 1. read data form network 28 | */ 29 | public T readFromNetStream(InputStream stream, long len, String charSet) throws IOException { 30 | if (stream != null) { 31 | try { 32 | this.data = parseNetStream(stream, len, charSet); 33 | } finally { 34 | stream.close(); 35 | } 36 | } 37 | return this.data; 38 | } 39 | 40 | /** 41 | * source 2. read data form disk 42 | */ 43 | public abstract T readFromDiskCache(File file) throws IOException; 44 | 45 | 46 | /** 47 | * source 3. read data form network 48 | */ 49 | public final T readFromMemoryCache(T data) { 50 | if (isMemCacheSupport()) { 51 | this.data = data; 52 | } 53 | return this.data; 54 | } 55 | 56 | /** 57 | * parse network stream 58 | */ 59 | protected abstract T parseNetStream(InputStream stream, long totalLength, 60 | String charSet) throws IOException; 61 | 62 | /** 63 | * is memory cache supported 64 | */ 65 | public abstract boolean isMemCacheSupport(); 66 | 67 | /** 68 | * get the data 69 | * 70 | * @return custom data 71 | */ 72 | public final T getData() { 73 | return data; 74 | } 75 | 76 | 77 | /** 78 | * length of data 79 | */ 80 | public final long getReadedLength() { 81 | return readLength; 82 | } 83 | 84 | /** 85 | * set a request to parser 86 | */ 87 | public final void setRequest(AbstractRequest request) { 88 | this.request = request; 89 | if (request.getCharSet() != null) { 90 | charSet = request.getCharSet(); 91 | } 92 | } 93 | 94 | public String getRawString() { 95 | return null; 96 | } 97 | 98 | /** 99 | * translate original bytes to custom bytes. 100 | * if your data is encrypted, you can override this method to decrypt it. 101 | * 102 | * @param bytes data form server 103 | * @return decrypt data 104 | */ 105 | protected byte[] translateBytes(byte[] bytes) { 106 | return bytes; 107 | } 108 | 109 | /** 110 | * notify readed length to listener 111 | */ 112 | protected final void notifyReading(long total, long len) { 113 | HttpListener listener = request.getHttpListener(); 114 | if (listener != null) { 115 | listener.notifyCallLoading(request, total, len); 116 | } 117 | } 118 | 119 | @Override 120 | public String toString() { 121 | return "DataParser{" + 122 | "buffSize=" + buffSize + 123 | ", readLength=" + readLength + 124 | '}'; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/parser/FileCacheableParser.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.parser; 2 | 3 | import com.litesuits.http.log.HttpLog; 4 | 5 | import java.io.*; 6 | 7 | /** 8 | * @author MaTianyu 9 | * @date 2015-04-26 10 | */ 11 | public abstract class FileCacheableParser extends DataParser { 12 | protected File file; 13 | public FileCacheableParser() { 14 | } 15 | public FileCacheableParser(File saveToFile) { 16 | this.file = saveToFile; 17 | } 18 | 19 | public final T readFromDiskCache(File file) throws IOException { 20 | data = parseDiskCache(file); 21 | return data; 22 | } 23 | 24 | /** 25 | * parse local file 26 | */ 27 | protected abstract T parseDiskCache(File file) throws IOException; 28 | 29 | @Override 30 | public boolean isMemCacheSupport() { 31 | return false; 32 | } 33 | 34 | protected final File streamToFile(InputStream is, long len) throws IOException { 35 | File file = request.getCachedFile(); 36 | FileOutputStream fos = null; 37 | try { 38 | File pFile = file.getParentFile(); 39 | if (!pFile.exists()) { 40 | boolean mk = pFile.mkdirs(); 41 | if (HttpLog.isPrint) { 42 | HttpLog.i(TAG, "keep cache mkdirs result: " + mk + " path:" + pFile.getAbsolutePath()); 43 | } 44 | } 45 | fos = new FileOutputStream(file); 46 | byte[] tmp = new byte[buffSize]; 47 | int l; 48 | while (!request.isCancelledOrInterrupted() && (l = is.read(tmp)) != -1) { 49 | tmp = translateBytes(tmp); 50 | fos.write(tmp, 0, l); 51 | readLength += l; 52 | notifyReading(len, readLength); 53 | } 54 | if (HttpLog.isPrint) { 55 | HttpLog.i("FileParser", "file len: " + file.length()); 56 | } 57 | } finally { 58 | if (fos != null) { 59 | fos.close(); 60 | } 61 | } 62 | return file; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/parser/impl/BitmapParser.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.parser.impl; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import com.litesuits.http.parser.FileCacheableParser; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | 11 | /** 12 | * parse inputstream to bitmap. 13 | * 14 | * @author MaTianyu 15 | * 2014-2-21下午8:56:59 16 | */ 17 | public class BitmapParser extends FileCacheableParser { 18 | public BitmapParser() {} 19 | public BitmapParser(File file) { 20 | this.file = file; 21 | } 22 | 23 | @Override 24 | public Bitmap parseNetStream(InputStream stream, long len, String charSet) throws IOException { 25 | //if (this.file != null || request.isCachedModel() 26 | // || (request.getHttpListener() != null && request.getHttpListener().isReadingNotify())) { 27 | // File file = streamToFile(stream, len, cacheDir); 28 | // return BitmapFactory.decodeFile(file.getAbsolutePath()); 29 | //} else { 30 | // return BitmapFactory.decodeStream(stream); 31 | //} 32 | file = streamToFile(stream, len); 33 | return BitmapFactory.decodeFile(file.getAbsolutePath()); 34 | } 35 | 36 | @Override 37 | public Bitmap parseDiskCache(File file) { 38 | return BitmapFactory.decodeFile(file.getAbsolutePath()); 39 | } 40 | } -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/parser/impl/BytesParser.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.parser.impl; 2 | 3 | import com.litesuits.http.parser.MemCacheableParser; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | 8 | /** 9 | * parse inputstream to bytes. 10 | * 11 | * @author MaTianyu 12 | * 2014-2-21下午8:56:59 13 | */ 14 | public class BytesParser extends MemCacheableParser { 15 | 16 | @Override 17 | public byte[] parseNetStream(InputStream stream, long len, String charSet) throws IOException { 18 | return streamToByteArray(stream, len); 19 | } 20 | 21 | @Override 22 | protected byte[] parseDiskCache(InputStream stream, long length) throws IOException { 23 | return streamToByteArray(stream, length); 24 | } 25 | 26 | 27 | @Override 28 | protected boolean tryKeepToCache(byte[] data) throws IOException { 29 | return keepToCache(data); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/parser/impl/FileParser.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.parser.impl; 2 | 3 | import com.litesuits.http.parser.FileCacheableParser; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | 9 | /** 10 | * parse inputstream to file. 11 | * 12 | * @author MaTianyu 13 | * 2014-2-21下午8:56:59 14 | */ 15 | public class FileParser extends FileCacheableParser { 16 | public FileParser() { 17 | } 18 | public FileParser(File saveToFile) { 19 | this.file = saveToFile; 20 | } 21 | 22 | @Override 23 | public File parseNetStream(InputStream stream, long len, String charSet) throws IOException { 24 | return streamToFile(stream, len); 25 | } 26 | 27 | @Override 28 | public File parseDiskCache(File file) { 29 | return file; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/parser/impl/JsonParser.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.parser.impl; 2 | 3 | import com.litesuits.http.data.Json; 4 | import com.litesuits.http.parser.MemCacheableParser; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.lang.reflect.Type; 9 | 10 | /** 11 | * parse inputstream to java model. 12 | * 13 | * @author MaTianyu 14 | * 2014-4-19 15 | */ 16 | public class JsonParser extends MemCacheableParser { 17 | protected Type claxx; 18 | protected String json; 19 | 20 | public JsonParser(Type claxx) { 21 | this.claxx = claxx; 22 | } 23 | 24 | @Override 25 | protected T parseNetStream(InputStream stream, long totalLength 26 | , String charSet) throws IOException { 27 | json = streamToString(stream, totalLength, charSet); 28 | return Json.get().toObject(json, claxx); 29 | } 30 | 31 | @Override 32 | protected T parseDiskCache(InputStream stream, long length) throws IOException { 33 | json = streamToString(stream, length, charSet); 34 | return Json.get().toObject(json, claxx); 35 | } 36 | 37 | @Override 38 | protected boolean tryKeepToCache(T data) throws IOException { 39 | return keepToCache(json); 40 | } 41 | 42 | /** 43 | * get the row string 44 | */ 45 | @Override 46 | public String getRawString() { 47 | return json; 48 | } 49 | 50 | /** 51 | * get the json model 52 | */ 53 | public C getJsonModel(Class claxx) { 54 | return Json.get().toObject(json, claxx); 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return "JsonParser{" + 60 | "claxx=" + claxx + 61 | "} " + super.toString(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/parser/impl/StringParser.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.parser.impl; 2 | 3 | import com.litesuits.http.parser.MemCacheableParser; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | 8 | /** 9 | * parse inputstream to string. 10 | * 11 | * @author MaTianyu 12 | * 2014-2-21下午8:56:59 13 | */ 14 | public class StringParser extends MemCacheableParser { 15 | 16 | @Override 17 | public String parseNetStream(InputStream stream, long len, String charSet) throws IOException { 18 | return streamToString(stream, len, charSet); 19 | } 20 | 21 | @Override 22 | protected String parseDiskCache(InputStream stream, long length) throws IOException { 23 | return streamToString(stream, length, charSet); 24 | } 25 | 26 | @Override 27 | protected boolean tryKeepToCache(String data) throws IOException { 28 | return keepToCache(data); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/BitmapRequest.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request; 2 | 3 | import android.graphics.Bitmap; 4 | import com.litesuits.http.parser.DataParser; 5 | import com.litesuits.http.parser.impl.BitmapParser; 6 | import com.litesuits.http.request.param.HttpParamModel; 7 | import com.litesuits.http.request.param.NonHttpParam; 8 | 9 | import java.io.File; 10 | 11 | /** 12 | * @author MaTianyu 13 | * @date 2015-04-18 14 | */ 15 | public class BitmapRequest extends AbstractRequest { 16 | 17 | @NonHttpParam 18 | protected File saveToFile; 19 | 20 | public BitmapRequest(HttpParamModel model) { 21 | super(model); 22 | } 23 | 24 | public BitmapRequest(HttpParamModel model, File saveToFile) { 25 | super(model); 26 | this.saveToFile = saveToFile; 27 | } 28 | 29 | public BitmapRequest(HttpParamModel model, String saveToPath) { 30 | super(model); 31 | setFileSavePath(saveToPath); 32 | } 33 | 34 | public BitmapRequest(String url) { 35 | super(url); 36 | } 37 | 38 | public BitmapRequest(String url, File saveToFile) { 39 | super(url); 40 | this.saveToFile = saveToFile; 41 | } 42 | 43 | public BitmapRequest(String url, String saveToPath) { 44 | super(url); 45 | setFileSavePath(saveToPath); 46 | } 47 | 48 | 49 | public BitmapRequest setFileSavePath(String savaToPath) { 50 | if (savaToPath != null) { 51 | saveToFile = new File(savaToPath); 52 | } 53 | return this; 54 | } 55 | 56 | public File getCachedFile() { 57 | return saveToFile != null ? saveToFile : super.getCachedFile(); 58 | } 59 | 60 | @Override 61 | public DataParser createDataParser() { 62 | return new BitmapParser(saveToFile); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/BytesRequest.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request; 2 | 3 | import com.litesuits.http.parser.DataParser; 4 | import com.litesuits.http.parser.impl.BytesParser; 5 | import com.litesuits.http.request.param.HttpParamModel; 6 | 7 | /** 8 | * @author MaTianyu 9 | * @date 2015-04-18 10 | */ 11 | public class BytesRequest extends AbstractRequest { 12 | 13 | public BytesRequest(String url) { 14 | super(url); 15 | } 16 | 17 | public BytesRequest(HttpParamModel model) { 18 | super(model); 19 | } 20 | 21 | @Override 22 | public DataParser createDataParser() { 23 | return new BytesParser(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/FileRequest.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request; 2 | 3 | import com.litesuits.http.parser.DataParser; 4 | import com.litesuits.http.parser.impl.FileParser; 5 | import com.litesuits.http.request.param.HttpParamModel; 6 | import com.litesuits.http.request.param.NonHttpParam; 7 | 8 | import java.io.File; 9 | 10 | /** 11 | * @author MaTianyu 12 | * @date 2015-04-18 13 | */ 14 | public class FileRequest extends AbstractRequest { 15 | 16 | @NonHttpParam 17 | private File saveToFile; 18 | 19 | public FileRequest(String url) { 20 | super(url); 21 | } 22 | 23 | public FileRequest(HttpParamModel model, String savaToPath) { 24 | super(model); 25 | setFileSavePath(savaToPath); 26 | } 27 | 28 | public FileRequest(HttpParamModel model, File saveToFile) { 29 | super(model); 30 | this.saveToFile = saveToFile; 31 | } 32 | 33 | public FileRequest(String url, File saveToFile) { 34 | super(url); 35 | this.saveToFile = saveToFile; 36 | } 37 | 38 | public FileRequest(String url, String savaToPath) { 39 | super(url); 40 | setFileSavePath(savaToPath); 41 | } 42 | 43 | public FileRequest setFileSavePath(String savaToPath) { 44 | if (savaToPath != null) { 45 | saveToFile = new File(savaToPath); 46 | } 47 | return this; 48 | } 49 | 50 | public File getCachedFile() { 51 | return saveToFile != null ? saveToFile : super.getCachedFile(); 52 | } 53 | 54 | @Override 55 | public DataParser createDataParser() { 56 | return new FileParser(saveToFile); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/JsonAbsRequest.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request; 2 | 3 | import com.litesuits.http.parser.DataParser; 4 | import com.litesuits.http.parser.impl.JsonParser; 5 | import com.litesuits.http.request.param.HttpParamModel; 6 | import com.litesuits.http.request.param.NonHttpParam; 7 | 8 | import java.lang.reflect.ParameterizedType; 9 | import java.lang.reflect.Type; 10 | 11 | /** 12 | * @author MaTianyu 13 | * @date 2015-04-18 14 | */ 15 | public abstract class JsonAbsRequest extends AbstractRequest { 16 | 17 | @NonHttpParam 18 | protected Type resultType; 19 | 20 | public JsonAbsRequest(String url) { 21 | super(url); 22 | } 23 | 24 | protected JsonAbsRequest(HttpParamModel model) { 25 | super(model); 26 | } 27 | 28 | protected JsonAbsRequest(String url, HttpParamModel model) { 29 | super(url, model); 30 | } 31 | 32 | @Override 33 | public DataParser createDataParser() { 34 | return new JsonParser(getResultType()); 35 | } 36 | 37 | public Type getResultType() { 38 | if (resultType == null) { 39 | resultType = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 40 | } 41 | return resultType; 42 | } 43 | 44 | @SuppressWarnings("unchecked") 45 | public R setResultType(Type resultType) { 46 | this.resultType = resultType; 47 | return (R) this; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/JsonRequest.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request; 2 | 3 | import com.litesuits.http.data.TypeToken; 4 | import com.litesuits.http.parser.DataParser; 5 | import com.litesuits.http.parser.impl.JsonParser; 6 | import com.litesuits.http.request.param.HttpParamModel; 7 | 8 | import java.lang.reflect.Type; 9 | 10 | /** 11 | * @author MaTianyu 12 | * @date 2015-04-18 13 | */ 14 | public class JsonRequest extends JsonAbsRequest { 15 | 16 | public JsonRequest(String url, Type resultType) { 17 | super(url); 18 | setResultType(resultType); 19 | } 20 | 21 | public JsonRequest(HttpParamModel model, Type resultType) { 22 | super(model); 23 | setResultType(resultType); 24 | } 25 | 26 | public JsonRequest(String url, TypeToken resultType) { 27 | super(url); 28 | setResultType(resultType.getType()); 29 | } 30 | 31 | public JsonRequest(HttpParamModel model, TypeToken resultType) { 32 | super(model); 33 | setResultType(resultType.getType()); 34 | } 35 | 36 | @Override 37 | public DataParser createDataParser() { 38 | return new JsonParser(resultType); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/StringRequest.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request; 2 | 3 | import com.litesuits.http.parser.DataParser; 4 | import com.litesuits.http.parser.impl.StringParser; 5 | import com.litesuits.http.request.param.HttpParamModel; 6 | 7 | /** 8 | * @author MaTianyu 9 | * @date 2015-04-18 10 | */ 11 | public class StringRequest extends AbstractRequest { 12 | 13 | public StringRequest(String url) { 14 | super(url); 15 | } 16 | 17 | public StringRequest(HttpParamModel model) { 18 | super(model); 19 | } 20 | 21 | public StringRequest(String url, HttpParamModel model) { 22 | super(url, model); 23 | } 24 | 25 | @Override 26 | public DataParser createDataParser() { 27 | return new StringParser(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/ByteArrayBody.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content; 2 | 3 | import com.litesuits.http.data.Consts; 4 | 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | import java.util.Arrays; 8 | 9 | /** 10 | * @author MaTianyu 11 | * @date 14-7-29 12 | */ 13 | public class ByteArrayBody extends HttpBody { 14 | private byte[] bytes; 15 | 16 | public ByteArrayBody(byte[] bytes) { 17 | this(bytes, Consts.MIME_TYPE_OCTET_STREAM); 18 | } 19 | 20 | public ByteArrayBody(byte[] bytes, String contentType) { 21 | this.bytes = bytes; 22 | this.contentType = contentType; 23 | } 24 | 25 | 26 | @Override 27 | public long getContentLength() { 28 | return bytes.length; 29 | } 30 | 31 | @Override 32 | public void writeTo(OutputStream outstream) throws IOException { 33 | outstream.write(bytes); 34 | outstream.flush(); 35 | } 36 | 37 | public byte[] getBytes() { 38 | return bytes; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "ByteArrayBody{" + 44 | "bytes=" + Arrays.toString(bytes) + 45 | "} " + super.toString(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/FileBody.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content; 2 | 3 | import com.litesuits.http.data.Consts; 4 | 5 | import java.io.*; 6 | 7 | /** 8 | * @author MaTianyu 9 | * @date 14-7-29 10 | */ 11 | public class FileBody extends HttpBody { 12 | private File file; 13 | 14 | public FileBody(File file) { 15 | this(file, Consts.MIME_TYPE_OCTET_STREAM); 16 | } 17 | 18 | public FileBody(File file, String contentType) { 19 | this.file = file; 20 | this.contentType = contentType; 21 | } 22 | 23 | public File getFile() { 24 | return file; 25 | } 26 | 27 | @Override 28 | public long getContentLength() { 29 | return file.length(); 30 | } 31 | 32 | @Override 33 | public void writeTo(OutputStream outstream) throws IOException { 34 | final InputStream instream = new FileInputStream(this.file); 35 | try { 36 | final byte[] tmp = new byte[OUTPUT_BUFFER_SIZE]; 37 | int l; 38 | while ((l = instream.read(tmp)) != -1) { 39 | outstream.write(tmp, 0, l); 40 | } 41 | outstream.flush(); 42 | } finally { 43 | instream.close(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/HttpBody.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content; 2 | 3 | import com.litesuits.http.HttpConfig; 4 | import com.litesuits.http.listener.HttpListener; 5 | import com.litesuits.http.request.AbstractRequest; 6 | 7 | import java.io.IOException; 8 | import java.io.OutputStream; 9 | 10 | /** 11 | * @author MaTianyu 12 | * @date 14-7-29 13 | */ 14 | public abstract class HttpBody { 15 | public static final int OUTPUT_BUFFER_SIZE = HttpConfig.DEFAULT_BUFFER_SIZE; 16 | protected HttpListener httpListener; 17 | protected AbstractRequest request; 18 | protected String contentType; 19 | protected String contentEncoding; 20 | 21 | public String getContentType() { 22 | return contentType; 23 | } 24 | 25 | public abstract long getContentLength(); 26 | 27 | public abstract void writeTo(OutputStream outstream) throws IOException; 28 | 29 | public HttpBody setContentType(String contentType) { 30 | this.contentType = contentType; 31 | return this; 32 | } 33 | 34 | public String getContentEncoding() { 35 | return contentEncoding; 36 | } 37 | 38 | public HttpBody setContentEncoding(String contentEncoding) { 39 | this.contentEncoding = contentEncoding; 40 | return this; 41 | } 42 | 43 | public HttpListener getHttpListener() { 44 | return httpListener; 45 | } 46 | 47 | public void setHttpListener(HttpListener httpListener) { 48 | this.httpListener = httpListener; 49 | } 50 | 51 | public AbstractRequest getRequest() { 52 | return request; 53 | } 54 | 55 | public void setRequest(AbstractRequest request) { 56 | this.request = request; 57 | setHttpListener(request.getHttpListener()); 58 | } 59 | } -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/InputStreamBody.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content; 2 | 3 | import com.litesuits.http.data.Consts; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.OutputStream; 8 | 9 | /** 10 | * @author MaTianyu 11 | * @date 14-7-29 12 | */ 13 | public class InputStreamBody extends HttpBody { 14 | protected InputStream instream; 15 | protected long length; 16 | 17 | public InputStreamBody(InputStream instream) { 18 | this(instream, null); 19 | } 20 | 21 | public InputStreamBody(InputStream instream, String contentType) { 22 | this(instream, contentType, -1); 23 | } 24 | 25 | public InputStreamBody(InputStream instream, String contentType, long length) { 26 | this.instream = instream; 27 | this.contentType = (contentType != null) ? contentType : Consts.MIME_TYPE_OCTET_STREAM; 28 | this.length = length; 29 | } 30 | 31 | public InputStream getInstream() { 32 | return instream; 33 | } 34 | 35 | @Override 36 | public long getContentLength() { 37 | return length; 38 | } 39 | 40 | @Override 41 | public void writeTo(OutputStream outstream) throws IOException { 42 | if (instream == null) { 43 | return; 44 | } 45 | try { 46 | final byte[] buffer = new byte[OUTPUT_BUFFER_SIZE]; 47 | int l; 48 | if (this.length < 0) { 49 | // consume until EOF 50 | while ((l = instream.read(buffer)) != -1) { 51 | outstream.write(buffer, 0, l); 52 | } 53 | } else { 54 | // consume no more than length 55 | long remaining = this.length; 56 | while (remaining > 0) { 57 | l = instream.read(buffer, 0, (int) Math.min(OUTPUT_BUFFER_SIZE, remaining)); 58 | if (l == -1) { 59 | break; 60 | } 61 | outstream.write(buffer, 0, l); 62 | remaining -= l; 63 | } 64 | } 65 | outstream.flush(); 66 | } finally { 67 | instream.close(); 68 | } 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | return "InputStreamBody{" + 74 | "instream=" + instream + 75 | ", length=" + length + 76 | "} " + super.toString(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/JsonBody.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content; 2 | 3 | import com.litesuits.http.data.Consts; 4 | import com.litesuits.http.data.Json; 5 | 6 | /** 7 | * @author MaTianyu 8 | * @date 14-7-29 9 | */ 10 | public class JsonBody extends StringBody { 11 | 12 | public JsonBody(Object param) { 13 | this(param, Consts.DEFAULT_CHARSET); 14 | } 15 | 16 | public JsonBody(String param) { 17 | this(param, Consts.DEFAULT_CHARSET); 18 | } 19 | 20 | public JsonBody(String json, String charset) { 21 | super(json, Consts.MIME_TYPE_JSON, charset); 22 | } 23 | 24 | public JsonBody(Object param, String charset) { 25 | super(Json.get().toJson(param), Consts.MIME_TYPE_JSON, charset); 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return "JsonBody{} " + super.toString(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/SerializableBody.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.ObjectOutputStream; 6 | import java.io.Serializable; 7 | 8 | /** 9 | * @author MaTianyu 10 | * @date 14-7-29 11 | */ 12 | public class SerializableBody extends ByteArrayBody { 13 | 14 | public SerializableBody(Serializable ser) { 15 | super(getBytes(ser), null); 16 | } 17 | 18 | public static byte[] getBytes(Serializable ser) { 19 | try { 20 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 21 | ObjectOutputStream oos = null; 22 | oos = new ObjectOutputStream(baos); 23 | oos.writeObject(ser); 24 | return baos.toByteArray(); 25 | } catch (IOException e) { 26 | e.printStackTrace(); 27 | } 28 | return null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/StringBody.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content; 2 | 3 | import com.litesuits.http.data.Consts; 4 | 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | import java.io.UnsupportedEncodingException; 8 | 9 | /** 10 | * @author MaTianyu 11 | * @date 14-7-29 12 | */ 13 | public class StringBody extends HttpBody { 14 | protected String charset; 15 | protected String mimeType; 16 | protected String string; 17 | protected byte[] content; 18 | 19 | 20 | public StringBody(String string) { 21 | this(string, null, null); 22 | } 23 | 24 | public StringBody(String string, String mimeType, String charset) { 25 | if (mimeType == null) { 26 | mimeType = Consts.MIME_TYPE_TEXT; 27 | } 28 | if (charset == null) { 29 | charset = Consts.DEFAULT_CHARSET; 30 | } 31 | this.charset = charset; 32 | this.string = string; 33 | this.mimeType = mimeType; 34 | try { 35 | this.content = string.getBytes(charset); 36 | } catch (UnsupportedEncodingException e) { 37 | e.printStackTrace(); 38 | } 39 | this.contentType = mimeType + Consts.CHARSET_PARAM + charset; 40 | } 41 | 42 | @Override 43 | public long getContentLength() { 44 | return content.length; 45 | } 46 | 47 | @Override 48 | public void writeTo(OutputStream outstream) throws IOException { 49 | outstream.write(this.content); 50 | outstream.flush(); 51 | } 52 | 53 | public String getString() { 54 | return string; 55 | } 56 | 57 | public String getCharset() { 58 | return charset; 59 | } 60 | 61 | public String getMimeType() { 62 | return mimeType; 63 | } 64 | 65 | public byte[] getContent() { 66 | return content; 67 | } 68 | 69 | @Override 70 | public String toString() { 71 | return "StringBody{" + 72 | "charset='" + charset + '\'' + 73 | ", mimeType='" + mimeType + '\'' + 74 | ", string='" + string + '\'' + 75 | "} " ; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/UrlEncodedFormBody.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content; 2 | 3 | import com.litesuits.http.data.Consts; 4 | import com.litesuits.http.data.NameValuePair; 5 | 6 | import java.io.UnsupportedEncodingException; 7 | import java.net.URLEncoder; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author MaTianyu 13 | * @date 14-7-29 14 | */ 15 | public class UrlEncodedFormBody extends StringBody { 16 | 17 | public UrlEncodedFormBody(String encodeBody) { 18 | super(encodeBody, Consts.MIME_TYPE_FORM_URLENCODE, Consts.DEFAULT_CHARSET); 19 | } 20 | 21 | public UrlEncodedFormBody(String encodeBody, String charset) { 22 | super(encodeBody, Consts.MIME_TYPE_FORM_URLENCODE, charset); 23 | } 24 | 25 | public UrlEncodedFormBody(List list) { 26 | super(handleListValue(list, Consts.DEFAULT_CHARSET), Consts.MIME_TYPE_FORM_URLENCODE, Consts.DEFAULT_CHARSET); 27 | } 28 | 29 | public UrlEncodedFormBody(List list, String charset) { 30 | super(handleListValue(list, charset), Consts.MIME_TYPE_FORM_URLENCODE, charset); 31 | } 32 | 33 | public UrlEncodedFormBody(Map map) { 34 | super(handleMapValue(map, Consts.DEFAULT_CHARSET), Consts.MIME_TYPE_FORM_URLENCODE, Consts.DEFAULT_CHARSET); 35 | } 36 | 37 | public UrlEncodedFormBody(Map map, String charset) { 38 | super(handleMapValue(map, charset), Consts.MIME_TYPE_FORM_URLENCODE, charset); 39 | } 40 | 41 | private static String handleMapValue(Map map, String charset) { 42 | if (map == null) { 43 | return ""; 44 | } 45 | StringBuilder sb = new StringBuilder(); 46 | boolean isF = true; 47 | for (Map.Entry entry : map.entrySet()) { 48 | if (!isF) 49 | sb.append(Consts.AND); 50 | else 51 | isF = false; 52 | try { 53 | sb.append(URLEncoder.encode(entry.getKey(), charset)) 54 | .append(Consts.EQUALS) 55 | .append(URLEncoder.encode(entry.getValue(), charset)); 56 | } catch (UnsupportedEncodingException e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | return sb.toString(); 61 | } 62 | 63 | private static String handleListValue(List list, String charset) { 64 | if (list == null) { 65 | return ""; 66 | } 67 | StringBuilder sb = new StringBuilder(); 68 | boolean isF = true; 69 | for (NameValuePair p : list) { 70 | if (!isF) 71 | sb.append(Consts.AND); 72 | else 73 | isF = false; 74 | try { 75 | sb.append(URLEncoder.encode(p.getName(), charset)) 76 | .append(Consts.EQUALS) 77 | .append(URLEncoder.encode(p.getValue(), charset)); 78 | } catch (UnsupportedEncodingException e) { 79 | e.printStackTrace(); 80 | } 81 | } 82 | return sb.toString(); 83 | } 84 | 85 | 86 | @Override 87 | public String toString() { 88 | return "StringEntity{" + 89 | "string='" + string + '\'' + 90 | ", charset='" + charset + '\'' + 91 | ", contentType='" + contentType + '\'' + 92 | '}'; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/multi/AbstractPart.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content.multi; 2 | 3 | import com.litesuits.http.data.Consts; 4 | import com.litesuits.http.utils.StringCodingUtils; 5 | 6 | import java.io.ByteArrayOutputStream; 7 | import java.io.IOException; 8 | import java.io.OutputStream; 9 | import java.nio.charset.Charset; 10 | 11 | /** 12 | * 抽象上传类 13 | * 14 | * @author MaTianyu 15 | * @date 14-7-29 16 | */ 17 | public abstract class AbstractPart { 18 | 19 | protected static final Charset infoCharset = BoundaryCreater.charset; 20 | public static final byte[] CR_LF = StringCodingUtils.getBytes("\r\n", infoCharset); 21 | public static final byte[] TRANSFER_ENCODING_BINARY = 22 | StringCodingUtils.getBytes("Content-Transfer-Encoding: binary\r\n", infoCharset); 23 | public static final byte[] TRANSFER_ENCODING_8BIT = 24 | StringCodingUtils.getBytes("Content-Transfer-Encoding: 8bit\r\n", infoCharset); 25 | 26 | 27 | protected String key; 28 | public byte[] header; 29 | protected String mimeType = Consts.MIME_TYPE_OCTET_STREAM; 30 | protected MultipartBody multipartBody; 31 | 32 | protected AbstractPart(String key, String mimeType) { 33 | this.key = key; 34 | if (mimeType != null) { 35 | this.mimeType = mimeType; 36 | } 37 | } 38 | 39 | //此方法需要被调用以产生header(开发者无需自己调用,Entity会调用它) 40 | public byte[] createHeader(byte[] boundaryLine) { 41 | ByteArrayOutputStream headerStream = new ByteArrayOutputStream(); 42 | try { 43 | headerStream.write(boundaryLine); 44 | headerStream.write(createContentDisposition()); 45 | headerStream.write(createContentType()); 46 | headerStream.write(getTransferEncoding()); 47 | headerStream.write(CR_LF); 48 | header = headerStream.toByteArray(); 49 | } catch (IOException e) { 50 | e.printStackTrace(); 51 | } 52 | return header; 53 | } 54 | 55 | protected abstract byte[] createContentType(); 56 | 57 | protected abstract byte[] createContentDisposition(); 58 | 59 | public abstract long getTotalLength() throws IOException; 60 | 61 | public abstract byte[] getTransferEncoding(); 62 | 63 | public abstract void writeTo(OutputStream out) throws IOException; 64 | 65 | public void writeToServer(OutputStream out) throws IOException { 66 | if (header == null) { 67 | throw new RuntimeException("Not call createHeader(),未调用createHeader方法"); 68 | } 69 | out.write(header); 70 | updateProgress(header.length); 71 | writeTo(out); 72 | } 73 | 74 | public MultipartBody getMultipartBody() { 75 | return multipartBody; 76 | } 77 | 78 | public void setMultipartBody(MultipartBody multipartBody) { 79 | this.multipartBody = multipartBody; 80 | } 81 | 82 | protected void updateProgress(int length) { 83 | if (multipartBody != null) { 84 | multipartBody.updateProgress(length); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/multi/BoundaryCreater.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content.multi; 2 | 3 | import com.litesuits.http.data.Consts; 4 | import com.litesuits.http.utils.StringCodingUtils; 5 | 6 | import java.nio.charset.Charset; 7 | import java.util.Random; 8 | 9 | /** 10 | * @author MaTianyu 11 | * @date 2014-08-06 12 | */ 13 | public class BoundaryCreater { 14 | public static final Charset charset = Charset.forName(Consts.DEFAULT_CHARSET); 15 | private final static char[] MULTIPART_CHARS = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); 16 | private String boundary; 17 | private byte[] boundaryLine; 18 | private byte[] boundaryEnd; 19 | 20 | public BoundaryCreater() { 21 | final StringBuilder buf = new StringBuilder(); 22 | final Random rand = new Random(); 23 | for (int i = 0; i < 30; i++) { 24 | buf.append(MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]); 25 | } 26 | boundary = buf.toString(); 27 | boundaryLine = StringCodingUtils.getBytes("--" + boundary + "\r\n", charset); 28 | boundaryEnd = StringCodingUtils.getBytes("--" + boundary + "--\r\n", charset); 29 | } 30 | 31 | public String getBoundary() { 32 | return boundary; 33 | } 34 | 35 | public byte[] getBoundaryLine() { 36 | return boundaryLine; 37 | } 38 | 39 | public byte[] getBoundaryEnd() { 40 | return boundaryEnd; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/multi/BytesPart.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content.multi; 2 | 3 | import com.litesuits.http.log.HttpLog; 4 | import com.litesuits.http.data.Consts; 5 | import com.litesuits.http.utils.StringCodingUtils; 6 | 7 | import java.io.IOException; 8 | import java.io.OutputStream; 9 | 10 | /** 11 | * 上传字节 12 | * 13 | * @author MaTianyu 14 | * @date 14-7-29 15 | */ 16 | public class BytesPart extends AbstractPart { 17 | public byte[] bytes; 18 | public static final String TAG = BytesPart.class.getSimpleName(); 19 | //protected String type = Consts.MIME_TYPE_OCTET_STREAM; 20 | 21 | public BytesPart(String key, byte[] bytes) { 22 | this(key, bytes, null); 23 | this.bytes = bytes; 24 | } 25 | 26 | public BytesPart(String key, byte[] bytes, String mimeType) { 27 | super(key, mimeType); 28 | this.bytes = bytes; 29 | } 30 | 31 | @Override 32 | protected byte[] createContentType() { 33 | return StringCodingUtils.getBytes(Consts.CONTENT_TYPE + ": " + mimeType + "\r\n", infoCharset); 34 | } 35 | 36 | @Override 37 | protected byte[] createContentDisposition() { 38 | return StringCodingUtils.getBytes("Content-Disposition: form-data; name=\"" + key + "\"\r\n", infoCharset); 39 | } 40 | 41 | public long getTotalLength() { 42 | if (HttpLog.isPrint) if (HttpLog.isPrint) HttpLog.v(TAG, TAG + "内容长度 header : " + header.length + " ,body: " 43 | + bytes.length + " ," + "换行:" + CR_LF.length); 44 | return header.length + bytes.length + CR_LF.length; 45 | } 46 | 47 | @Override 48 | public byte[] getTransferEncoding() { 49 | return TRANSFER_ENCODING_BINARY; 50 | } 51 | 52 | @Override 53 | public void writeTo(OutputStream out) throws IOException { 54 | out.write(bytes); 55 | out.write(CR_LF); 56 | updateProgress(bytes.length + CR_LF.length); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/multi/FilePart.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content.multi; 2 | 3 | import com.litesuits.http.log.HttpLog; 4 | import com.litesuits.http.data.Consts; 5 | import com.litesuits.http.request.content.HttpBody; 6 | import com.litesuits.http.utils.StringCodingUtils; 7 | 8 | import java.io.*; 9 | 10 | /** 11 | * 上传文件 12 | * 13 | * @author MaTianyu 14 | * @date 14-7-29 15 | */ 16 | public class FilePart extends AbstractPart { 17 | public File file; 18 | public static final String TAG = FilePart.class.getSimpleName(); 19 | 20 | public FilePart(String key, File file) { 21 | this(key, file, Consts.MIME_TYPE_OCTET_STREAM); 22 | } 23 | 24 | public FilePart(String key, File file, String mimeType) { 25 | super(key, mimeType); 26 | this.file = file; 27 | } 28 | 29 | @Override 30 | protected byte[] createContentType() { 31 | return StringCodingUtils.getBytes(Consts.CONTENT_TYPE + ": " + mimeType + "\r\n", infoCharset); 32 | } 33 | 34 | @Override 35 | protected byte[] createContentDisposition() { 36 | String dis = "Content-Disposition: form-data; name=\"" + key; 37 | return StringCodingUtils.getBytes(dis + "\"; filename=\"" + file.getName() + "\"\r\n", infoCharset); 38 | } 39 | 40 | 41 | public long getTotalLength() { 42 | long len = file.length(); 43 | if (HttpLog.isPrint) { 44 | HttpLog.v(TAG, TAG + " 内容长度header : " + header.length 45 | + " ,body: " + len + " ," + "换行:" + CR_LF.length); 46 | } 47 | return header.length + len + CR_LF.length; 48 | } 49 | 50 | @Override 51 | public byte[] getTransferEncoding() { 52 | return TRANSFER_ENCODING_BINARY; 53 | } 54 | 55 | public void writeTo(OutputStream out) throws IOException { 56 | final InputStream instream = new FileInputStream(this.file); 57 | try { 58 | final byte[] tmp = new byte[HttpBody.OUTPUT_BUFFER_SIZE]; 59 | int l; 60 | while ((l = instream.read(tmp)) != -1) { 61 | out.write(tmp, 0, l); 62 | updateProgress(l); 63 | } 64 | out.write(CR_LF); 65 | updateProgress(CR_LF.length); 66 | out.flush(); 67 | } catch (IOException e) { 68 | e.printStackTrace(); 69 | } finally { 70 | instream.close(); 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/multi/InputStreamPart.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content.multi; 2 | 3 | import com.litesuits.http.log.HttpLog; 4 | import com.litesuits.http.data.Consts; 5 | import com.litesuits.http.request.content.HttpBody; 6 | import com.litesuits.http.utils.StringCodingUtils; 7 | 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.OutputStream; 11 | 12 | /** 13 | * 上传数据流 14 | * 15 | * @author MaTianyu 16 | * @date 14-7-29 17 | */ 18 | public class InputStreamPart extends AbstractPart { 19 | protected InputStream inputStream; 20 | 21 | protected static final String TAG = InputStreamPart.class.getSimpleName(); 22 | protected String fileName; 23 | 24 | public InputStreamPart(String key, InputStream inputStream) { 25 | this(key, inputStream, null, Consts.MIME_TYPE_OCTET_STREAM); 26 | } 27 | 28 | public InputStreamPart(String key, InputStream inputStream, String contentType) { 29 | this(key, inputStream, null, contentType); 30 | } 31 | 32 | public InputStreamPart(String key, InputStream inputStream, String fileName, String mimeType) { 33 | super(key, mimeType); 34 | if (inputStream == null) { 35 | throw new NullPointerException("InputStream not be null !"); 36 | } 37 | this.inputStream = inputStream; 38 | this.fileName = fileName; 39 | } 40 | 41 | @Override 42 | protected byte[] createContentType() { 43 | return StringCodingUtils.getBytes(Consts.CONTENT_TYPE + ": " + mimeType + "\r\n", infoCharset); 44 | } 45 | 46 | @Override 47 | protected byte[] createContentDisposition() { 48 | String dis = "Content-Disposition: form-data; name=\"" + key; 49 | return fileName == null ? StringCodingUtils.getBytes(dis + "\"\r\n", infoCharset) 50 | : StringCodingUtils.getBytes(dis + "\"; filename=\"" + fileName + "\"\r\n", infoCharset); 51 | } 52 | 53 | @Override 54 | public long getTotalLength() throws IOException { 55 | long len = inputStream.available(); 56 | if (HttpLog.isPrint) { 57 | HttpLog.v(TAG, TAG + "内容长度 header : " + header.length + " ,body: " + len + " ," + 58 | "换行:" + CR_LF.length); 59 | } 60 | return header.length + len + CR_LF.length; 61 | } 62 | 63 | @Override 64 | public byte[] getTransferEncoding() { 65 | return TRANSFER_ENCODING_BINARY; 66 | } 67 | 68 | public void writeTo(OutputStream out) throws IOException { 69 | try { 70 | final byte[] tmp = new byte[HttpBody.OUTPUT_BUFFER_SIZE]; 71 | int l; 72 | while ((l = inputStream.read(tmp)) != -1) { 73 | out.write(tmp, 0, l); 74 | updateProgress(l); 75 | } 76 | out.write(CR_LF); 77 | updateProgress(CR_LF.length); 78 | out.flush(); 79 | } catch (final IOException e) { 80 | e.printStackTrace(); 81 | } finally { 82 | if (inputStream != null) 83 | inputStream.close(); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/multi/MultipartBody.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content.multi; 2 | 3 | import com.litesuits.http.data.Consts; 4 | import com.litesuits.http.request.content.HttpBody; 5 | 6 | import java.io.*; 7 | import java.util.LinkedList; 8 | 9 | /** 10 | * @author MaTianyu 11 | * @date 14-7-29 12 | */ 13 | public class MultipartBody extends HttpBody { 14 | private LinkedList httpParts = new LinkedList(); 15 | private long totalSize; 16 | private long bytesWritten; 17 | BoundaryCreater boundaryCreater; 18 | 19 | public MultipartBody() { 20 | boundaryCreater = new BoundaryCreater(); 21 | contentType = Consts.MIME_TYPE_FORM_DATA + Consts.BOUNDARY_PARAM + boundaryCreater.getBoundary(); 22 | } 23 | 24 | public LinkedList getHttpParts() { 25 | return httpParts; 26 | } 27 | 28 | public MultipartBody setHttpParts(LinkedList httpParts) { 29 | this.httpParts = httpParts; 30 | return this; 31 | } 32 | 33 | public MultipartBody addPart(String key, String string, String charset, String mimeType) throws 34 | UnsupportedEncodingException { 35 | return addPart(new StringPart(key, string, charset, mimeType)); 36 | } 37 | 38 | public MultipartBody addPart(String key, byte[] bytes, String mimeType) { 39 | return addPart(new BytesPart(key, bytes, mimeType)); 40 | } 41 | 42 | public MultipartBody addPart(String key, File file, String mimeType) throws FileNotFoundException { 43 | return addPart(new FilePart(key, file, mimeType)); 44 | } 45 | 46 | public MultipartBody addPart(String key, InputStream inputStream, String fileName, String mimeType) { 47 | return addPart(new InputStreamPart(key, inputStream, fileName, mimeType)); 48 | } 49 | 50 | public MultipartBody addPart(AbstractPart part) { 51 | if (part == null) { 52 | return this; 53 | } 54 | // note that: set multibody to every part, so that we can get progress of these part. 55 | part.setMultipartBody(this); 56 | part.createHeader(boundaryCreater.getBoundaryLine()); 57 | httpParts.add(part); 58 | return this; 59 | } 60 | 61 | public long getContentLength() { 62 | long contentLen = -1; 63 | try { 64 | for (AbstractPart part : httpParts) { 65 | long len = 0; 66 | len = part.getTotalLength(); 67 | if (len < 0) { 68 | return -1; 69 | } 70 | contentLen += len; 71 | } 72 | contentLen += boundaryCreater.getBoundaryEnd().length; 73 | } catch (IOException e) { 74 | e.printStackTrace(); 75 | } 76 | return contentLen; 77 | } 78 | 79 | public void writeTo(final OutputStream outstream) throws IOException { 80 | bytesWritten = 0; 81 | totalSize = (int) getContentLength(); 82 | for (AbstractPart part : httpParts) { 83 | part.writeToServer(outstream); 84 | } 85 | outstream.write(boundaryCreater.getBoundaryEnd()); 86 | updateProgress(boundaryCreater.getBoundaryEnd().length); 87 | } 88 | 89 | @SuppressWarnings("unchecked") 90 | protected void updateProgress(long count) { 91 | bytesWritten += count; 92 | if (httpListener != null) { 93 | httpListener.notifyCallUploading(request, totalSize, bytesWritten); 94 | } 95 | } 96 | 97 | public BoundaryCreater getBoundary() { 98 | return boundaryCreater; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/content/multi/StringPart.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.content.multi; 2 | 3 | import com.litesuits.http.data.Consts; 4 | import com.litesuits.http.utils.StringCodingUtils; 5 | 6 | import java.io.UnsupportedEncodingException; 7 | 8 | /** 9 | * @author MaTianyu 10 | * @date 14-7-29 11 | */ 12 | public class StringPart extends BytesPart { 13 | protected String charset; 14 | protected String mimeType; 15 | 16 | public StringPart(String key, String string) { 17 | this(key, string, Consts.DEFAULT_CHARSET, Consts.MIME_TYPE_TEXT); 18 | } 19 | 20 | public StringPart(String key, String string, String charset, String mimeType) { 21 | super(key, getBytes(string, charset),mimeType); 22 | this.mimeType = mimeType != null ? mimeType : Consts.MIME_TYPE_TEXT; 23 | this.charset = charset; 24 | } 25 | 26 | public static byte[] getBytes(String string, String charset) { 27 | try { 28 | return string.getBytes(charset); 29 | } catch (UnsupportedEncodingException e) { 30 | e.printStackTrace(); 31 | } 32 | return null; 33 | } 34 | 35 | @Override 36 | protected byte[] createContentType() { 37 | return StringCodingUtils.getBytes(Consts.CONTENT_TYPE + ": " + mimeType + " " + Consts.CHARSET_PARAM + charset + 38 | "\r\n", infoCharset); 39 | } 40 | 41 | @Override 42 | public byte[] getTransferEncoding() { 43 | return TRANSFER_ENCODING_8BIT; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/param/CacheMode.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.param; 2 | 3 | /** 4 | * @author MaTianyu 5 | * @date 2015-04-22 6 | */ 7 | public enum CacheMode { 8 | NetOnly, 9 | NetFirst, 10 | CacheFirst, 11 | CacheOnly 12 | } 13 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/param/HttpCustomParam.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.param; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * help to build custom parameters for {@link com.litesuits.http.request.AbstractRequest} 10 | * 11 | * @author MaTianyu 12 | * 2014-1-1上午2:45:11 13 | */ 14 | public interface HttpCustomParam { 15 | 16 | @Target(ElementType.METHOD) 17 | @Retention(RetentionPolicy.RUNTIME) 18 | public @interface CustomValueBuilder {} 19 | 20 | @CustomValueBuilder 21 | public CharSequence buildValue(); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/param/HttpMethods.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.param; 2 | 3 | /** 4 | * support method 5 | * 6 | * @author MaTianyu 7 | * 2014-1-1下午9:51:59 8 | */ 9 | public enum HttpMethods { 10 | /* ******************* Http Get(Query) Request *************/ 11 | /** 12 | * get 13 | */ 14 | Get("GET"), 15 | /** 16 | * get http header only 17 | */ 18 | Head("HEAD"), 19 | /** 20 | * debug 21 | */ 22 | Trace("TRACE"), 23 | /** 24 | * query 25 | */ 26 | Options("OPTIONS"), 27 | /** 28 | * delete 29 | */ 30 | Delete("DELETE"), 31 | /* ******************* Http Upate(Entity Enclosing) Request *************/ 32 | /** 33 | * update 34 | */ 35 | Put("PUT"), 36 | /** 37 | * add 38 | */ 39 | Post("POST"), 40 | /** 41 | * incremental update 42 | */ 43 | Patch("PATCH"); 44 | 45 | private String methodName; 46 | 47 | HttpMethods(String methodName) { 48 | this.methodName = methodName; 49 | } 50 | 51 | public String getMethodName() { 52 | return methodName; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/param/HttpParam.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.param; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author MaTianyu @http://litesuits.com 10 | * @date 2015-11-13 11 | */ 12 | @Target(ElementType.FIELD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface HttpParam { 15 | String value(); 16 | } 17 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/param/HttpParamModel.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.param; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * mark a class as a http parameter modle. 7 | * classes that implement this will be parsed to http parameter. 8 | * 9 | * @author MaTianyu 10 | * 2014-1-19上午2:39:31 11 | */ 12 | public interface HttpParamModel extends Serializable{} 13 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/param/HttpReplace.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.param; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author MaTianyu @http://litesuits.com 10 | * @date 2015-11-18 11 | */ 12 | @Target(ElementType.FIELD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface HttpReplace { 15 | String value(); 16 | } -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/param/HttpRichParamModel.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.param; 2 | 3 | import com.litesuits.http.listener.HttpListener; 4 | import com.litesuits.http.request.JsonRequest; 5 | import com.litesuits.http.request.content.HttpBody; 6 | import com.litesuits.http.request.content.StringBody; 7 | import com.litesuits.http.request.content.UrlEncodedFormBody; 8 | import com.litesuits.http.request.content.multi.MultipartBody; 9 | import com.litesuits.http.request.query.ModelQueryBuilder; 10 | 11 | import java.lang.reflect.ParameterizedType; 12 | import java.lang.reflect.Type; 13 | import java.util.LinkedHashMap; 14 | 15 | /** 16 | * mark a class as a http parameter modle. 17 | * classes that implement this will be parsed to http parameter. 18 | * 杂袍1只, 墨兰1对, 大红1对, 红鼻10条,金光10条,玻璃扯旗10条,三角10条,红绿灯10条。 19 | * 20 | * @author MaTianyu 21 | * 2014-1-19上午2:39:31 22 | */ 23 | public abstract class HttpRichParamModel implements HttpParamModel { 24 | private HttpListener httpListener; 25 | 26 | public final LinkedHashMap getHeaders() { 27 | return createHeaders(); 28 | } 29 | 30 | public ModelQueryBuilder getModelQueryBuilder() { 31 | return createQueryBuilder(); 32 | } 33 | 34 | public final HttpBody getHttpBody() { 35 | return createHttpBody(); 36 | } 37 | 38 | public final HttpListener getHttpListener() { 39 | if (httpListener == null) { 40 | httpListener = createHttpListener(); 41 | } 42 | return httpListener; 43 | } 44 | 45 | public boolean isFieldsAttachToUrl() { 46 | return true; 47 | } 48 | 49 | /** 50 | * craete headers for request. 51 | */ 52 | protected LinkedHashMap createHeaders() {return null;} 53 | 54 | /** 55 | * craete uri query builder for request. 56 | */ 57 | protected ModelQueryBuilder createQueryBuilder() { 58 | return null; 59 | } 60 | 61 | /** 62 | * create http body for POST/PUT... request. 63 | * 64 | * @return such as {@link StringBody}, {@link UrlEncodedFormBody}, {@link MultipartBody}... 65 | */ 66 | protected HttpBody createHttpBody() {return null;} 67 | 68 | /** 69 | * create http listener for request. 70 | */ 71 | protected HttpListener createHttpListener() {return null;} 72 | 73 | /** 74 | * build request and set http listener. 75 | */ 76 | @SuppressWarnings("unchecked") 77 | public final > M setHttpListener(HttpListener httpListener) { 78 | this.httpListener = httpListener; 79 | return (M) this; 80 | } 81 | 82 | /** 83 | * build as a request. 84 | */ 85 | public JsonRequest buildRequest() { 86 | Type type = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 87 | return new JsonRequest(this, type); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/param/NonHttpParam.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.param; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * marked for java field that exclude from http parameter. 10 | * 11 | * @author MaTianyu 12 | * 2014-1-19下午11:57:47 13 | */ 14 | @Target(ElementType.FIELD) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface NonHttpParam {} 17 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/request/query/JsonQueryBuilder.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.request.query; 2 | 3 | import com.litesuits.http.data.Json; 4 | 5 | /** 6 | * when uri query parameter's value is complicated, build value into json. 7 | * in this case, value will intelligently translate to json string. 8 | *

9 | * such as: 10 | * http://def.so? key1 = value.toJsonString() & key2 = value.toJsonString() 11 | * 12 | * @author MaTianyu 13 | * 2014-1-4下午5:06:37 14 | */ 15 | public class JsonQueryBuilder extends ModelQueryBuilder { 16 | 17 | @Override 18 | protected CharSequence buildSencondaryValue(Object model) { 19 | try { 20 | return Json.get().toJson(model); 21 | } catch (Exception e) { 22 | e.printStackTrace(); 23 | } 24 | return null; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/response/Response.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.response; 2 | 3 | import com.litesuits.http.data.HttpStatus; 4 | import com.litesuits.http.data.NameValuePair; 5 | import com.litesuits.http.exception.HttpException; 6 | import com.litesuits.http.request.AbstractRequest; 7 | 8 | import java.util.ArrayList; 9 | 10 | /** 11 | * User Facade 12 | * providing developers with easy access to the results of 13 | * {@link com.litesuits.http.LiteHttp#execute(AbstractRequest)}, 14 | * and with information of status,request,charset,etc. 15 | * 16 | * @author MaTianyu 17 | * 2014-1-1下午10:00:42 18 | */ 19 | public interface Response { 20 | 21 | 22 | ArrayList getHeaders(); 23 | 24 | HttpStatus getHttpStatus(); 25 | 26 | T getResult(); 27 | 28 | > R getRequest(); 29 | 30 | long getReadedLength(); 31 | 32 | long getContentLength(); 33 | 34 | 35 | String getContentEncoding(); 36 | 37 | String getContentType(); 38 | 39 | String getCharSet(); 40 | 41 | long getUseTime(); 42 | 43 | boolean isConnectSuccess(); 44 | 45 | int getRetryTimes(); 46 | 47 | int getRedirectTimes(); 48 | 49 | HttpException getException(); 50 | 51 | boolean isCacheHit(); 52 | 53 | String getRawString(); 54 | 55 | Response setTag(Object tag); 56 | 57 | Object getTag(); 58 | 59 | String resToString(); 60 | 61 | void printInfo(); 62 | 63 | } 64 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/utils/MD5Util.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.utils; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.security.MessageDigest; 6 | import java.security.NoSuchAlgorithmException; 7 | 8 | /** 9 | * MS5 10 | */ 11 | public class MD5Util { 12 | private static final String TAG = MD5Util.class.getSimpleName(); 13 | private static final int STREAM_BUFFER_LENGTH = 1024; 14 | 15 | public static MessageDigest getDigest(final String algorithm) throws NoSuchAlgorithmException { 16 | return MessageDigest.getInstance(algorithm); 17 | } 18 | 19 | public static byte[] md5(String txt) { 20 | return md5(txt.getBytes()); 21 | } 22 | 23 | public static byte[] md5(byte[] bytes) { 24 | try { 25 | MessageDigest digest = getDigest("MD5"); 26 | digest.update(bytes); 27 | return digest.digest(); 28 | } catch (NoSuchAlgorithmException e) { 29 | e.printStackTrace(); 30 | } 31 | return null; 32 | } 33 | 34 | public static byte[] md5(InputStream is) throws NoSuchAlgorithmException, IOException { 35 | return updateDigest(getDigest("MD5"), is).digest(); 36 | } 37 | 38 | public static MessageDigest updateDigest(final MessageDigest digest, final InputStream data) throws IOException { 39 | final byte[] buffer = new byte[STREAM_BUFFER_LENGTH]; 40 | int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH); 41 | 42 | while (read > -1) { 43 | digest.update(buffer, 0, read); 44 | read = data.read(buffer, 0, STREAM_BUFFER_LENGTH); 45 | } 46 | 47 | return digest; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/utils/StringCodingUtils.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.utils; 2 | 3 | import android.os.Build; 4 | 5 | import java.io.UnsupportedEncodingException; 6 | import java.nio.charset.Charset; 7 | 8 | /** 9 | * @author MaTianyu 10 | * @date 2014-12-05 11 | */ 12 | public class StringCodingUtils { 13 | 14 | public static byte[] getBytes(String src, Charset charSet) { 15 | // Build.VERSION_CODES.GINGERBREAD = 9 16 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) { 17 | try { 18 | return src.getBytes(charSet.name()); 19 | } catch (UnsupportedEncodingException e) { 20 | e.printStackTrace(); 21 | } 22 | return null; 23 | } else { 24 | return src.getBytes(charSet); 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /litehttp/src/main/java/com/litesuits/http/utils/UriUtil.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http.utils; 2 | 3 | import android.net.Uri; 4 | 5 | import java.util.*; 6 | 7 | /** 8 | * @author matianyu 9 | * @date 2015-04-24 10 | */ 11 | public class UriUtil { 12 | /** 13 | * Returns a set of the unique names of all query parameters. Iterating 14 | * over the set will return the names in order of their first occurrence. 15 | * 16 | * @return a set of decoded names 17 | * @throws UnsupportedOperationException if this isn't a hierarchical URI 18 | */ 19 | public static Set getQueryParameterNames(Uri uri) { 20 | if (uri.isOpaque()) { 21 | return Collections.emptySet(); 22 | } 23 | 24 | String query = uri.getEncodedQuery(); 25 | if (query == null) { 26 | return Collections.emptySet(); 27 | } 28 | 29 | Set names = new LinkedHashSet(); 30 | int start = 0; 31 | do { 32 | int next = query.indexOf('&', start); 33 | int end = (next == -1) ? query.length() : next; 34 | 35 | int separator = query.indexOf('=', start); 36 | if (separator > end || separator == -1) { 37 | separator = end; 38 | } 39 | 40 | String name = query.substring(start, separator); 41 | names.add(name); 42 | // Move start to end of name. 43 | start = end + 1; 44 | } while (start < query.length()); 45 | 46 | return Collections.unmodifiableSet(names); 47 | } 48 | 49 | /** 50 | * Searches the query string for parameter values with the given key. 51 | * 52 | * @param key which will be encoded 53 | * @return a list of decoded values 54 | * @throws UnsupportedOperationException if this isn't a hierarchical URI 55 | * @throws NullPointerException if key is null 56 | */ 57 | public static List getQueryParameters(Uri uri, String key) { 58 | if (uri.isOpaque()) { 59 | return Collections.emptyList(); 60 | } 61 | if (key == null) { 62 | throw new NullPointerException("key"); 63 | } 64 | 65 | String query = uri.getEncodedQuery(); 66 | if (query == null) { 67 | return Collections.emptyList(); 68 | } 69 | 70 | ArrayList values = new ArrayList(); 71 | 72 | int start = 0; 73 | do { 74 | int nextAmpersand = query.indexOf('&', start); 75 | int end = nextAmpersand != -1 ? nextAmpersand : query.length(); 76 | 77 | int separator = query.indexOf('=', start); 78 | if (separator > end || separator == -1) { 79 | separator = end; 80 | } 81 | 82 | if (separator - start == key.length() 83 | && query.regionMatches(start, key, 0, key.length())) { 84 | if (separator == end) { 85 | values.add(""); 86 | } else { 87 | values.add(query.substring(separator + 1, end)); 88 | } 89 | } 90 | 91 | // Move start to end of name. 92 | if (nextAmpersand != -1) { 93 | start = nextAmpersand + 1; 94 | } else { 95 | break; 96 | } 97 | } while (true); 98 | 99 | return Collections.unmodifiableList(values); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /litehttp/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | litehttp3 3 | 4 | -------------------------------------------------------------------------------- /litehttp/src/test/java/com/litesuits/http/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.litesuits.http; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':litehttp-sample', ':litehttp', ':apache-client' 2 | -------------------------------------------------------------------------------- /web-server-sample/lib/javax.annotation.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/lib/javax.annotation.jar -------------------------------------------------------------------------------- /web-server-sample/lib/javax.ejb.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/lib/javax.ejb.jar -------------------------------------------------------------------------------- /web-server-sample/lib/javax.jms.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/lib/javax.jms.jar -------------------------------------------------------------------------------- /web-server-sample/lib/javax.persistence.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/lib/javax.persistence.jar -------------------------------------------------------------------------------- /web-server-sample/lib/javax.resource.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/lib/javax.resource.jar -------------------------------------------------------------------------------- /web-server-sample/lib/javax.servlet.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/lib/javax.servlet.jar -------------------------------------------------------------------------------- /web-server-sample/lib/javax.servlet.jsp.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/lib/javax.servlet.jsp.jar -------------------------------------------------------------------------------- /web-server-sample/lib/javax.servlet.jsp.jstl.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/lib/javax.servlet.jsp.jstl.jar -------------------------------------------------------------------------------- /web-server-sample/lib/javax.transaction.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/lib/javax.transaction.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/lib/commons-codec-1.9.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/web/WEB-INF/lib/commons-codec-1.9.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/lib/commons-fileupload-1.3.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/web/WEB-INF/lib/commons-fileupload-1.3.1.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/lib/commons-io-2.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/web/WEB-INF/lib/commons-io-2.4.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/lib/commons-logging-1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/web/WEB-INF/lib/commons-logging-1.2.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/lib/fluent-hc-4.4.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/web/WEB-INF/lib/fluent-hc-4.4.1.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/lib/httpclient-4.4.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/web/WEB-INF/lib/httpclient-4.4.1.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/lib/httpclient-cache-4.4.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/web/WEB-INF/lib/httpclient-cache-4.4.1.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/lib/httpclient-win-4.4.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/web/WEB-INF/lib/httpclient-win-4.4.1.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/lib/httpcore-4.4.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/web/WEB-INF/lib/httpcore-4.4.1.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/lib/httpmime-4.4.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/web/WEB-INF/lib/httpmime-4.4.1.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/lib/jna-4.1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/web/WEB-INF/lib/jna-4.1.0.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/lib/jna-platform-4.1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litesuits/android-lite-http/20e469814edb818cfab5e9b61aaeb034cc517fac/web-server-sample/web/WEB-INF/lib/jna-platform-4.1.0.jar -------------------------------------------------------------------------------- /web-server-sample/web/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /web-server-sample/web/index.jsp: -------------------------------------------------------------------------------- 1 | <%-- 2 | Created by IntelliJ IDEA. 3 | User: MaTianyu 4 | Date: 15/5/3 5 | Time: 下午8:23 6 | To change this template use File | Settings | File Templates. 7 | --%> 8 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> 9 | 10 | 11 | hello world 12 | 13 | 14 | hello world! 15 |

This is a server client sample for litehttp-v3

16 | 17 | 18 | --------------------------------------------------------------------------------