一、基本的使用
HttpClient组件(这里以HttpClient4.3为例)可以模拟浏览器Http协议的request/response请求的交互。
下面的代码是基本使用的代码示例:
String url= "http://......."; // 构建请求参数 CloseableHttpClient httpclient=HttpClients.createDefault(); HttpGet httpget=new HttpGet(url); CloseableHttpResponse response=httpclient.execute(httpget); try { HttpEntity entity=response.getEntity(); InputStream in=entity.getContent(); if(in!=null){ //...... } //........... } finally { response.close(); } }
HttpClient是线程安全的,推荐在类中相同的实例在多线程中重复使用
1、HTTP request
httpClient支持HTTP1.1协议中的GET,HEAD,POST,PUT,DELETE,TRACE以及OPTIONS。分别对应如下的类:HttpGet,HttpHead,HttpPost,HttpPut,HttpDelete,HttpTrace以及HttpOptions.
HTTP 请求的URI由protocol scheme,hostname,optional port,resource path,optional query 和其他可选的部分组成
HttpClient提供了URI的构建工具类URIBuilder.使用方法如下:
URI uri=new URIBuilder().setScheme("http") .setHost("www.google.com") .setPath("/search") .setParameter("q", "httpclient") .setParameter("aq", "f") .build(); System.out.println(uri.toString());
执行结果:http://www.google.com/search?q=httpclient&aq=f
2、HTTP Response
reponse是服务器收到并解析request之后返回给请求端的信息。
HttpResponse response=new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus.SC_OK,"OK"); System.out.println(response.getProtocolVersion()); System.out.println(response.getStatusLine().getStatusCode()); System.out.println(response.getStatusLine().getReasonPhrase()); System.out.println(response.getStatusLine().toString());
执行结果:
HTTP/1.1
200
OK
HTTP/1.1 200 OK
3、Http的请求头
HttpResponse response=new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus.SC_OK,"OK"); response.addHeader("Set-Cookie","c1=a;path=/;domain=localhost"); response.addHeader("Set-Cookie", "c2=b;path=\"/\",c3=c;domain=\"localhost\""); Header h1=response.getFirstHeader("Set-Cookie"); System.out.println(h1); Header h2=response.getLastHeader("Set-Cookie"); System.out.println(h2); Header[] hs=response.getHeaders("Set-Cookie"); System.out.println(hs.length); //最方便获取请求头属性的方式 HeaderIterator it=response.headerIterator("Set-Cookie"); while(it.hasNext()){ System.out.println(it.next()); } HeaderElementIterator it=new BasicHeaderElementIterator(response.headerIterator("Set-Cookie")); while(it.hasNext()){ HeaderElement elem=it.nextElement(); System.out.println(elem.getName()+" = " +elem.getValue()); NameValuePair[] params=elem.getParameters(); for(int i=0;i<params.length;i++){ System.out.println(" "+params[i]); } }
4、HTTP entity
主要是response返回内容的实体或者是request的时候使用post或者put方式的时候用到entity.
主要方法,HttpEntity entity=response.getEntity(); InputStream in=entity.getContent();
获取entity内容推荐的方式为HttpEntity#getContent()或者HttpEntity#writeTo(outputStream).
HttpClient也提供了工具类EntityUtils.java。但是只在信任返回来源且确切知道来源长度较小的情况下
推荐使用。
String url= "http://........"; // 构建请求参数 CloseableHttpClient httpclient=HttpClients.createDefault(); HttpGet httpget=new HttpGet(url); CloseableHttpResponse response=httpclient.execute(httpget); try { HttpEntity entity=response.getEntity(); if(entity!=null){ long len=entity.getContentLength(); //当返回值长度较小的时候,使用工具类 if(len!=-1&&len<2048){ System.out.println(EntityUtils.toString(entity)); }else{ //否则使用IO流来读取 } } } finally { response.close(); }
有时候需要重复多次获取entity,则需要用到包装类BufferedHttpEntity.java.代码示例如下:
HttpEntity entity=response.getEntity(); if(entity!=null){ entity=new BufferedHttpEntity(entity); }
构建Entity的方式有多种数据形式,比如,string,byte array,input stream,file等。分别对应如下类,StringEntity,ByteArrayEntity,InputStreamEntity,FileEntity.代码示例如下:
File file=new File("somefile.txt"); FileEntity entity=new FileEntity(file); HttpPost httppost=new HttpPost("http://localhost/.../action.do"); httppost.setEntity(entity);
5、模拟HTML forms提交
List<NameValuePair> formparams=new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("param1", "value1")); formparams.add(new BasicNameValuePair("param2", "value2")); formparams.add(new BasicNameValuePair("param3", "value3")); UrlEncodedFormEntity entity=new UrlEncodedFormEntity(formparams,Consts.UTF_8); HttpPost httppost=new HttpPost("http://localhost/handler.do"); httppost.setEntity(entity);
6、Response Handlers
ResponseHandler,.....
7、针对幂等的请求,自定义重试机制的handler
//自定义重试机制 HttpRequestRetryHandler myRetryHandler=new HttpRequestRetryHandler(){ public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { if (executionCount >= 5) { // Do not retry if over max retry count return false; } if (exception instanceof InterruptedIOException) { // Timeout return false; } if (exception instanceof UnknownHostException) { // Unknown host return false; } if (exception instanceof ConnectTimeoutException) { // Connection refused return false; } if (exception instanceof SSLException) { // SSL handshake exception return false; } HttpClientContext clientContext = HttpClientContext.adapt(context); HttpRequest request = clientContext.getRequest(); boolean idempotent = !(request instanceof HttpEntityEnclosingRequest); if (idempotent) { // Retry if the request is considered idempotent return true; } return false; } }; CloseableHttpClient httpclient = HttpClients.custom() .setRetryHandler(myRetryHandler) .build(); }
8、HttpClient的拦截器(interceptor)
类似于servlet,需要自己保证线程安全。
代码示例:
//http拦截器 CloseableHttpClient httpclient = HttpClients.custom() .addInterceptorLast(new HttpRequestInterceptor() { public void process( final HttpRequest request, final HttpContext context) throws HttpException, IOException { AtomicInteger count = (AtomicInteger) context.getAttribute("count1"); request.addHeader("count1", Integer.toString(count.getAndIncrement())); } }).build(); AtomicInteger count = new AtomicInteger(1); HttpClientContext localContext = HttpClientContext.create(); localContext.setAttribute("count1", count); localContext.setAttribute("count2", count); HttpGet httpget = new HttpGet(url); for (int i = 0; i < 10; i++) { CloseableHttpResponse response = httpclient.execute(httpget, localContext); try { HttpEntity entity = response.getEntity(); //..... } finally { response.close(); } } }
9、重定向的Handler
httpcomponents 在处理重定向问题时,默认的情况下是有限制的:
对于 HEAD 和 GET 方法, HttpComponents 会自动做重定向处理;
对于 POST 和 PUT 方法, HttpComponents 不会进行自动重定向处理,这需要用户自己设定才行。
DefaultHttpClient client = new DefaultHttpClient(); LaxRedirectStrategy redirectStrategy = new LaxRedirectStrategy(); // 设定自己需要的重定向策略 client.setRedirectStrategy(redirectStrategy); // 创建登陆form List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("username", USERNAME)); formparams.add(new BasicNameValuePair("password", PASSWORD)); UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formparams, "UTF-8"); // 创建登陆请求 HttpPost loginPost = new HttpPost(URL_LOGIN); loginPost.setEntity(formEntity); // 执行请求, // 在使用默认的重定向策略是,状态代码返回的是 302 // 使用了重定向策略后, 状态代码返回的是 200 HttpResponse loginResponse = client.execute(loginPost); System.out.println("登录请求放回状态代码: " + loginResponse.getStatusLine().getStatusCode());
获取重定向的URI以及还原之后的URL:
CloseableHttpClient httpclient = HttpClients.createDefault(); HttpClientContext context = HttpClientContext.create(); HttpGet httpget = new HttpGet(url); CloseableHttpResponse response = httpclient.execute(httpget, context); try { HttpHost target = context.getTargetHost(); List<URI> redirectLocations = context.getRedirectLocations(); URI location = URIUtils.resolve(httpget.getURI(), target, redirectLocations); System.out.println("Final HTTP location: " + location.toASCIIString()); // Expected to be an absolute URI } finally { response.close(); }