您的位置:首页 > 理论基础 > 计算机网络

如何使用 java.net.URLConnection 处理 HTTP 请求?

2014-12-20 17:21 896 查看
[原文地址]

android中如何使用 java.net.URLConnection 处理 HTTP 请求?

非常基础非常清晰,虽然感觉像是从 stackoverflow上翻译过来的

首先需要做个声明:本文发布的代码片段都是很基础的例子。你需要自行处理像 NullPointerException、IOExceptions 、RuntimeExceptions、ArrayIndexOutOfBoundsException 这些异常。

准备开始:

首先,我们至少需要了解URL和字符集 charset,至于参数是可选的,主要取决于具体功能

?
query参数必须是 name=value 格式的,且通过 & 符号连接起来。通常还需要将 query 参数用指定的字符集 charset 进行编码,这里使用 URLEncoder#encode() 。

代码中的 String#format() 只是为了方便而已,当字符串连接符 “+” 出现两次以上时我比较喜欢使用这种方式,个人喜好而已。

发起一个HTTP GET请求,可以携带查询参数(可选):

这个任务比较轻松,使用默认的方法就可以了

?
使用 “?” 符号将query 字符串连接到URL上。 Accept-Charset 头信息可能暗示服务器其中的参数是什么编码。如果没有任何query字符串需要发送,那么可以直接忽略 Accept-Charset 头信息。如果不需要设置任何头信息,那么你完全可以使用 URL#的OpenStream()快捷方法。

?
无论哪种方式,如果另一端是一个 HttpServlet ,那么它的 doGet()方法将被调用,其中的参数可以通过 HttpServletRequest#getParameter()获取。

发起带query 参数 的HTTP POST 请求:

设置 URLConnection#setDoOutput() 为 true ,隐性设置请求方法为 POST。 标准的 HTTP POST 是一种 application/x-www-form-urlencoded 类型的网络表单,传递的参数都会被写入请求信息主体中。

?
注意:无论何时,如果希望以编程方式提交 HTML 格式的内容,别忘了获取query 参数中 元素下的 name=value 值对。 当然还有 下的name=value 值对。(因为这些参数通常会在服务器端用来判断按钮是否被按下,哪一个被按下等等)

你也可以将链接方式从 URLConnection 更改成 HttpURLConnection ,然后调用其中的 HttpURLConnection#setRequestMethod()方法。但是,如果你想使用连接作为输出,那么你仍然需要设置 URLConnection的#setDoOutput()为true。

?
无论哪种方式,如果另一端是一个 HttpServlet ,那么 doPost()方法将会被调用,传递的参数可以通过HttpServletRequest#getParameter() 获取。

发起 HTTP 请求

您可以通过 URLConnection#connect() 显式的发起HTTP请求,但是如果你希望获取 HTTP 响应需求信息,那么HTTP请求就会自动发起,例如 HTTP响应的响应体使用 URLConnection#getInputStream() 等方法时。上面的例子都是如此,所以connect()调用其实是多余的。

采集HTTP响应信息

HTTP 响应状态

这里你需要 HttpURLConnection 。如果有必要可以第一个调用。

?
HTTP 响应头信息

?
HTTP 响应编码

当 Content-type 中包含字符集参数时,响应主体可能是基于文本格式的 ,那么我们希望使用服务端指定的字符集处理消息主体。

?
会话维持

服务器端的会话通常是由 cookie 支持的。有些网页形式要求您登录 或者 可以跟踪会话。基本上你需要从所有登录或者第一次GET请求的响应中获取 Set-Cookie 头信息 ,然后传递给后续的请求。

?
split(“;”,2)[0] 用来去除与服务器端无关的cookie 属性,如 expires, path 等,另外,你也可以使用cookie.substring(0,cookie.indexOf(';'))代替 split()。

内建的另一种方法是使用CookieHandler API。在发送所有的 HTTP 请求之前,您需要准备一个 CookieManager ,其包含 ACCEPT_ALL 的CookiePolicy 。

?
请注意,众所周知的,以上的方法并不是所有情况下都有效。如果您尝试失败,那么最好是手动采集和设置cookie头信息,就像我们在第一个代码片段中所看到的那样。

流模式

默认情况下,在请求发送之前 ,无论您是否已经通过 connection.setRequestProperty(“Content-Length”, contentLength); 设置了内容的固定长度,HttpURLConnection 都会缓冲整个请求主体。因此当你同时发送大数据量 POST请求的时候(例如上传文件),就可能会导致 OutOfMemoryExceptions 异常。为了避免这种情况,你应该设置 HttpURLConnection setFixedLengthStreamingMode()。

?
但是,如果内容长度是事先不知道的,那么你可以利用分块流模式,通过设置 HttpURLConnection setChunkedStreamingMode(),更改 HTTP Transfer-Encoding 头信息,强制将请求主体以区块的形式发送出去。下面的例子按照每个区块1KB发送。

?
User-Agent

它的工作原理与真正的网页浏览器一样,当请求返回了意外的响应时才会产生。基于 User-Agent 请求头信息被服务器端阻塞的机会是很大的。 URLConnection 在默认情况下,将其设置为 Java/1.6.0_19 ,最后一部分很明显是 JRE的版本号。 您可以重写此方法,代码如下:

?
错误处理

如果HTTP 响应代码为4nn(客户端错误)或者 5nn(服务器错误),那么你可能想读取HttpURLConnection#getErrorStream() ,看看服务器是否发送了什么有用的错误信息。

?
如果 HTTP 响应代码为-1,那么肯定是连接和响应处理出现了错误。HttpURLConnection 的连接状态保持存在bug。您可以通过设置 http.keepAlive 的系统属性为false 来关闭连接。可以在应用程序开始时做以下操作:

?
上传文件

上传文件的POST 通常使用 multipart / form-data 编码(主要是二进制和字符数据)。更详细地介绍都在RFC2388中。

?
如果另一端是 HttpServlet ,那么 doPost()方法将被调用,parts 可通过 HttpServletRequest#getPart()获取(请注意,不是 getParameter()或其他方法)。 getPart()是一个相对较新的方法,在 Servlet 3.0 中有所介绍(GlassFish 3,Tomcat 7 等等)。在Servlet3.0 以前,你最好的选择就是使用Apache Commons FileUpload 解析 multipart / form-data 请求。

Apache HttpComponents HttpClient

这个HTTP库更方便

解析与提取 HTML

如果你想对HTML进行解析和提取其中的内容,最好使用HTML解析器,比如 Jsoup (Jsoup.org)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐