實現(xiàn)連接網(wǎng)絡(luò)并獲取數(shù)據(jù)
1. 定義一個HttpStack接口
/**
* Created by lq on 2017/5/14.
* 該接口定義了實現(xiàn)請求的具體方法
*/
public interface HttpStack {
//真正實現(xiàn)網(wǎng)絡(luò)請求焚鹊,并返回數(shù)據(jù)的方法
public Response performRequest(Request<?> request);
}
2. 使用HttpClientStack方式實現(xiàn)請求
/**
* Created by lq on 2017/5/14.
* api 9以下使用HttpClient執(zhí)行網(wǎng)絡(luò)請求
*/
public class HttpClientStack implements HttpStack {
//使用HttpClient執(zhí)行網(wǎng)絡(luò)請求的https配置
HttpClientConfig mConfig = HttpClientConfig.getConfig();
HttpClient mHttpClient = AndroidHttpClient.newInstance(mConfig.userAgent);
@Override
public Response performRequest(Request<?> request) {
try {
HttpUriRequest httpUriRequest = createHttpRequest(request);
//添加連接參數(shù)
setConnectionParams(httpUriRequest);
//添加Header
addHeaders(httpUriRequest,request.getHeaders());
//https配置
configHttps(request);
//執(zhí)行網(wǎng)絡(luò)請求码荔,并返回結(jié)果
HttpResponse response = mHttpClient.execute(httpUriRequest);
//構(gòu)建Response
Response rawResponse = new Response(response.getStatusLine());
//設(shè)置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);
}
}
//設(shè)置連接參數(shù)
private void setConnectionParams(HttpUriRequest httpUriRequest){
HttpParams httpParams = httpUriRequest.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams,mConfig.ConnTimeOut);
HttpConnectionParams.setSoTimeout(httpParams,mConfig.soTimeOut);
}
//根據(jù)類型創(chuàng)建不同的請求類型
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));
}
}
//將請求參數(shù)設(shè)置到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方式實現(xiàn)請求
/**
* Created by lq on 2017/5/14.
* 使用HttpURLConnection執(zhí)行網(wǎng)絡(luò)請求的HttpStack
*/
public class HttpUrlConnStack implements HttpStack {
//配置https
HttpUrlConnConfig mConfig = HttpUrlConnConfig.getConfig();
@Override
public Response performRequest(Request<?> request) {
HttpURLConnection connection = null;
try {
//構(gòu)建HttpURLConnection
connection = createUrlConnection(request.getUrl());
//設(shè)置headers
setRequestHeaders(connection,request);
//設(shè)置Body參數(shù)
setRequestParams(connection,request);
//https配置
configHttps(request);
//獲取結(jié)果
return fetchResponse(connection);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null){
connection.disconnect();
}
}
return null;
}
//構(gòu)建連接
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));
}
}
//將數(shù)據(jù)寫入請求中,針對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();
}
}
//解析響應(yīng),并構(gòu)建自定義響應(yīng)
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");
}
//狀態(tài)行數(shù)據(jù)
StatusLine responseStatus = new BasicStatusLine(protocolVersion, connection.getResponseCode(),
connection.getResponseMessage());
//構(gòu)建response
Response response = new Response(responseStatus);
//設(shè)置response數(shù)據(jù)
response.setEntity(entityFromURLConnection(connection));
addHeadersToResponse(response,connection);
return response;
}
//執(zhí)行HTTP請求后獲取到其數(shù)據(jù)流疯特,即返回請求結(jié)果的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;
}
//將連接的請求頭添加到響應(yīng)中
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. 根據(jù)SDK選擇不同的請求方式
/**
* Created by lq on 2017/5/14.
* 根據(jù)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();
}
}