HttpClient 简介
- 格式:doc
- 大小:44.00 KB
- 文档页数:11
前言超文本传输协议(HTTP)也许是当今互联网上使用的最重要的协议了。
Web服务,有网络功能的设备和网络计算的发展,都持续扩展了HTTP协议的角色,超越了用户使用的Web 浏览器范畴,同时,也增加了需要HTTP协议支持的应用程序的数量。
尽管包提供了基本通过HTTP访问资源的功能,但它没有提供全面的灵活性和其它很多应用程序需要的功能。
HttpClient就是寻求弥补这项空白的组件,通过提供一个有效的,保持更新的,功能丰富的软件包来实现客户端最新的HTTP标准和建议。
为扩展而设计,同时为基本的HTTP协议提供强大的支持,HttpClient组件也许就是构建HTTP客户端应用程序,比如web浏览器,web服务端,利用或扩展HTTP协议进行分布式通信的系统的开发人员的关注点。
1. HttpClient的范围基于HttpCore[/httpcomponents-core/index.html]的客户端HTTP运输实现库基于经典(阻塞)I/O内容无关2. 什么是HttpClient不能做的HttpClient 不是一个浏览器。
它是一个客户端的HTTP通信实现库。
HttpClient的目标是发送和接收HTTP报文。
HttpClient不会去缓存内容,执行嵌入在HTML页面中的javascript 代码,猜测内容类型,重新格式化请求/重定向URI,或者其它和HTTP运输无关的功能。
第一章基础1.1 执行请求HttpClient 最重要的功能是执行HTTP方法。
一个HTTP方法的执行包含一个或多个HTTP 请求/HTTP响应交换,通常由HttpClient的内部来处理。
而期望用户提供一个要执行的请求对象,而HttpClient期望传输请求到目标服务器并返回对应的响应对象,或者当执行不成功时抛出异常。
很自然地,HttpClient API的主要切入点就是定义描述上述规约的HttpClient接口。
这里有一个很简单的请求执行过程的示例:HttpClient httpclient = new DefaultHttpClient();HttpGet httpget = new HttpGet("http://localhost/");HttpResponse response = httpclient.execute(httpget);HttpEntity entity = response.getEntity();if (entity != null) {InputStream instream = entity.getContent();int l;byte[] tmp = new byte[2048];while ((l = instream.read(tmp)) != -1) {}}1.1.1 HTTP请求所有HTTP请求有一个组合了方法名,请求URI和HTTP协议版本的请求行。
使⽤HttpClient实现⽂件的上传下载⽅法1 HTTPHTTP 协议可能是现在 Internet 上使⽤得最多、最重要的协议了,越来越多的 Java 应⽤程序需要直接通过 HTTP 协议来访问⽹络资源。
虽然在 JDK 的 包中已经提供了访问 HTTP 协议的基本功能,但是对于⼤部分应⽤程序来说,JDK 库本⾝提供的功能还不够丰富和灵活。
HttpClient ⽤来提供⾼效的、最新的、功能丰富的⽀持 HTTP 协议的客户端编程⼯具包,并且它⽀持HTTP 协议最新的版本和建议。
⼀般的情况下我们都是使⽤Chrome或者其他浏览器来访问⼀个WEB服务器,⽤来浏览页⾯查看信息或者提交⼀些数据、⽂件上传下载等等。
所访问的这些页⾯有的仅仅是⼀些普通的页⾯,有的需要⽤户登录后⽅可使⽤,或者需要认证以及是⼀些通过加密⽅式传输,例如HTTPS。
⽬前我们使⽤的浏览器处理这些情况都不会构成问题。
但是⼀旦我们有需求不通过浏览器来访问服务器的资源呢?那该怎么办呢?下⾯以本地客户端发起⽂件的上传、下载为例做个⼩Demo。
HttpClient有两种形式,⼀种是org.apache.http下的,⼀种是mons.httpclient.HttpClient。
2 ⽂件上传⽂件上传可以使⽤两种⽅式实现,⼀种是PostMethod⽅式,⼀种是HttpPost⽅式。
两者的处理⼤同⼩异。
PostMethod是使⽤FileBody将⽂件包装流包装起来,HttpPost是使⽤FilePart将⽂件流包装起来。
在传递⽂件流给服务端的时候,都可以同时传递其他的参数。
2.1 客户端处理2.1.1 PostMethod⽅式将⽂件封装到FilePart中,放⼊Part数组,同时,其他参数可以放⼊StringPart中,这⾥没有写,只是单纯的将参数以setParameter的⽅式进⾏设置。
此处的HttpClient是mons.httpclient.HttpClient。
浅谈HttpClient、okhttp和RestTemplate的区别⼀、HttpClient1、pom依赖<!--HttpClient--><dependency><groupId>commons-httpclient</groupId><artifactId>commons-httpclient</artifactId><version>3.1</version></dependency>2、HttpClient代码实现public class HttpClientUtil {/*** httpClient的get请求⽅式* 使⽤GetMethod来访问⼀个URL对应的⽹页实现步骤:* 1.⽣成⼀个HttpClient对象并设置相应的参数;* 2.⽣成⼀个GetMethod对象并设置响应的参数;* 3.⽤HttpClient⽣成的对象来执⾏GetMethod⽣成的Get⽅法;* 4.处理响应状态码;* 5.若响应正常,处理HTTP响应内容;* 6.释放连接。
* @param url* @param charset* @return*/public static String doGet(String url, String charset) {//1.⽣成HttpClient对象并设置参数HttpClient httpClient = new HttpClient();//设置Http连接超时为5秒httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);//2.⽣成GetMethod对象并设置参数GetMethod getMethod = new GetMethod(url);//设置get请求超时为5秒getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 5000);//设置请求重试处理,⽤的是默认的重试处理:请求三次getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());String response = "";//3.执⾏HTTP GET 请求try {int statusCode = httpClient.executeMethod(getMethod);//4.判断访问的状态码if (statusCode != HttpStatus.SC_OK) {System.err.println("请求出错:" + getMethod.getStatusLine());}//5.处理HTTP响应内容//HTTP响应头部信息,这⾥简单打印Header[] headers = getMethod.getResponseHeaders();for(Header h : headers) {System.out.println(h.getName() + "---------------" + h.getValue());}//读取HTTP响应内容,这⾥简单打印⽹页内容//读取为字节数组byte[] responseBody = getMethod.getResponseBody();response = new String(responseBody, charset);System.out.println("-----------response:" + response);//读取为InputStream,在⽹页内容数据量⼤时候推荐使⽤//InputStream response = getMethod.getResponseBodyAsStream();} catch (HttpException e) {//发⽣致命的异常,可能是协议不对或者返回的内容有问题System.out.println("请检查输⼊的URL!");e.printStackTrace();} catch (IOException e) {//发⽣⽹络异常System.out.println("发⽣⽹络异常!");} finally {//6.释放连接getMethod.releaseConnection();}return response;}/*** post请求* @param url* @param json* @return*/public static String doPost(String url, JSONObject json){HttpClient httpClient = new HttpClient();PostMethod postMethod = new PostMethod(url);postMethod.addRequestHeader("accept", "*/*");postMethod.addRequestHeader("connection", "Keep-Alive");//设置json格式传送postMethod.addRequestHeader("Content-Type", "application/json;charset=GBK");//必须设置下⾯这个HeaderpostMethod.addRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36"); //添加请求参数postMethod.addParameter("commentId", json.getString("commentId"));String res = "";try {int code = httpClient.executeMethod(postMethod);if (code == 200){res = postMethod.getResponseBodyAsString();System.out.println(res);}} catch (IOException e) {e.printStackTrace();}return res;}public static void main(String[] args) {System.out.println(doGet("/cc/json/mobile_tel_segment.htm?tel=130********", "GBK"));System.out.println("-----------分割线------------");System.out.println("-----------分割线------------");System.out.println("-----------分割线------------");JSONObject jsonObject = new JSONObject();jsonObject.put("commentId", "130********");System.out.println(doPost("/cc/json/mobile_tel_segment.htm?tel=130********", jsonObject));}}3、建议代码复杂,还得操⼼资源回收等。
异步httpclient(httpasyncclient)的使⽤与总结参考:1. 前⾔应⽤层的⽹络模型有同步与异步。
同步意味当前线程是阻塞的,只有本次请求完成后才能进⾏下⼀次请求;异步意味着所有的请求可以同时塞⼊缓冲区,不阻塞当前的线程;httpclient在4.x之后开始提供基于nio的异步版本httpasyncclient,httpasyncclient借助了Java并发库和nio进⾏封装(虽说NIO是同步⾮阻塞IO,但是HttpAsyncClient提供了回调的机制,与netty类似,所以可以模拟类似于AIO的效果),其调⽤⽅式⾮常便捷,但是其中也有许多需要注意的地⽅。
2. pom⽂件本⽂依赖4.1.2,当前最新的客户端版本是4.1.3maven repository 地址<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.2</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><version>4.4.5</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore-nio</artifactId><version>4.4.5</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpasyncclient</artifactId><version>4.1.2</version></dependency>12345678910111213141516171819202122233. 简单的实例public class TestHttpClient {public static void main(String[] args){RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(50000).setSocketTimeout(50000).setConnectionRequestTimeout(1000).build();//配置io线程IOReactorConfig ioReactorConfig = IOReactorConfig.custom().setIoThreadCount(Runtime.getRuntime().availableProcessors()).setSoKeepAlive(true).build();//设置连接池⼤⼩ConnectingIOReactor ioReactor=null;try {ioReactor = new DefaultConnectingIOReactor(ioReactorConfig);} catch (IOReactorException e) {e.printStackTrace();}PoolingNHttpClientConnectionManager connManager = new PoolingNHttpClientConnectionManager(ioReactor); connManager.setMaxTotal(100);connManager.setDefaultMaxPerRoute(100);final CloseableHttpAsyncClient client = HttpAsyncClients.custom().setConnectionManager(connManager).setDefaultRequestConfig(requestConfig).build();//构造请求String url = "http://127.0.0.1:9200/_bulk";HttpPost httpPost = new HttpPost(url);StringEntity entity = null;try {String a = "{ \"index\": { \"_index\": \"test\", \"_type\": \"test\"} }\n" +"{\"name\": \"上海\",\"age\":33}\n";entity = new StringEntity(a);} catch (UnsupportedEncodingException e) {e.printStackTrace();}httpPost.setEntity(entity);//startclient.start();//异步请求client.execute(httpPost, new Back());while(true){try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}static class Back implements FutureCallback<HttpResponse>{private long start = System.currentTimeMillis();Back(){}public void completed(HttpResponse httpResponse) {try {System.out.println("cost is:"+(System.currentTimeMillis()-start)+":"+EntityUtils.toString(httpResponse.getEntity())); } catch (IOException e) {e.printStackTrace();}}public void failed(Exception e) {System.err.println(" cost is:"+(System.currentTimeMillis()-start)+":"+e);}public void cancelled() {2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66717273747576777879808182834. ⼏个重要的参数4.1 TimeOut(3个)的设置ConnectTimeout : 连接超时,连接建⽴时间,三次握⼿完成时间。
HttpClient源码分析/*** 此接⼝仅代表HTTP请求执⾏的最基本约定。
* 它对请求执⾏过程没有任何限制或特定的细节,并将状态管理、⾝份验证和重定向处理的细节留给单个实现。
*/public interface HttpClient {HttpResponse execute(HttpUriRequest request);}/*** ⽤于提供创建{@link CloseableHttpClient}实例⼯⼚⽅法.*/public class HttpClients {public static CloseableHttpClient createDefault() {return HttpClientBuilder.create().build();}}/*** HTTP消息包括从客户机到服务器的请求和从服务器到客户机的响应。
* HTTP-message = Request | Response ; HTTP/1.1 messages** {@link HttpRequest} and {@link HttpResponse} 接⼝继承{@link HttpMessage }*/public interface HttpMessage {}/*** 从客户机到服务器的请求消息包括,* 在该消息的第⼀⾏中,要应⽤于该资源的⽅法、资源的标识符以及正在使⽤的协议版本。
* method uri http/1.1*/public interface HttpRequest extends HttpMessage {RequestLine getRequestLine(); // 获取请求⾏}/*** 在接收和解释请求消息后,服务器⽤HTTP响应消息响应。
* 设置/获取状态⾏、状态码、原因短语、实体、locale*/public interface HttpResponse extends HttpMessage {}/*** Extended version of the {@link HttpRequest} interface that provides convenience methods to access request properties such as request URI and method type. * {@link HttpRequest}接⼝的扩展版本,提供访问请求属性(如请求URI和⽅法类型)的⽅便⽅法。
HttpClient、RestTemplate和Feign相关知识#先了解⼀下HTTP 协议史前时期 HTTP 协议在我们的⽣活中随处可见,打开⼿机或者电脑,只要你上⽹,不论是⽤ iPhone、Android、Windows 还是 Mac,不论是⽤浏览器还是 App,不论是看新闻、短视频还是听⾳乐、玩游戏,后⾯总会有 HTTP 在默默为你服务。
据 NetCraft 公司统计,⽬前全球⾄少有 16 亿个⽹站、2 亿多个独⽴域名,⽽这个庞⼤⽹络世界的底层运转机制就是 HTTP。
那么,在享受如此便捷舒适的⽹络⽣活时,你有没有想过,HTTP 协议是怎么来的?它最开始是什么样⼦的?⼜是如何⼀步⼀步发展到今天,⼏乎“统治”了整个互联⽹世界的呢? 20 世纪 60 年代,美国国防部⾼等研究计划署(ARPA)建⽴了 ARPA ⽹,它有四个分布在各地的节点,被认为是如今互联⽹的“始祖”。
然后在 70 年代,基于对 ARPA ⽹的实践和思考,研究⼈员发明出了著名的 TCP/IP 协议。
由于具有良好的分层结构和稳定的性能,TCP/IP 协议迅速战胜其他竞争对⼿流⾏起来,并在 80 年代中期进⼊了 UNIX 系统内核,促使更多的计算机接⼊了互联⽹。
创世纪 1989 年,任职于欧洲核⼦研究中⼼(CERN)的蒂姆·伯纳斯 - 李(Tim Berners-Lee)发表了⼀篇论⽂,提出了在互联⽹上构建超链接⽂档系统的构想。
这篇论⽂中他确⽴了三项关键技术。
URI:即统⼀资源标识符,作为互联⽹上资源的唯⼀⾝份;HTML:即超⽂本标记语⾔,描述超⽂本⽂档;HTTP:即超⽂本传输协议,⽤来传输超⽂本。
所以在这⼀年,我们的HTTP诞⽣了。
HTTP/0.9 20 世纪 90 年代初期的互联⽹世界⾮常简陋,计算机处理能⼒低,存储容量⼩,⽹速很慢,还是⼀⽚“信息荒漠”。
⽹络上绝⼤多数的资源都是纯⽂本,很多通信协议也都使⽤纯⽂本,所以 HTTP 的设计也不可避免地受到了时代的限制。
使用HttpClient 进行连接使用 .Http 命名空间中的 HttpClient 类可以向 WebService发送 POST与GET 请求并检索响应数据。
.Http 命名空间中的类可为现代 HTTP 应用提供编程接口。
.Http 命名空间和相关的 .Http.Headers 命名空间提供的 HTTP 客户端组件,允许用户通过 HTTP 使用现代的 WebService。
HttpClient 类用于通过 HTTP 发送和接收基本要求。
它提供了一个用于从 URI 所标识的资源发送 HTTP 请求和接收 HTTP 响应的基类。
该类可用来向 Web Service发送 GET、PUT、POST、DELETE 以及其他请求。
上述每种请求都作为异步操作进行发送。
HttpResponseMessage 类用于声明从 HTTP 请求接收到的 HTTP 响应消息。
HTTP 消息由 IETF 在 RFC 2616 中进行定义。
HttpContent 类是用于声明 HTTP 实体正文和内容标题的基类。
在这种情况下,HttpContent 用于声明 HTTP 响应。
以下示例使用 .NET Framework 4.0 的 C#。
同时你必须对 RFC 2616 中详细描述的 HTTP 请求有基本的了解。
一、创建新项目1. 打开Microsoft Visual Studio 2010,然后从“文件”菜单中选择“新建项目”。
在模板列表中,选择Visual C#。
在该区域下面,选择“Windows应用程序应用”,然后选择“空白应用程序”。
将该应用程序命名为winHttpClientBase,然后单击“确定”。
2. 添加Microsoft HTTP Client Libraries的引用如下图1,图2,图3,图4。
图1图2图3图4二、设置启用网络访问的功能需要为应用设置网络功能,以启用家庭网络或工作网络以及 Internet 的访问。
一、HttpClient 功能简介●实现了所有HTTP 的方法(GET,POST,PUT,HEAD,OPTIONS,TRACE)●支持自动转向●支持HTTPS 协议●透明地穿过HTTP代理建立连接●通过CONNECT方法,利用通过建立穿过HTTP代理的HTTPS连接●利用本地Java socket,透明地穿过SOCKS(版本5和4)代理建立连接●支持利用Basic、Digest和NTLM加密的认证●支持用于上传大文件的Multi-Part表单POST方法●插件式安全socket实现,易于使用第三方的解决方案●连接管理,支持多线程应用,支持设定单个主机总连接和最高连接数量,自动检测和关闭失效的连接●直接将请求信息流送到服务器的端口●直接读取从服务器的端口送出的应答信息●支持HTTP/1.0中用KeepAlive和HTTP/1.1中用persistance设置的持久连接●直接访问由服务器送出的应答代码和头部信息●可设置连接超时时间●HttpMethods 实现Command Pattern,以允许并行请求或高效连接复用●遵循the Apache Software License协议,源码免费可得二、环境搭建1.HttpClient 3.1 所需的基本jar包:commons-httpclient-3.1.jar,下载地址:/dist/httpcomponents/commons-httpclient/binary/;commons-logging.jar,下载地址:/logging/download_logging.cgi;commons-codec.jar,下载地址:/codec/download_codec.cgi;2.HttpClient 4所需的基本jar包:下载地址:/downloads.cgi;最新版本为4.1.2,且官方不再升级HttpClient3。
三、HttpClient 3.x 基本功能的使用1.使用 HttpClient 需要以下 6 个步骤:●创建HttpClient 的实例●创建某种连接方法的实例,在这里是GetMethod。
模拟http请求HttpClient简介HttpClient 功能介绍以下列出的是 HttpClient 提供的主要的功能,要知道更多详细的功能可以参见 HttpClient 的主页。
实现了所有 HTTP 的⽅法(GET,POST,PUT,HEAD 等)⽀持⾃动转向⽀持 HTTPS 协议⽀持代理服务器等⼀般的情况下我们都是使⽤IE或者Navigator浏览器来访问⼀个WEB服务器,⽤来浏览页⾯查看信息或者提交⼀些数据等等。
所访问的这些页⾯有的仅仅是⼀些普通的页⾯,有的需要⽤户登录后⽅可使⽤,或者需要认证以及是⼀些通过加密⽅式传输,例如HTTPS。
⽬前我们使⽤的浏览器处理这些情况都不会构成问题。
不过你可能在某些时候需要通过程序来访问这样的⼀些页⾯,⽐如从别⼈的⽹页中“偷”⼀些数据;利⽤某些站点提供的页⾯来完成某种功能,例如说我们想知道某个⼿机号码的归属地⽽我们⾃⼰⼜没有这样的数据,因此只好借助其他公司已有的⽹站来完成这个功能,这个时候我们需要向⽹页提交⼿机号码并从返回的页⾯中解析出我们想要的数据来。
如果对⽅仅仅是⼀个很简单的页⾯,那我们的程序会很简单,本⽂也就没有必要⼤张旗⿎的在这⾥浪费⼝⾆。
但是考虑到⼀些服务授权的问题,很多公司提供的页⾯往往并不是可以通过⼀个简单的URL就可以访问的,⽽必须经过注册然后登录后⽅可使⽤提供服务的页⾯,这个时候就涉及到COOKIE 问题的处理。
我们知道⽬前流⾏的动态⽹页技术例如ASP、JSP⽆不是通过COOKIE来处理会话信息的。
为了使我们的程序能使⽤别⼈所提供的服务页⾯,就要求程序⾸先登录后再访问服务页⾯,这过程就需要⾃⾏处理cookie,想想当你⽤.HttpURLConnection来完成这些功能时是多么恐怖的事情啊!况且这仅仅是我们所说的顽固的WEB服务器中的⼀个很常见的“顽固”!再有如通过HTTP来上传⽂件呢?不需要头疼,这些问题有了“它”就很容易解决了!我们不可能列举所有可能的顽固,我们会针对⼏种最常见的问题进⾏处理。
第25讲网络通信(2)—HttpClient一、HttpClient为了更好的处理向web站点的请求,包括处理Session、Cookie等细节问题,Apache开源组织提供了一个HttpClient项目(HttpClient就是一个增强版本的HttpURLConnection),扩展了HttpURLConnection的功能,Android将这个HttpClient所在的包集成了进来,较之HttpURLConnection,采用HttpClient发送请求,接收响应更为简单。
例:修改上面的Android客户端程序,采用HttpClient来发送GET和POST请求。
先创建一个能将InputStream转换成一个字节数组的工具类:public class StreamUtil {public static byte[] convertStreamToByte(InputStream in){ ByteArrayOutputStream baos = new ByteArrayOutputStream();byte [] buffer = new byte[1024];int len =0;try {while((len=in.read(buffer))!=-1){baos.write(buffer,0,len);}byte [] result = baos.toByteArray();return result;} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}}(1)发送GET请求public int login_HttpClient_Get(String username ,String password){ String baseURL ="http://192.168.101.62:8080/LoginDemoServer/servlet/LoginServlet";String path = baseURL+"?username="+username+"&password="+password;try {HttpClient client = new DefaultHttpClient(); //创建一个浏览器的客户端HttpGet httpGet = new HttpGet(path); //创建一个请求对象HttpResponse httpResponse = client.execute(httpGet); //将请求发送出去if(httpResponse.getStatusLine().getStatusCode()==200){Log.i("test", "网络连接成功,采用HttpClient的get请求");//进一步判断,返回回来的字符串是InputStream in =httpResponse.getEntity().getContent(); //得到服务器响应的输入流byte buffer[] = StreamUtil.convertStreamToByte(in);String result = new String(buffer).trim(); //.trim()去掉字符串前后空格换行等无用的字符Log.i("test", result+"--------------");if(result.equals("success")){Log.i("test", "登陆成功");return LOGINSUCCESS;}else{Log.i("test", "用户名密码错误");return LOGINFAILURE;}}else{//连接失败Log.i("test", "网络连接失败");return NETFAILURE;}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return 0;}(2)发送Post请求public int login_HttpClient_Post(String username ,String password){ String baseURL ="http://192.168.101.62:8080/LoginDemoServer/servlet/LoginServlet";HttpClient client = new DefaultHttpClient(); //创建一个浏览器的客户端HttpPost httpPost = new HttpPost(baseURL);try {username=new String(username.getBytes("utf8"),"iso8859-1");password=new String(password.getBytes("utf8"),"iso8859-1");} catch (UnsupportedEncodingException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}if(httpResponse.getStatusLine().getStatusCode()==200){Log.i("test", "网络连接成功,采用HttpClient的post请求");InputStream in =httpResponse.getEntity().getContent(); //得到服务器响应的输入流byte buffer[] = StreamUtil.convertStreamToByte(in);String result = new String(buffer).trim(); //.trim()去掉字符串前后空格换行等无用的字符Log.i("test", result+"--------------");if(result.equals("success")){Log.i("test", "登陆成功");return LOGINSUCCESS;}else{Log.i("test", "用户名密码错误");return LOGINFAILURE;}}else{//连接失败Log.i("test", "网络连接失败");return NETFAILURE;}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return 0;}二、数据提交的乱码处理---使用HttpClient(1)Post请求:发送时:在Android端,先将需要发送的文字:username=new String(username.getBytes("utf8"),"iso8859-1");values.add(new BasicNameValuePair("username",username)); //将转码后的字符串加入到Post 请求的参数中去。
HttpClient组件及其在Android开发中的应用探讨摘要:本文介绍了httpclient组件在web应用开发中的作用及基本使用方法,并探讨了在android手机客户端开发中的实际应用。
关键词:httpclient web客户端 android开发中图分类号:tp311.52 文献标识码:a 文章编号:1007-9416(2013)01-0078-011 引言http协议是目前internet上使用得最多、最重要的协议,除了以b/s模式(browser/server)开发的web应用系统之外,各类基于网络的设备、网络计算的发展等,都在不断地扩展着http的应用领域。
此外,即使是采用了b/s模式提供的信息服务,有时也需要通过定制的客户端程序而非用户驱动的浏览器来访问服务器资源。
httpclient组件为我们编写这一类java客户端程序提供了便捷有效的访问手段。
2 httpclient在web应用开发中的作用2.1 httpclient简介jdk的包已经提供了访问http协议的基本功能,但对于大部分应用程序来说,jdk库本身提供的功能还不够丰富和灵活。
httpclient是apache jakarta commons下的子项目,用来提供高效的、最新的、功能丰富的支持http协议的客户端编程工具包。
但httpclient并不是浏览器,例如它不支持对网页中javascript 脚本的执行。
2.2 httpclient的使用方法httpclient实现了http协议中的get,post,put,head 等方法,可通过这些方法向基于http协议的服务器提交请求,并从服务器端得到返回的响应,程序根据业务逻辑,对响应头及响应正文做进一步的处理。
下面以访问服务器端的登录页面为例,给出以post方式访问服务器资源的一般方法。
defaulthttpclient client = new defaulthttpclient();httppost post = new httppost(”http://localhost:8080/login.jsp”); //访问服务端的登录页面list qparams = new arraylist();q= new arraylist();q.add(new basicnamevaluepair(”username”,“sys”));q.add(new basicnamevaluepair(”passwd”,“neu”));urlencodedformentity params = new urlencodedformentity (q,“utf-8”);post.setentity(params);string res=client.execute(post, new basicresponsehandler());post.abort();3 httpclient在android开发中的应用在android开发中我们经常会与服务器进行数据的交互,为此android的sdk中提供了apache的httpclient组件,可方便地使用httpclient组件来访问基于http的网络资源。
HttpClient详细使⽤⽰例详解⽬录进⼊正题详细使⽤⽰例HttpClient 是Apache Jakarta Common 下的⼦项⽬,可以⽤来提供⾼效的、最新的、功能丰富的⽀持 HTTP 协议的客户端编程⼯具包,并且它⽀持 HTTP 协议最新的版本和建议。
HTTP 协议可能是现在 Internet 上使⽤得最多、最重要的协议了,越来越多的 Java 应⽤程序需要直接通过 HTTP 协议来访问⽹络资源。
虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于⼤部分应⽤程序来说,JDK 库本⾝提供的功能还不够丰富和灵活。
HttpClient 是 Apache Jakarta Common 下的⼦项⽬,⽤来提供⾼效的、最新的、功能丰富的⽀持 HTTP 协议的客户端编程⼯具包,并且它⽀持 HTTP 协议最新的版本和建议。
HTTP和浏览器有点像,但却不是浏览器。
很多⼈觉得既然HttpClient是⼀个HTTP客户端编程⼯具,很多⼈把他当做浏览器来理解,但是其实HttpClient不是浏览器,它是⼀个HTTP通信库,因此它只提供⼀个通⽤浏览器应⽤程序所期望的功能⼦集,最根本的区别是HttpClient中没有⽤户界⾯,浏览器需要⼀个渲染引擎来显⽰页⾯,并解释⽤户输⼊,例如⿏标点击显⽰页⾯上的某处,有⼀个布局引擎,计算如何显⽰HTML页⾯,包括级联样式表和图像。
javascript解释器运⾏嵌⼊HTML页⾯或从HTML页⾯引⽤的javascript代码。
来⾃⽤户界⾯的事件被传递到javascript解释器进⾏处理。
除此之外,还有⽤于插件的接⼝,可以处理Applet,嵌⼊式媒体对象(如pdf⽂件,Quicktime电影和Flash动画)或ActiveX控件(可以执⾏任何操作)。
HttpClient只能以编程的⽅式通过其API⽤于传输和接受HTTP消息。
HttpClient的主要功能:实现了所有 HTTP 的⽅法(GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS 等)⽀持 HTTPS 协议⽀持代理服务器(Nginx等)等⽀持⾃动(跳转)转向……进⼊正题环境说明:JDK1.8、SpringBoot准备环节第⼀步:在pom.xml中引⼊HttpClient的依赖第⼆步:引⼊fastjson依赖注:本⼈引⼊此依赖的⽬的是,在后续⽰例中,会⽤到“将对象转化为json字符串的功能”,也可以引其他有此功能的依赖。
HttpClient提供URIBuilder工具类来简化URIs的创建和修改过程。
1. URI uri = new URIBuilder()2. .setScheme("http")3. .setHost("")4. .setPath("/search")5. .setParameter("q", "httpclient")6. .setParameter("btnG", "Google Search")7. .setParameter("aq", "f")8. .setParameter("oq", "")9. .build();10. HttpGet httpget = new HttpGet(uri);11. System.out.println(httpget.getURI());上述代码会在控制台输出:1. /search?q=httpclient&btnG=Google+Search&aq=f&oq=1.1.2. HTTP响应服务器收到客户端的http请求后,就会对其进行解析,然后把响应发给客户端,这个响应就是HTTP response.HTTP响应第一行是协议版本,之后是数字状态码和相关联的文本段。
1. HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,2. HttpStatus.SC_OK, "OK");3.4. System.out.println(response.getProtocolVersion());5. System.out.println(response.getStatusLine().getStatusCode());6. System.out.println(response.getStatusLine().getReasonPhrase());7. System.out.println(response.getStatusLine().toString());上述代码会在控制台输出:1. HTTP/1.12. 2003. OK4. HTTP/1.1 200 OK1.1.3. 消息头一个Http消息可以包含一系列的消息头,用来对http消息进行描述,比如消息长度,消息类型等等。
Commons-HTTPClient组件项目1、Commons-HTTPClient组件的主要功能(1)需要在应用程序中直接访问Web服务器中的目标资源在访问Web服务器中的目标资源时,一般是采用标准的浏览器程序实现。
但现在越来越多的Java 应用程序需要直接通过 HTTP 协议来访问Web服务器中的目标资源——比如RIA中的应用程序客户端程序。
(2)常规的方式是应用JDK中的 包中URL和URLConnection类虽然在 JDK 的 包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 系统库中所提供的功能不够丰富和也不灵活。
(3)HttpClient 是 Apache Jakarta Commons中的一个子项目它为开发人员提供高效的、最新的、功能丰富的支持HTTP 协议的客户端编程工具包,Commons-HttpClient项目就是专门设计并用来简化HTTP客户端与服务器进行各种通讯编程实现的——它能实现常规的HTTP客户端程序(也就是浏览器程序)的各种功能。
(4)HttpClient组件所提供的主要功能●实现了http1.0和1.1版中的全部方法(GET、POST、PUT、DELETE、HEAD、OPTIONS和TRACE)和支持Cookie●支持HTTPS的加密操作,并透明地穿过HTTP代理建立连接●支持利用Basic、Digest和NTLM加密的认证、支持用于上传大文件的Multi-Part表单POST方法●不仅能够直接将请求信息流送到服务器的端口,也能够直接读取从服务器的端口送出的应答信息,直接访问由服务器送出的应答代码和头部信息●支持HTTP/1.0中用KeepAlive和HTTP/1.1中用persistance设置的持久连接●可设置连接超时时间,并且其中的HttpMethods允许并行请求或高效连接复用2、下载Commons-HTTPClient组件及有关的系统库文件(1)Commons-HTTPClient组件中的主要系统库文件ommons-httpclient-3.1.jar可以在Apache的官方网站中下载系统库(2)还需要commons-codec-1.3.jar文件否则在应用HttpClient时会报错:NoClassDefFoundError org/apache/commons/codec/DecoderException (3)当然也还需要Common-logging日志功能组件3、然后再将它们分别放入到项目的lib目录中4、熟悉HTTP请求的各种方式及差别(1)Options请求提交方式Options请求提交方式可以获得针对由请求URL标识的目标Web服务器的资源在请求/应答的通信过程可以使用的功能选项。
JDK之HttpClient(jdk11)HttpClient 简介.http.HttpClient 是 jdk11 中正式启⽤的⼀个 http ⼯具类(其实早在 jdk9 的时候就已经存在了,只是处于孵化期),官⽅寓意为想要取代 HttpURLConnection 和 Apache HttpClient 等⽐较古⽼的开发⼯具。
新增的 HttpClient 截⽌到⽬前(2019年3⽉)为⽌其实⽹络资料还⽐较少,笔者只是根据⼀些博⽂和官⽅ Demo ⾃⼰摸索了⼀下,做了下总结。
由于是 jdk11 中才正式使⽤的⼯具类,距离开发者还很遥远,所以对于源码笔者暂不打算深挖,浅浅的理解怎么使⽤就⾏⼀、HttpClient在 Apache HttpClient 中,⼀般会创建⼀个 HttpClient 对象来作为门⾯。
.http.HttpClient 的逻辑也差不多,只是创建⽅式更加时髦了://创建 builderHttpClient.Builder builder = HttpClient.newBuilder();//链式调⽤HttpClient client = builder//http 协议版本 1.1 或者 2.version(HttpClient.Version.HTTP_2) //.version(HttpClient.Version.HTTP_1_1)//连接超时时间,单位为毫秒.connectTimeout(Duration.ofMillis(5000)) //.connectTimeout(Duration.ofMinutes(1))//连接完成之后的转发策略.followRedirects(HttpClient.Redirect.NEVER) //.followRedirects(HttpClient.Redirect.ALWAYS)//指定线程池.executor(Executors.newFixedThreadPool(5))//认证,默认情况下 Authenticator.getDefault() 是 null 值,会报错//.authenticator(Authenticator.getDefault())//代理地址//.proxy(ProxySelector.of(new InetSocketAddress("", 8080)))//缓存,默认情况下 CookieHandler.getDefault() 是 null 值,会报错//.cookieHandler(CookieHandler.getDefault())//创建完成.build();在 builder() ⽅法中,最终会调⽤到 HttpClientImpl 的构造器,完成 HttpClient 的创建⼯作://HttpClientImpl.classprivate HttpClientImpl(HttpClientBuilderImpl builder,SingleFacadeFactory facadeFactory) {//CLIENT_IDS 是 AtomicLong 类型的变量,使⽤ incrementAndGet() ⽅法实现⾃增长的 idid = CLIENT_IDS.incrementAndGet();//记录下存有 id 的字符串dbgTag = "HttpClientImpl(" + id + ")";//ssl 认证if (builder.sslContext == null) {try {sslContext = SSLContext.getDefault();} catch (NoSuchAlgorithmException ex) {throw new InternalError(ex);}} else {sslContext = builder.sslContext;}//线程池,没有的话就默认创建⼀个Executor ex = builder.executor;if (ex == null) {ex = Executors.newCachedThreadPool(new DefaultThreadFactory(id));isDefaultExecutor = true;} else {isDefaultExecutor = false;}delegatingExecutor = new DelegatingExecutor(this::isSelectorThread, ex); facadeRef = new WeakReference<>(facadeFactory.createFacade(this));//处理 http 2 的 client 类client2 = new Http2ClientImpl(this);‘//缓存操作cookieHandler = builder.cookieHandler;//超时时间connectTimeout = builder.connectTimeout;//转发策略,默认为 NEVERfollowRedirects = builder.followRedirects == null ?Redirect.NEVER : builder.followRedirects;//代理设置erProxySelector = Optional.ofNullable(builder.proxy);this.proxySelector = userProxySelector.orElseGet(HttpClientImpl::getDefaultProxySelector);if (debug.on())debug.log("proxySelector is %s (user-supplied=%s)",this.proxySelector, userProxySelector.isPresent());//认证设置authenticator = builder.authenticator;//设置 http 协议版本if (builder.version == null) {version = HttpClient.Version.HTTP_2;} else {version = builder.version;}if (builder.sslParams == null) {sslParams = getDefaultParams(sslContext);} else {sslParams = builder.sslParams;}//连接线程池connections = new ConnectionPool(id);connections.start();timeouts = new TreeSet<>();//SelectorManager 本质上是 Thread 类的封装//selmgr 会开启⼀条线程,HttpClient 的主要逻辑运⾏在此线程中//所以说 HttpClient 是⾮阻塞的,因为并不跑在主线程中try {selmgr = new SelectorManager(this);} catch (IOException e) {throw new InternalError(e);}//设置为守护线程selmgr.setDaemon(true);filters = new FilterFactory();initFilters();assert facadeRef.get() != null;}主要是⼀些储存操作,⼤致理解即可,不细究。
HttpClient简介HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持HTTP 协议的客户端编程工具包,并且它支持HTTP 协议最新的版本和建议。
本文首先介绍HTTPClient,然后根据作者实际工作经验给出了一些常见问题的解决方法。
HTTP 协议可能是现在Internet 上使用得最多、最重要的协议了,越来越多的Java 应用程序需要直接通过HTTP 协议来访问网络资源。
虽然在JDK 的 包中已经提供了访问HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。
HttpClient 是Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP 协议的客户端编程工具包,并且它支持HTTP 协议最新的版本和建议。
HttpClient 已经应用在很多的项目中,比如Apache Jakarta 上很著名的另外两个开源项目Cactus 和HTMLUnit 都使用了HttpClient。
现在HttpClient最新版本为HttpClient 4.0-beta22.HttpClient 功能介绍以下列出的是HttpClient 提供的主要的功能,要知道更多详细的功能可以参见HttpClient 的主页。
(1)实现了所有HTTP 的方法(GET,POST,PUT,HEAD 等)(2)支持自动转向(3)支持HTTPS 协议(4)支持代理服务器等3.HttpClient 基本功能的使用(1) GET方法使用HttpClient 需要以下6 个步骤:1. 创建HttpClient 的实例2. 创建某种连接方法的实例,在这里是GetMethod。
在GetMethod 的构造函数中传入待连接的地址3. 调用第一步中创建好的实例的execute 方法来执行第二步中创建好的method 实例4. 读response5. 释放连接。
无论执行方法是否成功,都必须释放连接6. 对得到后的内容进行处理根据以上步骤,我们来编写用GET方法来取得某网页内容的代码。
大部分情况下HttpClient 默认的构造函数已经足够使用。
HttpClient httpClient = new HttpClient();创建GET方法的实例。
在GET方法的构造函数中传入待连接的地址即可。
用GetMethod将会自动处理转发过程,如果想要把自动处理转发过程去掉的话,可以调用方法setFollowRedirects(false)。
GetMethod getMethod = new GetMethod(".....");调用实例httpClient的executeMethod方法来执行getMethod。
由于是执行在网络上的程序,在运行executeMethod方法的时候,需要处理两个异常,分别是HttpException和IOException。
引起第一种异常的原因主要可能是在构造getMethod的时候传入的协议不对,比如不小心将"http"写成"htp",或者服务器端返回的内容不正常等,并且该异常发生是不可恢复的;第二种异常一般是由于网络原因引起的异常,对于这种异常(IOException),HttpClient会根据你指定的恢复策略自动试着重新执行executeMethod方法。
HttpClient的恢复策略可以自定义(通过实现接口HttpMethodRetryHandler来实现)。
通过httpClient的方法setParameter设置你实现的恢复策略,本文中使用的是系统提供的默认恢复策略,该策略在碰到第二类异常的时候将自动重试3次。
executeMethod返回值是一个整数,表示了执行该方法后服务器返回的状态码,该状态码能表示出该方法执行是否成功、需要认证或者页面发生了跳转(默认状态下GetMethod的实例是自动处理跳转的)等。
//设置成了默认的恢复策略,在发生异常时候将自动重试3次,在这里你也可以设置成自定义的恢复策略getMethod.getParams().setParameter(HttpMethodParams.RETRY_ HANDLER,new DefaultHttpMethodRetryHandler());//执行getMethodint statusCode = client.executeMethod(getMethod);if (statusCode != HttpStatus.SC_OK) {System.err.println("Method failed: " +getMethod.getStatusLine());}在返回的状态码正确后,即可取得内容。
取得目标地址的内容有三种方法:第一种,getResponseBody,该方法返回的是目标的二进制的byte流;第二种,getResponseBodyAsString,这个方法返回的是String类型,值得注意的是该方法返回的String的编码是根据系统默认的编码方式,所以返回的String值可能编码类型有误,在本文的"字符编码"部分中将对此做详细介绍;第三种,getResponseBodyAsStream,这个方法对于目标地址中有大量数据需要传输是最佳的。
在这里我们使用了最简单的getResponseBody方法。
byte[] responseBody = method.getResponseBody();释放连接。
无论执行方法是否成功,都必须释放连接。
method.releaseConnection();处理内容。
在这一步中根据你的需要处理内容,在例子中只是简单的将内容打印到控制台。
System.out.println(newString(responseBody));下面是程序的完整代码,这些代码也可在附件中的test.GetSample 中找到。
package test;import java.io.IOException;import mons.httpclient.*;import mons.httpclient.methods.GetMethod;importmons.httpclient.params.HttpMethodParams;public class GetSample{public static void main(String[] args) {//构造HttpClient的实例HttpClient httpClient = new HttpClient();//创建GET方法的实例GetMethod getMethod = new GetMethod("...");//使用系统提供的默认的恢复策略getMethod.getParams().setParameter(HttpMethodParams.RETRY_ HANDLER,new DefaultHttpMethodRetryHandler());try {//执行getMethodint statusCode = httpClient.executeMethod(getMethod);if (statusCode != HttpStatus.SC_OK) {System.err.println("Method failed: "+ getMethod.getStatusLine());}//读取内容byte[] responseBody = getMethod.getResponseBody();//处理内容System.out.println(new String(responseBody));} catch (HttpException e) {//发生致命的异常,可能是协议不对或者返回的内容有问题System.out.println("Please check your provided http address!");e.printStackTrace();} catch (IOException e) {//发生网络异常e.printStackTrace();} finally {//释放连接getMethod.releaseConnection();}}}(2)POST方法根据RFC2616,对POST的解释如下:POST方法用来向目的服务器发出请求,要求它接受被附在请求后的实体,并把它当作请求队列(Request-Line)中请求URI所指定资源的附加新子项。
POST被设计成用统一的方法实现下列功能:对现有资源的注释(Annotation of existing resources)向电子公告栏、新闻组,邮件列表或类似讨论组发送消息提交数据块,如将表单的结果提交给数据处理过程通过附加操作来扩展数据库调用HttpClient中的PostMethod与GetMethod类似,除了设置PostMethod的实例与GetMethod有些不同之外,剩下的步骤都差不多。
在下面的例子中,省去了与GetMethod相同的步骤,只说明与上面不同的地方,并以登录清华大学BBS为例子进行说明。
构造PostMethod之前的步骤都相同,与GetMethod一样,构造PostMethod也需要一个URI参数。
在创建了PostMethod的实例之后,需要给method实例填充表单的值,在BBS的登录表单中需要有两个域,第一个是用户名(域名叫id),第二个是密码(域名叫passwd)。
表单中的域用类NameValuePair来表示,该类的构造函数第一个参数是域名,第二参数是该域的值;将表单所有的值设置到PostMethod中用方法setRequestBody。
另外由于BBS登录成功后会转向另外一个页面,但是HttpClient对于要求接受后继服务的请求,比如POST和PUT,不支持自动转发,因此需要自己对页面转向做处理。
具体的页面转向处理请参见下面的"自动转向"部分。
代码如下:String url = "....";PostMethod postMethod = new PostMethod(url);// 填入各个表单域的值NameValuePair[] data = { new NameValuePair("id", "youUserName"),new NameValuePair("passwd", "yourPwd") };// 将表单的值放入postMethod中postMethod.setRequestBody(data);// 执行postMethodint statusCode = httpClient.executeMethod(postMethod);// HttpClient对于要求接受后继服务的请求,象POST和PUT等不能自动处理转发// 301或者302if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY ||statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {// 从头中取出转向的地址Header locationHeader =postMethod.getResponseHeader("location");String location = null;if (locationHeader != null) {location = locationHeader.getValue();System.out.println("The page was redirected to:" + location);} else {System.err.println("Location field value is null.");}return;}[编辑本段]4 使用HttpClient过程中常见的一些问题下面介绍在使用HttpClient过程中常见的一些问题。