理解了HTTP的协议的基本请求构造后,我们来讲讲JAVA 的URL类的使用:
URL类是java中常用的网络类,这个类提供了很多的关于请求网络数据的方法:
其实最关键的是
url.openConnection();
URL url=new URL(path);
表示请求对应URL和获得有关的连接。
一般的用法是使用
HttpURLConnection count_length_con=(HttpURLConnection)url.openConnection();
这样来使用:
我们现在细细的表述下这个过程:
回想学过的HTTP的协议的请求过程:
URL url=new URL(path);
这个类的构造方法:其实就是建立三次握手,其实仅仅是建立了一个TCP连接,
HttpURLConnection count_length_con=(HttpURLConnection)url.openConnection();
而这个行代码,才是建立HTTP请求的时刻!
之后,我们可以对HttpUrlconceiton类进行参数设置:
比如:
count_length_con.setDoInput(true);
<pre name="code" class="java" style="color: rgb(61, 61, 61); font-size: 14px; text-align: justify;"> count_length_con.setDoOutput(true);
count_length_con.setRequestMethod("GET"); count_length_con.setReadTimeout(1000*60);
之后,这是在三次握手之后,这一步就是想服务器发送的TCP请求:
count_length_con.connect();
</pre><p>这之后,如果是connection.getInputStream();就是已经把请求数据发送完成,正式开启HTTP连接,得到会响应的报文,</p><p>如果是,connection.getOutputStream(),就是在写请求体的内容,此时,也是正式开启HTTP连接。</p><p>接下来我们说说如何去用java来模拟表单的的封装:</p><p><span style="font-family: Arial; font-size: 14px; line-height: 26px; color: rgb(51, 51, 51);">POST的表单的content-type一般有两种类型:application/x-www-form-urlencoded 和</span><span style="font-family: Arial; font-size: 14px; line-height: 26px; color: rgb(61, 61, 61);">multipart/form-data</span></p><p><span style="font-family:Arial;color:#3d3d3d;"><span style="font-size: 14px; line-height: 26px;">如果是第一种方式:因为没有文件类型的数据的时候,</span></span></p><p><span style="font-family:Arial;color:#3d3d3d;"><span style="font-size: 14px; line-height: 26px;"><span style="color: rgb(61, 61, 61); font-family: Arial; font-size: 14px; line-height: 26px;">则这样构造:</span></span></span><pre name="code" class="html">URL("http://jobsearch.dice.com/jobsearch/jobsearch.cgi");
URLConnection connection = url.openConnection();
OutputStreamWriter ut = newOutputStreamWriter(uc.getOutputStream(), "8859_1");
out.write("username=bob&password="+password+"");
// remember to clean up
out.flush();
out.close();
比如想服务器提交username和password数据的时候,用这种方式做请求参数的封装:
,请求的效果如下所示:
POST /jobsearch/jobsearch.cgi HTTP 1.0
ACCEPT: text/plain
Content-type: application/x-www-form-urlencoded
Content-length: 99
username=bob
password=someword
好,接下来讲下如何混合提交含有文件类型的表单(multipart/form-data)
首先,我们来看看这种类型的表单的请求体是如何构造的:
- --${bound}
- Content-Disposition: form-data; name="Filename"
- HTTP.pdf
- --${bound}
- Content-Disposition: form-data; name="file000"; filename="HTTP协议详解.pdf"
- Content-Type: application/octet-stream
- %PDF-1.5
- file content
- %%EOF
- --${bound}
- Content-Disposition: form-data; name="Upload"
- Submit Query
- --${bound}--
- --${bound} 是什么呢?这是边界分隔符号,用他来分隔我们混合的表单实体,比如文件,比如请求的字符串,这个分隔符号为
- --加上自定义符号,我们怎么去自定义呢?
- httpurlconnection.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundry);
- 这样就可以自定义了,现在,我们有怎么去模拟呢?
这里就附上我的代码里面的一个函数:
<span style="color:#3d3d3d;"> String boundry="******";//HTTP报文的分隔符符号
String twoHyphens="--";
String end="\r\n";//报文中换行符号
try {
URL url=new URL(url_path);
HttpURLConnection httpurlconnection=(HttpURLConnection)url.openConnection();
this.PrepareConnection(httpurlconnection);
httpurlconnection.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundry);
FileInputStream file_sd_inputstream=new FileInputStream(file_image);
DataOutputStream upload_file_server_stream=new DataOutputStream(httpurlconnection.getOutputStream());
String file_path=file_image.getAbsolutePath().trim();
upload_file_server_stream.writeBytes(twoHyphens+boundry+end);//有边界符号,开始写实体了
</span><span style="color:#ff0000;"> upload_file_server_stream.writeBytes("Content-Disposition: form-data;name=\"up_file\"; filename=\" "
+file_path.substring(file_path.lastIndexOf("/")+1)+ "\" "+end);</span>
<span style="color: rgb(61, 61, 61);"> //定义实体内容了,这个实体是文件,描述实体的POST名字和文件的名字,
</span><span style="color:#ff0000;"> upload_file_server_stream.writeBytes(end);</span><span style="color:#3d3d3d;">
this.WriteFormEntity(upload_file_server_stream, file_sd_inputstream);//这个函数我之后写在下面的代码里面,
file_sd_inputstream.close();
</span><span style="color:#ff0000;">upload_file_server_stream.writeBytes(end);</span><span style="color:#3d3d3d;">
</span><span style="color:#ff0000;">upload_file_server_stream.writeBytes(twoHyphens+boundry+end);</span>
<span style="color:#ff0000;">//写完一个实体后,发现还有实体可以提交,于是,我们还要再写的话,记得在写一次分隔符号</span><span style="color:#3d3d3d;">
</span><span style="color:#ff0000;"> upload_file_server_stream.writeBytes("Content-Disposition: form-data;name=\"user_id\" "+end);</span><span style="color:#3d3d3d;">
</span><span style="color:#ff0000;"> upload_file_server_stream.writeBytes(end);</span><span style="color:#3d3d3d;">
upload_file_server_stream.writeBytes("1");
</span><span style="color:#ff0000;">upload_file_server_stream.writeBytes(end);</span><span style="color:#3d3d3d;">
</span><span style="color:#ff0000;"> upload_file_server_stream.writeBytes(twoHyphens+boundry+twoHyphens+end);//没有想服务器发送的了,用--*******--表示结束</span><span style="color:#3d3d3d;">
upload_file_server_stream.flush();
String res=this.getServet_back_info(httpurlconnection);
upload_file_server_stream.close();
this.sendMSG_to_MainThread(res);
} catch (MalformedURLException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}</span>
上面那个写文件实体的代码:
private void WriteFormEntity(OutputStream file_outputstream,InputStream file_sd_inputstream)
{
byte []buffer=new byte[8192];
int len=-1;
try {
while((len=file_sd_inputstream.read(buffer))!=-1)
{
file_outputstream.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
大家看到了吧,就是这样的,简单,好用,只要你按照格式来,就很简单啦,
最后注意几点:1.一定要有服务器输入流,不然服务器怎么给你响应呢?这次请求过程都没有结束的说。
2.还有就是,记得对输出流flush,和close,及时释放内存,android的内存很珍贵的啊