httpclient使用实例

来源:互联网 发布:统计局数据库 编辑:程序博客网 时间:2024/06/05 20:34
一、HttpClient简介

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


二、HttpClient 功能介绍

以下列出的是 HttpClient 提供的主要的功能,要知道更多详细的功能可以参见 HttpClient 的主页。


    实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)

    支持自动转向

    支持 HTTPS 协议

    支持代理服务器等


一般的情况下我们都是使用IE或者Navigator浏览器来访问一个WEB服务器,用来浏览页面查看信息或者提交一些数据等等。所访问的这些页面有的仅仅是一些普通的页面,有的需要用户登录后方可使用,或者需要认证以及是一些通过加密方式传输,例如HTTPS。目前我们使用的浏览器处理这些情况都不会构成问题。不过你可能在某些时候需要通过程序来访问这样的一些页面,比如从别人的网页中“偷”一些数据;利用某些站点提供的页面来完成某种功能,例如说我们想知道某个手机号码的归属地而我们自己又没有这样的数据,因此只好借助其他公司已有的网站来完成这个功能,这个时候我们需要向网页提交手机号码并从返回的页面中解析出我们想要的数据来。如果对方仅仅是一个很简单的页面,那我们的程序会很简单,本文也就没有必要大张旗鼓的在这里浪费口舌。但是考虑到一些服务授权的问题,很多公司提供的页面往往并不是可以通过一个简单的URL就可以访问的,而必须经过注册然后登录后方可使用提供服务的页面,这个时候就涉及到COOKIE问题的处理。我们知道目前流行的动态网页技术例如ASP、JSP无不是通过COOKIE来处理会话信息的。为了使我们的程序能使用别人所提供的服务页面,就要求程序首先登录后再访问服务页面,这过程就需要自行处理cookie,想想当你用java.net.HttpURLConnection来完成这些功能时是多么恐怖的事情啊!况且这仅仅是我们所说的顽固的WEB服务器中的一个很常见的“顽固”!再有如通过HTTP来上传文件呢?不需要头疼,这些问题有了“它”就很容易解决了!


我们不可能列举所有可能的顽固,我们会针对几种最常见的问题进行处理。当然了,正如前面说到的,如果我们自己使用java.net.HttpURLConnection来搞定这些问题是很恐怖的事情,因此在开始之前我们先要介绍一下一个开放源码的项目,这个项目就是Apache开源组织中的httpclient,它隶属于Jakarta的commons项目,目前的版本是2.0RC2。commons下本来已经有一个net的子项目,但是又把httpclient单独提出来,可见http服务器的访问绝非易事。
Commons-httpclient项目就是专门设计来简化HTTP客户端与服务器进行各种通讯编程。通过它可以让原来很头疼的事情现在轻松的解决,例如你不再管是HTTP或者HTTPS的通讯方式,告诉它你想使用HTTPS方式,剩下的事情交给httpclient替你完成。本文会针对我们在编写HTTP客户端程序时经常碰到的几个问题进行分别介绍如何使用httpclient来解决它们,为了让读者更快的熟悉这个项目我们最开始先给出一个简单的例子来读取一个网页的内容,然后循序渐进解决掉前进中的所有问题。


三、使用实例

1、工具类

package com.rmd.pay.utils;import org.apache.http.*;import org.apache.http.client.config.RequestConfig;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.config.*;import org.apache.http.conn.socket.ConnectionSocketFactory;import org.apache.http.conn.socket.PlainConnectionSocketFactory;import org.apache.http.entity.ContentType;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;import org.apache.http.message.BasicNameValuePair;import org.apache.http.util.EntityUtils;import java.io.IOException;import java.nio.charset.CodingErrorAction;import java.util.ArrayList;import java.util.List;import java.util.Map;/** * httpclient 工具类 * lc */public class HttpClientUtil {public static final int SOCKET_TIMEOUT = 180000;public static final int CONNECT_TIMEOUT = 10000;public static final int CONNECTION_REQUEST_TIMEOUT = 60000;/** * 默认的HTTP响应实体编码 = "UTF-8" */private static final String DEFAULT_CHARSET = "UTF-8";private HttpClientUtil() {}private static CloseableHttpClient httpClient = null;private static PoolingHttpClientConnectionManager connManager = null;static {Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create().register("http", PlainConnectionSocketFactory.INSTANCE).build();connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).build();connManager.setDefaultSocketConfig(socketConfig);MessageConstraints messageConstraints = MessageConstraints.custom().setMaxHeaderCount(200).setMaxLineLength(2000).build();ConnectionConfig connectionConfig = ConnectionConfig.custom().setMalformedInputAction(CodingErrorAction.IGNORE).setUnmappableInputAction(CodingErrorAction.IGNORE).setCharset(Consts.UTF_8).setMessageConstraints(messageConstraints).build();connManager.setDefaultConnectionConfig(connectionConfig);connManager.setMaxTotal(200);connManager.setDefaultMaxPerRoute(200);httpClient = HttpClients.custom().setConnectionManager(connManager).build();}/** * HTTP Get * <p/> * 响应内容实体采用<code>UTF-8</code>字符集 * @param url 请求url * @return 响应内容实体 */public static String get(String url) {return get(url, DEFAULT_CHARSET);}/** * 获取请求返回byte数组 * @param url 请求url * @return 响应内容实体 */public static byte[] get2Bytes(String url) {HttpGet getMethod = null;try {getMethod = new HttpGet(url);HttpResponse response = httpClient.execute(getMethod);return consumeResponseEntity(response);} catch (Exception e) {throw new RuntimeException(e);} finally {if (getMethod != null) {getMethod.releaseConnection();}}}/** * HTTP Get * @param url 请求url * @param responseCharset 响应内容字符集 * @return 响应内容实体 */public static String get(String url, String responseCharset) {HttpGet getMethod = null;try {getMethod = new HttpGet(url);HttpResponse response = httpClient.execute(getMethod);return consumeResponseEntity(response, responseCharset);} catch (Exception e) {throw new RuntimeException(e);} finally {if (getMethod != null) {getMethod.releaseConnection();}}}///////////////////////////////////////////////////////////////////////////// <<Post>>/** * HTTP Post * @param url 请求url * @param params 请求参数 * @return 响应内容实体 */public static String post(String url, Map<String, String> params) {return post(url, params, DEFAULT_CHARSET, DEFAULT_CHARSET);}/** * HTTP Post XML(使用默认字符集) * @param url 请求的URL * @param xml XML格式请求内容 * @return 响应内容实体 */public static String postXml(String url, String xml) {return postXml(url, xml, DEFAULT_CHARSET, DEFAULT_CHARSET);}/** * HTTP Post XML * @param url 请求的URL * @param xml XML格式请求内容 * @param requestCharset 请求内容字符集 * @param responseCharset 响应内容字符集 * @return 响应内容实体 */public static String postXml(String url, String xml, String requestCharset, String responseCharset) {return post(url, xml, "text/xml; charset=" + requestCharset, "text/xml", requestCharset, responseCharset);}/** * HTTP Post JSON(使用默认字符集) * @param url 请求的URL * @param json JSON格式请求内容 * @return 响应内容实体 */public static String postJson(String url, String json) {return postJson(url, json, DEFAULT_CHARSET, DEFAULT_CHARSET);}/** * HTTP Post JSON * @param url 请求的URL * @param json  JSON格式请求内容 * @param requestCharset 请求内容字符集 * @param responseCharset 响应内容字符集 * @return 响应内容实体 */public static String postJson(String url, String json, String requestCharset, String responseCharset) {return post(url, json, "application/json; charset=" + requestCharset, "application/json", requestCharset,responseCharset);}/** * HTTP Post * @param url 请求URL * @param params 请求参数集合 * @param paramEncoding 请求参数编码 * @param responseCharset 响应内容字符集 * @return 响应内容实体 */public static String post(String url, Map<String, String> params, String paramEncoding, String responseCharset) {HttpPost post = null;try {post = new HttpPost(url);if (params != null) {List<NameValuePair> paramList = new ArrayList<NameValuePair>();for (String key : params.keySet()) {paramList.add(new BasicNameValuePair(key, params.get(key)));}UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(paramList, paramEncoding);post.setEntity(formEntity);}// 设置请求和传输超时时间RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(SOCKET_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT).build();post.setConfig(requestConfig);// 执行请求HttpResponse response = httpClient.execute(post);return consumeResponseEntity(response, responseCharset);} catch (Exception e) {throw new RuntimeException(e);} finally {if (post != null) {post.releaseConnection();}}}/** * HTTP Post * @param url 请求的URL * @param content 请求内容 * @param contentType 请求内容类型,HTTP Header中的<code>Content-type</code> * @param mimeType 请求内容MIME类型 * @param requestCharset 请求内容字符集 * @param responseCharset 响应内容字符集 * @return 响应内容实体 */public static String post(String url, String content, String contentType, String mimeType, String requestCharset,String responseCharset) {HttpPost post = null;try {post = new HttpPost(url);post.setHeader("Content-Type", contentType);HttpEntity requestEntity = new StringEntity(content, ContentType.create(mimeType, requestCharset));post.setEntity(requestEntity);// 设置请求和传输超时时间RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(SOCKET_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT).build();post.setConfig(requestConfig);HttpResponse response = httpClient.execute(post);return consumeResponseEntity(response, responseCharset);} catch (Exception e) {throw new RuntimeException(e);} finally {if (post != null) {post.releaseConnection();}}}/** * 安全的消耗(获取)响应内容实体 * <p/> * 使用 将响应内容实体转换为字符串,同时关闭输入流 * <p/> * @param response HttpResponse * @param responseCharset 响应内容字符集 * @return 响应内容实体 * @throws IOException */private static String consumeResponseEntity(HttpResponse response, String responseCharset) throws IOException {if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {HttpEntity responseEntity = response.getEntity();String responseBody = EntityUtils.toString(responseEntity, responseCharset);return responseBody;} else {return null;}}/** * 安全的消耗(获取)响应内容实体 * <p/> * 使用 {@link EntityUtils} 将响应内容实体转换为字符串,同时关闭输入流 * <p/> * @param response HttpResponse * @return 响应内容实体 * @throws IOException */private static byte[] consumeResponseEntity(HttpResponse response) throws IOException {if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {HttpEntity responseEntity = response.getEntity();return EntityUtils.toByteArray(responseEntity);} else {return null;}}}

2、发送端

  @RequestMapping("sendOrder")    public void sendOrder(HttpServletResponse httpServletResponse)throws IOException{        Map<String, String>  jsonParam = new HashMap<String, String>(16);        // 订单号        jsonParam.put("orderNo","110021001100");        String url = "http://192.168.0.235:8080/rmd_lypay_testweb/polling/notifyOrderPolling";        // 发送        String str = HttpClientUtil.post(url,jsonParam);        // 返回值        JSONObject json = JSONObject.fromObject(str);        System.out.print(json);

3、接收端

package com.rmd.pay.controller;import net.sf.json.JSONObject;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;import java.util.HashMap;import java.util.Map;/** * 业务处理 * @author lc */@Controller@RequestMapping(value = "/polling")public class PollingMessageController {    private static final Log logger = LogFactory.getLog(BaseController.class);    /**     * 异步返回处理     * @param request     * @return     */    @RequestMapping(value="/notifyOrderPolling",method = RequestMethod.POST)    @ResponseBody    public String notifyOrderPolling(HttpServletRequest request) {        Map<String , String> paramMap = new HashMap<String , String>();        JSONObject result=new JSONObject();        try {            String orderNo = request.getParameter("orderNo");            if(orderNo != null){                System.out.println("订单号:"+orderNo);                result.put("status", "100");                result.put("message", "操作成功");            }else{                result.put("status", "200");                result.put("message", "操作失败");            }        }catch(Exception e){            result.put("status", "400");            result.put("message", "操作异常");            logger.error("请求异常!",e);        }        return result.toString();    }}




原创粉丝点击