---恢复内容开始---
还是继续FinalHttp,这个类涉及到的东西还是挺多的。
一:线程池
首先我们看到FinalHttp类里面有两个跟线程池相关的两个静态类
private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); public Thread newThread(Runnable r) { Thread tread = new Thread(r, "FinalHttp #" + mCount.getAndIncrement()); tread.setPriority(Thread.NORM_PRIORITY - 1); return tread; } }; private static final Executor executor =Executors.newFixedThreadPool(httpThreadCount, sThreadFactory);
ThreadFactory是一个工厂模式,下面是一个线程池Executor。线程池里new出来的线程都是这个ThreadFactory孵化出来的线程,赋予了原始信息线程名字都是FinalHttp #n,(这里还有一个AtomicInteger,这是一个原子操作类,主要用于在高并发环境下的高效程序处理。使用非阻塞算法来实现并发控制。)并且设置线程优先级。
看到这个类里面很多方法都有传递这个Executor线程池,没到执行一个线程我想都是executor 加入线程池去执行的,这样的线程管理是比较高效和出色的。
二:构造方法
这个构造方法有超多默认配置,蛋疼了米有?
public FinalHttp() { BasicHttpParams httpParams = new BasicHttpParams(); ConnManagerParams.setTimeout(httpParams, socketTimeout); ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(maxConnections)); ConnManagerParams.setMaxTotalConnections(httpParams, 10); HttpConnectionParams.setSoTimeout(httpParams, socketTimeout); HttpConnectionParams.setConnectionTimeout(httpParams, socketTimeout); HttpConnectionParams.setTcpNoDelay(httpParams, true); HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE); HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(httpParams, schemeRegistry); httpContext = new SyncBasicHttpContext(new BasicHttpContext()); httpClient = new DefaultHttpClient(cm, httpParams); httpClient.addRequestInterceptor(new HttpRequestInterceptor() { public void process(HttpRequest request, HttpContext context) { if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) { request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP); } for (String header : clientHeaderMap.keySet()) { request.addHeader(header, clientHeaderMap.get(header)); } } }); httpClient.addResponseInterceptor(new HttpResponseInterceptor() { public void process(HttpResponse response, HttpContext context) { final HttpEntity entity = response.getEntity(); if (entity == null) { return; } final Header encoding = entity.getContentEncoding(); if (encoding != null) { for (HeaderElement element : encoding.getElements()) { if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) { response.setEntity(new InflatingEntity(response.getEntity())); break; } } } } }); httpClient.setHttpRequestRetryHandler(new RetryHandler(maxRetries)); clientHeaderMap = new HashMap<String, String>(); }
httpParams是一个网络链接配置类,比如设置最大连接数,路由最大连接数,读取超时时间,连接超时时间,套接字缓冲大小。这里连接数都是10次,超市时间都是10秒,其实这样本来就是一种网络请求任务的拖慢。再下面还有个重复次数,竟然是5次,如果网络不好的话有可能要重试5次,这样严重影响了上层的UI交互。不过有个亮点就是g-zip,Gzip开启以后会将输出的数据进行压缩的处理,这样就会减小通过网络传输的数据量,提高读取的速度。
三:AfinalHttp里的方法
1.配置方法:
public void configCharset(String charSet){ if(charSet!=null && charSet.trim().length()!=0) this.charset = charSet; } public void configCookieStore(CookieStore cookieStore) { httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); } public void configUserAgent(String userAgent) { HttpProtocolParams.setUserAgent(this.httpClient.getParams(), userAgent); } /** * 设置网络连接超时时间,默认为10秒钟 * @param timeout */ public void configTimeout(int timeout){ final HttpParams httpParams = this.httpClient.getParams(); ConnManagerParams.setTimeout(httpParams, timeout); HttpConnectionParams.setSoTimeout(httpParams, timeout); HttpConnectionParams.setConnectionTimeout(httpParams, timeout); } /** * 设置https请求时 的 SSLSocketFactory * @param sslSocketFactory */ public void configSSLSocketFactory(SSLSocketFactory sslSocketFactory) { Scheme scheme = new Scheme("https", sslSocketFactory, 443); this.httpClient.getConnectionManager().getSchemeRegistry().register(scheme); } /** * 配置错误重试次数 * @param retry */ public void configRequestExecutionRetryCount(int count){ this.httpClient.setHttpRequestRetryHandler(new RetryHandler(count)); }
这些配置应该都在发起请求之前执行,不过设置超时这个方法太狗血了,竟然三种超时都是10s,那是不是意味着有可能3种超时加起来就要30s,半分钟啊!
2.请求方法入口,有常用的get()方法,post()方法,download()文件下载方法得各种重载。
那些重载方法这就不贴了,都是调用的HttpHandler类去处理的。
这里我们看到有几个东西:
AjaxParams,这是一个设置url参数的类。
笔者在实际使用过程中发现,有两个缺陷。
一个是里头用到的是ConcurrentHashMap,我们看一看java中几种常用集合的对比。
Map
HashMap 无序
HashTable:线程安全
LinkedHashMap 有序
ConcurrentHashMap 无序 线程安全
TreeMap:重新排序
ConcurrentHashMap 是线程安全的,但却是无序的。适用于高并发情景,但是无序在此就不太恰当。比如有个www.bvin.com/login.jsp?name=bvin&pw=888888,如果用这个Ajax去Put进去的话,有可能会出现像这样的情况:www.bvin.com/login.jsp?pw=888888&name=bvin,明显这样是错误的。
还有一点就是,这个类竟然没有clean()或者removeAll()方法。如果要再次用到这个类的话,就必须重新new一个。其实写这么个方法就举手投足的事,AjaxParams里面其实就是两个ConcurrentHashMap实例。只要把下面这两个清空就行了。
protected ConcurrentHashMap<String, String> urlParams;
protected ConcurrentHashMap<String, FileWrapper> fileParams;
AjaxCallBack,这是一个泛型抽象类,起回调作用。
public void onStart(){}; public void onLoading(long count,long current){}; public void onSuccess(T t){}; public void onFailure(Throwable t,String strMsg){};
3.发送请求方法
protected <T> void sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, AjaxCallBack<T> ajaxCallBack) { if(contentType != null) { uriRequest.addHeader("Content-Type", contentType); } new HttpHandler<T>(client, httpContext, ajaxCallBack,charset) .executeOnExecutor(executor, uriRequest); } protected Object sendSyncRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType) { if(contentType != null) { uriRequest.addHeader("Content-Type", contentType); } return new SyncRequestHandler(client, httpContext,charset).sendRequest(uriRequest); }
这里涉及到HttpHandler和SyncRequestHandler两各类,下回分解了。。。