HttpClient基础(一)

一、基本的使用

       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();
		}

 

  

    

猜你喜欢

转载自kongxuan.iteye.com/blog/1948444