HttpClient的post和get请求

简介:

HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。
虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。
HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,
并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外
两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。现在HttpClient最新版本为 HttpClient 4.5 (GA) (2015-09-11)

功能介绍:

  以下列出的是 HttpClient 提供的主要的功能,要知道更多详细的功能可以参见 HttpClient 的主页。
(1)实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
(2)支持自动转向
(3)支持 HTTPS 协议
(4)支持代理服务器等

代码实现:

package com.superb.httpclient;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.log4j.Logger;

public class HttpUtil {
	private final static Logger logger = Logger.getLogger(HttpUtil.class);

	private static ThreadSafeClientConnManager cm = null;
	static {
		try {
			SSLContext ctx = SSLContext.getInstance("TLS");
			X509TrustManager tm = new X509TrustManager() {
				public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

				}
                          
				public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

				}

				public X509Certificate[] getAcceptedIssuers() {
					return null;
				}
			};
			ctx.init(null, new TrustManager[] { tm }, null);
			SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
			SchemeRegistry schemeRegistry = new SchemeRegistry();
			schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
			schemeRegistry.register(new Scheme("https", 443, ssf));
			cm = new ThreadSafeClientConnManager(schemeRegistry);
			cm.setMaxTotal(400);
			cm.setDefaultMaxPerRoute(40);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @description 获取 HTTP Client
	 * @return
	 */
	private static HttpClient getHttpClient() {
		HttpParams params = new BasicHttpParams();
		params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
		params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
		return new DefaultHttpClient(cm, params);
	}

	/**
	 * @description HTTP POST
	 * @param url
	 * @param msg
	 * @return
	 */
	public static String post(String url, Map
    
    
     
      params) {
		logger.info("URLInvoke.post#request message : ");

		List
     
     
      
       list = new ArrayList
      
      
       
       ();
		if (params != null && !params.isEmpty()) {
			for (Map.Entry
       
       
        
         entry : params.entrySet()) {
				list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}
		}
		try {
			// 实现将请求的参数封装到表单中,即请求体中
			UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
			// 使用post方式提交数据
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(entity);
			// 执行post请求,并获取服务器端的响应HttpResponse
			HttpClient client = getHttpClient();
			HttpResponse httpResponse = client.execute(httpPost);

			// 获取服务器端返回的状态码和输入流,将输入流转换成字符串
			if (httpResponse.getStatusLine().getStatusCode() == 200) {
				InputStream inputStream = httpResponse.getEntity().getContent();
				return changeInputStream(inputStream, "UTF-8");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	/*
	 * // 把从输入流InputStream按指定编码格式encode变成字符串String
	 */
	public static String changeInputStream(InputStream inputStream, String encode) {
		// ByteArrayOutputStream 一般叫做内存流
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		byte[] data = new byte[1024];
		int len = 0;
		String result = "";
		if (inputStream != null) {
			try {
				while ((len = inputStream.read(data)) != -1) {
					byteArrayOutputStream.write(data, 0, len);
				}
				result = new String(byteArrayOutputStream.toByteArray(), encode);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		logger.info("URLInvoke.post#response message : " + result);
		return result;
	}

	/**
	 * HTTP GET
	 * 
	 * @param url
	 * @return
	 */
	public static String get(String url) {
		logger.info("URLInvoke.get#response url : " + url);
		HttpResponse httpResponse = null;
		InputStream inputStream = null;
		String result = "";
		// 生成一个请求对象
		HttpGet httpGet = new HttpGet(url);
		// 生成一个http客户端
		HttpClient httpClient = new DefaultHttpClient();
		// 使用Http客户端发送请求对象
		// httpResponse是服务器返回给我们的响应httpentity是响应的内容
		try {
			httpResponse = httpClient.execute(httpGet);
			HttpEntity httpEntity = httpResponse.getEntity();
			inputStream = httpEntity.getContent();
			BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));

			String line = "";
			while ((line = br.readLine()) != null) {
				result += "\n" + line;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (inputStream != null) {
					inputStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		logger.info("URLInvoke.get#response result : " + result);
		return result;
	}
}

        
         
         
           4.0.0 
          
         
           com.superb 
          
         
           maven-1 
          
         
           20160720 
          
         
           jar 
          
         
           maven-1 
          
         
           http://maven.apache.org 
          
          
          
            UTF-8 
           
          
          
           
           
             junit 
            
           
             junit 
            
           
             3.8.1 
            
           
             test 
            
           
           
           
             commons-logging 
            
           
             commons-logging 
            
           
             1.1.1 
            
           
           
           
             commons-codec 
            
           
             commons-codec 
            
           
             1.4 
            
           
           
           
             commons-httpclient 
            
           
             commons-httpclient 
            
           
             3.0.1 
            
           
           
           
             org.slf4j 
            
           
             slf4j-log4j12 
            
           
             1.7.2 
            
           
           
           
             org.apache.httpcomponents 
            
           
             httpclient 
            
           
             4.3.5 
            
           
          
        

       
       
      
      
     
     
    
    

常见问题:

字符编码

某目标页的编码可能出现在两个地方,第一个地方是服务器返回的http头中,另外一个地方是得到的html/xml页面中。
在http头的Content-Type字段可能会包含 字符编码信息。例如可能返回的头会包含这样子的信息:Content-Type: text/html; charset=UTF-8。
这个头信息表明该页的编码是UTF-8,但是服务器返回的头信息未必与内容能匹配上。比如对于一些双 字节语言国家,
可能服务器返回的编码类型是UTF-8, 但真正的内容却不是UTF-8编码的,因此需要在另外的地方去得到页面的编码信息;
但是如果服务器返回的编码不是UTF-8,而是具体的一些编码, 比如gb2312等,那服务器返回的可能是正确的编码信息。
通过method对象的getResponseCharSet()方法就可以得到http头中的编码信息。 对于象xml或者html这样的文件,
允许作者在页面中直接指定编码类型。比如在html中会有
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"/>这样的标签;
或者在xml中会有<?xml version="1.0" encoding="gb2312"?>这样的标签,在这些情况下,可能与http头中返回的编码信息冲突,
需要用户自己判断到底那种编码类型应该是真正的 编码
自动转向
根据RFC2616中对自动转向的定义,主要有两种:301和302。301表示永久的移走(Moved Permanently),当返回的是301,
则表示请求的资源已经被移到一个固定的新地方,任何向该地址发起请求都会被转到新的地址上。302表示暂时的转向,
比如在服务器端的servlet程序调用了sendRedirect方法,则在客户端就会得到一个302的代码,这时服务器返回的头信息
中location的值就是sendRedirect转向的目标地址。
HttpClient支持自动转向处理,但是象POST和PUT方式这种要求接受后继服务的请求方式,暂时不支持自动转向,
因此如果碰到POST方式提交后返回的是301或者302的话需要自己处理。就像刚才在POSTMethod中举的例子:
如果想进入登录BBS后的页面,必须重新发起登录的请求,请求的地址可以在头字段location中得到。不过需要注意的是,
有时候location返回的可能是相对路径,因此需要对location返回的值做一些处理才可以发起向新地址的请求。
另外除了在头中包含的信息可能使页面发生重定向外,在页面中也有可能会发生页面的重定向。引起页面自动转发的
标签是:<meta http-equiv="refresh" content="5; url=....">。如果你想在程序中也处理这种情况的话得自己分析页面来实现转向。
需要注意的是,在上面那个标签中url的值也可以是一个 相对地址,如果是这样的话,需要对它做一些处理后才可以转发。
另外还有一些其他常见问题,比如:处理https协议等等


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值