实现一个简单的网络框架之连接篇
2017-05-16 本文已影响14人
大海孤了岛
实现连接网络并获取数据
1. 定义一个HttpStack接口
/**
* Created by lq on 2017/5/14.
* 该接口定义了实现请求的具体方法
*/
public interface HttpStack {
//真正实现网络请求,并返回数据的方法
public Response performRequest(Request<?> request);
}
2. 使用HttpClientStack方式实现请求
/**
* Created by lq on 2017/5/14.
* api 9以下使用HttpClient执行网络请求
*/
public class HttpClientStack implements HttpStack {
//使用HttpClient执行网络请求的https配置
HttpClientConfig mConfig = HttpClientConfig.getConfig();
HttpClient mHttpClient = AndroidHttpClient.newInstance(mConfig.userAgent);
@Override
public Response performRequest(Request<?> request) {
try {
HttpUriRequest httpUriRequest = createHttpRequest(request);
//添加连接参数
setConnectionParams(httpUriRequest);
//添加Header
addHeaders(httpUriRequest,request.getHeaders());
//https配置
configHttps(request);
//执行网络请求,并返回结果
HttpResponse response = mHttpClient.execute(httpUriRequest);
//构建Response
Response rawResponse = new Response(response.getStatusLine());
//设置Entity
rawResponse.setEntity(response.getEntity());
return rawResponse;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//如果是https请求,则使用用户配置的SSLSocketFactory进行配置
private void configHttps(Request<?> request){
SSLSocketFactory sslSocketFactory = mConfig.getSslSocketFactory();
if (request.isHttps() && sslSocketFactory != null){
Scheme scheme = new Scheme("https", (SocketFactory) sslSocketFactory,443);
mHttpClient.getConnectionManager().getSchemeRegistry().register(scheme);
}
}
//设置连接参数
private void setConnectionParams(HttpUriRequest httpUriRequest){
HttpParams httpParams = httpUriRequest.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams,mConfig.ConnTimeOut);
HttpConnectionParams.setSoTimeout(httpParams,mConfig.soTimeOut);
}
//根据类型创建不同的请求类型
static HttpUriRequest createHttpRequest(Request<?> request){
HttpUriRequest httpUriRequest = null;
switch (request.getHttpMethod()){
case GET:
httpUriRequest = new HttpGet(request.getUrl());
break;
case DELETE:
httpUriRequest = new HttpDelete(request.getUrl());
break;
case POST:
httpUriRequest = new HttpPost(request.getUrl());
break;
case PUT:
httpUriRequest = new HttpPut(request.getUrl());
break;
default:
throw new IllegalStateException("Unknown request method.");
}
return httpUriRequest;
}
//添加请求头
private static void addHeaders(HttpUriRequest request, Map<String,String> headers){
for (String key : headers.keySet()){
request.setHeader(key,headers.get(key));
}
}
//将请求参数设置到HttpEntity中
private static void setEntityNonEmptyBody(HttpEntityEnclosingRequestBase httpRequest,
Request<?> request){
byte[] body = request.getBody();
if (body != null){
HttpEntity entity = new ByteArrayEntity(body);
httpRequest.setEntity(entity);
}
}
}
3. 使用HttpUrlConnStack方式实现请求
/**
* Created by lq on 2017/5/14.
* 使用HttpURLConnection执行网络请求的HttpStack
*/
public class HttpUrlConnStack implements HttpStack {
//配置https
HttpUrlConnConfig mConfig = HttpUrlConnConfig.getConfig();
@Override
public Response performRequest(Request<?> request) {
HttpURLConnection connection = null;
try {
//构建HttpURLConnection
connection = createUrlConnection(request.getUrl());
//设置headers
setRequestHeaders(connection,request);
//设置Body参数
setRequestParams(connection,request);
//https配置
configHttps(request);
//获取结果
return fetchResponse(connection);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null){
connection.disconnect();
}
}
return null;
}
//构建连接
private HttpURLConnection createUrlConnection(String url) throws IOException {
URL newUrl = new URL(url);
URLConnection urlConnection = newUrl.openConnection();
urlConnection.setConnectTimeout(mConfig.ConnTimeOut);
urlConnection.setReadTimeout(mConfig.soTimeOut);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
return (HttpURLConnection) urlConnection;
}
private void configHttps(Request<?> request){
if (request.isHttps()){
SSLSocketFactory sslFactory = mConfig.getSslSocketFactory();
if (sslFactory != null){
HttpsURLConnection.setDefaultSSLSocketFactory(sslFactory);
HttpsURLConnection.setDefaultHostnameVerifier(mConfig.getHostnameVerifier());
}
}
}
private void setRequestHeaders(HttpURLConnection connection, Request<?> request){
Set<String> headerKeys = request.getHeaders().keySet();
for (String headerName : headerKeys){
connection.addRequestProperty(headerName,request.getHeaders().get(headerName));
}
}
//将数据写入请求中,针对POST和PUT方式
protected void setRequestParams(HttpURLConnection connection, Request<?> request) throws IOException {
Request.HttpMethod method = request.getHttpMethod();
connection.setRequestMethod(method.toString());
byte[] body = request.getBody();
if (body != null){
connection.setDoOutput(true);
connection.addRequestProperty(Request.HEADER_CONTENT_TYPE,request.getBodyContentType());
DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
dataOutputStream.write(body);
dataOutputStream.close();
}
}
//解析响应,并构建自定义响应
private Response fetchResponse(HttpURLConnection connection) throws IOException {
ProtocolVersion protocolVersion = new ProtocolVersion("HTTP",1,1);
int responseCode = connection.getResponseCode();
if (responseCode == -1){
throw new IOException("Could not retries response code from HttpUrlConnection");
}
//状态行数据
StatusLine responseStatus = new BasicStatusLine(protocolVersion, connection.getResponseCode(),
connection.getResponseMessage());
//构建response
Response response = new Response(responseStatus);
//设置response数据
response.setEntity(entityFromURLConnection(connection));
addHeadersToResponse(response,connection);
return response;
}
//执行HTTP请求后获取到其数据流,即返回请求结果的entity对象
private HttpEntity entityFromURLConnection(HttpURLConnection connection){
BasicHttpEntity entity = new BasicHttpEntity();
InputStream is = null;
try {
is = connection.getInputStream();
} catch (IOException e) {
e.printStackTrace();
is = connection.getErrorStream();
}
entity.setContent(is);
entity.setContentLength(connection.getContentLength());
entity.setContentEncoding(connection.getContentEncoding());
entity.setContentType(connection.getContentType());
return entity;
}
//将连接的请求头添加到响应中
private void addHeadersToResponse(BasicHttpResponse response, HttpURLConnection connection){
for (Map.Entry<String,List<String>> header : connection.getHeaderFields().entrySet()){
if (header.getKey() != null){
Header h = new BasicHeader(header.getKey(),header.getValue().get(0));
response.addHeader(h);
}
}
}
}
4. 根据SDK选择不同的请求方式
/**
* Created by lq on 2017/5/14.
* 根据api版本选择HttpClient或者HttpURLConnection.
*/
public class HttpStackFactory {
private static final int GINGERBREAD_SDK_NUM = 9;
public static HttpStack createHttpStack(){
int runtimeSDKApi = Build.VERSION.SDK_INT;
if (runtimeSDKApi >= GINGERBREAD_SDK_NUM){
return new HttpUrlConnStack();
}
return new HttpClientStack();
}
}