第六章
6.流利的API
6.1.易于使用的API门面
至于4.2版本的HttpClient是一个易于使用的门面API的基础上的概念能说一口流利的接口。流利的的门面API仅公开HttpClient的和最根本的功能是用于简单的用例HttpClient的,不需要充分的灵活性。例如,流畅的门面API处理连接管理和资源释放,减轻了用户。
这里有几个例子执行通过HC流利的API的HTTP请求
// Execute a GET with timeout settings and return response content as String. Request.Get("http://somehost/") .connectTimeout(1000) .socketTimeout(1000) .execute().returnContent().asString();
// Execute a POST with the 'expect-continue' handshake, using HTTP/1.1, // containing a request body as String and return response content as byte array. Request.Post("http://somehost/do-stuff") .useExpectContinue() .version(HttpVersion.HTTP_1_1) .bodyString("Important stuff", ContentType.DEFAULT_TEXT) .execute().returnContent().asBytes();
// Execute a POST with a custom header through the proxy containing a request body // as an HTML form and save the result to the file Request.Post("http://somehost/some-form") .addHeader("X-Custom-header", "stuff") .viaProxy(new HttpHost("myproxy", 8080)) .bodyForm(Form.form().add("username", "vip").add("password", "secret").build()) .execute().saveContent(new File("result.dump"));
也可以直接使用执行人以特定的安全上下文中执行请求认证的详细信息,缓存和重新用于后续的请求
Executor executor = Executor.newInstance() .auth(new HttpHost("somehost"), "username", "password") .auth(new HttpHost("myproxy", 8080), "username", "password") .authPreemptive(new HttpHost("myproxy", 8080)); executor.execute(Request.Get("http://somehost/")) .returnContent().asString(); executor.execute(Request.Post("http://somehost/do-stuff") .useExpectContinue() .bodyString("Important stuff", ContentType.DEFAULT_TEXT)) .returnContent().asString();
6.1.1.响应处理
一般流畅的门面API处理连接管理和资源释放,减轻了用户。不过,在大多数情况下,这是在价格缓冲区的内容在内存中的响应消息。我们强烈建议使用ResponseHandler的HTTP响应处理,以避免在内存缓冲区的内容。
Document result = Request.Get("http://somehost/content") .execute().handleResponse(new ResponseHandler<Document>() { public Document handleResponse(final HttpResponse response) throws IOException { StatusLine statusLine = response.getStatusLine(); HttpEntity entity = response.getEntity(); if (statusLine.getStatusCode() >= 300) { throw new HttpResponseException( statusLine.getStatusCode(), statusLine.getReasonPhrase()); } if (entity == null) { throw new ClientProtocolException("Response contains no content"); } DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance(); try { DocumentBuilder docBuilder = dbfac.newDocumentBuilder(); ContentType contentType = ContentType.getOrDefault(entity); if (!contentType.equals(ContentType.APPLICATION_XML)) { throw new ClientProtocolException("Unexpected content type:" + contentType); } String charset = contentType.getCharset(); if (charset == null) { charset = HTTP.DEFAULT_CONTENT_CHARSET; } return docBuilder.parse(entity.getContent(), charset); } catch (ParserConfigurationException ex) { throw new IllegalStateException(ex); } catch (SAXException ex) { throw new ClientProtocolException("Malformed XML document", ex); } } });
6.1.2.异步执行
可以用流利的门面API使用后台线程异步执行多个请求。
ExecutorService threadpool = Executors.newFixedThreadPool(2); Async async = Async.newInstance().use(threadpool); Request[] requests = new Request[] { Request.Get("http://www.google.com/"), Request.Get("http://www.yahoo.com/"), Request.Get("http://www.apache.com/"), Request.Get("http://www.apple.com/") }; Queue<Future<Content>> queue = new LinkedList<Future<Content>>(); for (final Request request: requests) { Future<Content> future = async.execute(request, new FutureCallback<Content>() { public void failed(final Exception ex) { System.out.println(ex.getMessage() + ": " + request); } public void completed(final Content content) { System.out.println("Request completed: " + request); } public void cancelled() { } }); queue.add(future); } // Process the queue