URLConnection类给应用程序和web资源之间架设起了通信的桥梁,这些web资源通常是通过url来标记的,本文将讲述如何使用HttpURLConnection来访问web页面(发送数据流)和读取数据流。
在Servlet中对于需要用post方式(get会暴露参数)写入参数的时候就用到了HttpURLConnection.
请求的Servlet,也可以写入main方法中进行测试
package
com;
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
import
java.io.BufferedReader;
import
java.io.IOException;
import
java.io.InputStreamReader;
import
java.io.OutputStream;
import
java.io.OutputStreamWriter;
import
java.net.HttpURLConnection;
import
java.net.URL;
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
@SuppressWarnings(
"
serial
"
)
public
class
IOServlet
extends
HttpServlet
![](https://i-blog.csdnimg.cn/blog_migrate/1fa987a29c6482f53d401256f96355eb.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
/** *//**
* 对于主动请求其它接口的参数流写入(POST方式)
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
{
System.out.println("begin send");
String inputParam = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><page><username>爱心天使</usernaem><age>26</age></page>";
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
URL url = null;
HttpURLConnection httpConn = null;
OutputStream output = null;
OutputStreamWriter outr = null;
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
url = new URL("http://127.0.0.1:8888/iotest/ReadServlet");
httpConn = (HttpURLConnection) url.openConnection();
HttpURLConnection.setFollowRedirects(true);
httpConn.setDoOutput(true);
httpConn.setRequestMethod("POST");
httpConn.setRequestProperty("Content-Type", "text/xml");
httpConn.connect();
output = httpConn.getOutputStream();
outr = new OutputStreamWriter(output);
// 写入请求参数
outr.write(inputParam.toString().toCharArray(), 0, inputParam
.toString().length());
outr.flush();
outr.close();
System.out.println("send ok");
int code = httpConn.getResponseCode();
System.out.println("code " + code);
System.out.println(httpConn.getResponseMessage());
//读取响应内容
String sCurrentLine = "";
String sTotalString = "";
if (code == 200)
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
{
java.io.InputStream is = httpConn.getInputStream();
BufferedReader reader = new BufferedReader(
new InputStreamReader(is));
while ((sCurrentLine = reader.readLine()) != null)
if (sCurrentLine.length() > 0)
sTotalString = sTotalString + sCurrentLine.trim();
} else
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
{
sTotalString = "远程服务器连接失败,错误代码:" + code;
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
}
System.out.println("response:" + sTotalString);
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
{
this.doGet(request, response);
}
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
}
ReadServlet(相当于被请求的服务器):
package
com;
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
import
java.io.IOException;
import
java.io.PrintWriter;
import
javax.servlet.ServletException;
import
javax.servlet.ServletInputStream;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
@SuppressWarnings(
"
serial
"
)
public
class
ReadServlet
extends
HttpServlet
![](https://i-blog.csdnimg.cn/blog_migrate/1fa987a29c6482f53d401256f96355eb.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
{
System.out.println("begin read");
ServletInputStream inStream = request.getInputStream(); // 取HTTP请求流
int size = request.getContentLength(); // 取HTTP请求流长度
byte[] buffer = new byte[size]; // 用于缓存每次读取的数据
byte[] in_b = new byte[size]; // 用于存放结果的数组
int count = 0;
int rbyte = 0;
// 循环读取
while (count < size)
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
{
rbyte = inStream.read(buffer); // 每次实际读取长度存于rbyte中 sflj
for (int i = 0; i < rbyte; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
{
in_b[count + i] = buffer[i];
}
count += rbyte;
}
System.out.println("result:" + new String(in_b,0,in_b.length));
response.setContentType("text/html");
//注意响应中文数据时要设置
response.setCharacterEncoding("GBK");
PrintWriter out = response.getWriter();
//回与响应数据
out.write("您已经请求成功,这是响应数据!");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
{
this.doGet(request, response);
}
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
}
打开页面:http://localhost:8888/iotest/IOServlet
你会在后台看到如下输出说明你已经成功了:
begin send
send ok
begin read
result:
<?
xml version
=
"
1.0
"
encoding
=
"
UTF-8
"
?><
page
><
username
>
爱心天使
</
usernaem
><
age
>
26
</
age
></
page
>
code
200
OK
response:您已经请求成功,这是响应数据
!
==================================
介绍用Java解析网络数据的三种特殊方法,希望对正在寻求这方面问题答案的读者有所帮助。
UTF8转换成GB2312 当我们在基于HTTP协议的JSP或Servlet的应用中获取数据或发送请求时,JVM会把输送的数据编码成UTF8格式。如果我们直接从HTTP流中提取中文数据,提取的结果为“????”(可能更多问号),为转换成我们能够理解的中文字符,我们需要把UTF8转换成GB2312,借助ISO-8859-1标准编码能够轻易的实现,下面的代码实现了这一功能:
以下是引用片段:
byte [] b;
String utf8_value;
utf8_value = request.getParameter("NAME");//从HTTP流中取"NAME"的UTF8数据
b = utf8_value.getBytes("8859_1"); //中间用ISO-8859-1过渡
String name = new String(b, "GB2312"); //转换成GB2312字符
在知道流长度的情况下将输入流转换成字节数组 Java中的输入流抽象类InputStream有int read(byte[] b, int off, int len)方法,参数中byte[] b是用来存放从InputStream中读取的数据,int off指定数组b的偏移地址,也就是数组b的起始下标,int len指定需要读取的长度,方法返回实际读取的字节数。刚学Java的朋友可能要说:先定义一个与流长度等长的字节数组,调用read方法,指定起始下标为0,指定读取长度与数组长度等长,不是一下子可以读出来了吗?说的没错,笔者曾经也试着这样读取数据,但后来发现在读取网络数据时很不安全,我们想想在网络上获取数据可能并没那么流畅,数据流的传送可能会断断续续,所以并不能保证一次就能读取全部数据,特别是在读取大容量数据时更是如此,所以我们必须在读取数据时检测实际读到的长度,如果没有读完已知长度的数据就应该再次读取,以此循环检测,直到实际读取的长度累加与已知的长度相等,下面的代码实现了这一功能:
以下是引用片段:
ServletInputStream inStream = request.getInputStream(); //取HTTP请求流
int size = request.getContentLength(); //取HTTP请求流长度
byte[] buffer = new byte[size]; //用于缓存每次读取的数据
byte[] in_b = new byte[size]; //用于存放结果的数组
int count = 0;
int rbyte = 0;
while (count < size) { //循环读取
rbyte = inStream.read(buffer); //每次实际读取长度存于rbyte中
for(int i=0;i
in_b[count + i] = buffer[i];
}
count += rbyte;
}