上篇通过一个get请求大致弄明白了HttpClient的请求过程,和请求中使用到关键的几个类,这次来说说其他种类的请求,以及超时,上传文件,cookie的用法和实现。
Post请求
首先看创建请求的一段代码:
return request.isGet() || request.isDelete() ? new GetSender(request)
: new PostSender(request);
从上面可以看出这个HttpClient工具中,针对get和delete请求都统一使用GetSender来处理,针对其他请求使用PostSendr来处理。
之前提到过: Sender类方法的主要功能是根据传入的参数构造Request请求,并且打开连接(OpenConnection),底层是调用Url的openConnection;最终返回数据Response
那么基本上GetSender就是这些功能,PostSender也一样,只不过,PostSender针对参数为输入流的情况做了判断处理:
if (null != ins) {
OutputStream ops = Streams.buff(conn.getOutputStream());
Streams.write(ops, ins);
Streams.safeClose(ins);
Streams.safeFlush(ops);
Streams.safeClose(ops);
}
超时处理
- 超时处理,在Sender类中体现,因为这个类负责openConnection嘛。
- 超时处理有两种类型,连接超时(默认30秒)和读取数据超时(默认10分钟)
- 实现中分别调用HttpUrlConnection的setConnectTimeout和setReadTimeout来设置超时时间。
上传文件
- 针对文件上传类的请求,提供了FilePostSender类,该类集成自PostSender类。
- 该类主要针对参数中的文件调用HttpURLConnection.getOutputStream()输出流,将文件输出到服务器端。
伪代码如下:
File f = getFileFromParams; final DataOutputStream outs = new DataOutputStream(conn.getOutputStream()); outs.write(f);
Cookie
Cookie的使用方法很简单,构造一个Cookie,然后Sender发送请求的时候将cookie作为参数发送即可:
Cookie cookie = new Cookie(); cookie.setDebug(true); Request req = Request.get("https://nutz.cn/user/login"); Response resp = Sender.create(req).setInterceptor(cookie).send();
Cookie的实现主要有两块:
一个是,在建立连接后将cookie发送到服务器端,
afterConnect{ String c = toString();//cokie内部实现使用map来存值,所以toString就是将这个键值对转换为字符串形式。 conn.addReque=stProperty("Cookie", c); }
一个是,在获取服务器响应的时候,将响应中的cookie信息保存下来。
afterResponse{ Map<String, List<String>> props = conn.getHeaderFields(); for (Entry<String, List<String>> en : props.entrySet()) { if (en.getKey() == null || !en.getKey().equalsIgnoreCase("Set-Cookie")) { continue; } for (String e : en.getValue()) { if (debug) log.debugf("found Set-Cookie [%s]", e); this.parse(e);//解析并保存cookie信息 } break; } }
- 上面代码中判断响应头信息是是否是cookie这里很有趣。按照我的理解,判断是否cookie的思路首先应该是:如果头信息中包含Set-Cookie的话,则解析这个cookie,但是作者确反过来判断了。
我的想法是这样:
if(en.getKey()!=null&&en.getKey().equalsIgnoreCase("Set-Cookie")) //解析cookie