公司的项目中有用HttpUrlConnection来编写测试类,虽然一直在用它,但是一直都没有对他有个研究,今天就来看看HttpUrlConnection。
先上Demo代码,然后分析几个关键点
package wangcc.test;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URI;
import java.net.URL;
import org.junit.Test;
public class TestConnection {
/**
* @Title: main
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param @param args
* @return void 返回类型
* @throws
*/
private static String connUrl="http://127.0.0.1:8080/MyHttpUrlConnectionTest/TestConnectionServlet";
public static void main(String[] args) {
// TODO Auto-generated method stub
}
private static void setConnectProperties(HttpURLConnection conn,int len) throws ProtocolException{
conn.setDoInput(true);
conn.setDoOutput(true);
/**
* 有些协议用于文档缓存。有时候能够进行“直通”并忽略缓存尤其重要,例如浏览器中的“重新加载”按钮。如果连接中的 UseCaches 标志为 true,则允许连接使用任何可用的缓存。如果为 false,则忽略缓存。默认值来自 DefaultUseCaches,它默认为 true。
* */
conn.setUseCaches(false);
System.out.println("超时毫秒数:"+conn.getConnectTimeout());
/**
* 设置一个指定的超时值(以毫秒为单位),该值将在打开到此 URLConnection 引用的资源的通信链接时使用。如果在建立连接之前超时期满,则会引发一个 java.net.SocketTimeoutException。超时时间为零表示无穷大超时。
此方法的一些非标准实现可能忽略指定的超时。要查看连接超时设置,请调用 getConnectTimeout()。
*/
conn.setConnectTimeout(30000);
conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-length", String.valueOf(len));
conn.setRequestMethod("POST");
}
@Test
public void testConn() throws Exception{
HttpURLConnection conn = null;
DataOutputStream dataout=null;
DataInputStream in=null;
BufferedReader reader=null;
try {
URL url=new URL(connUrl);
conn=(HttpURLConnection) url.openConnection();
String str="科比,布莱恩特:詹姆斯,勒布朗";
byte[] sendBytes=str.getBytes("GBK");
setConnectProperties(conn, sendBytes.length);
//调用conn.getOutputStream()时,会隐式的调用conn.connect();
dataout=new DataOutputStream(conn.getOutputStream());
dataout.write(sendBytes);
dataout.flush();
dataout.close();
System.out.println("超时毫秒数2:"+conn.getConnectTimeout());
in=new DataInputStream(conn.getInputStream());
reader=new BufferedReader(new InputStreamReader(in,"GBK"));
String s=null;
StringBuffer sb=new StringBuffer();
while((s=reader.readLine())!=null)
{
sb.append(s);
}
in.close();
System.out.println(sb.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
throw e;
}finally{
if (conn != null)
conn.disconnect();
if (reader != null)
reader.close();
if (in != null)
in.close();
if (dataout != null)
dataout.close();
}
}
}
利用JDK中的HttpUrlConnection 连接servlet或者基于servlet的web框架
,同样是有两种方式,POST,GET.get方式是将参数绑定在URL后面,而POST的参数是在请求体中。可以用抓包工具测试一下。
我们接下来看一下HttpURLConnection类。
HttpUrlConnection继承了URLConnection类,URLConnection代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源。通常,创建一个到 URL 的连接需要几个步骤:
1.通过在 URL 上调用 openConnection 方法创建连接对象。
2.处理设置参数和一般请求属性。
3.使用 connect 方法建立到远程对象的实际连接。
4.远程对象变为可用。远程对象的头字段和内容变为可访问。
使用以下方法修改设置参数:
setAllowUserInteraction
setDoInput
setDoOutput
setIfModifiedSince
setUseCaches
使用以下方法修改一般请求属性:
setRequestProperty
使用 setDefaultAllowUserInteraction 和 setDefaultUseCaches 可设置 AllowUserInteraction 和 UseCaches 参数的默认值。
上面每个 set 方法都有一个用于获取参数值或一般请求属性值的对应 get 方法。适用的具体参数和一般请求属性取决于协议。
在建立到远程对象的连接后,以下方法用于访问头字段和内容:
getContent
getHeaderField
getInputStream
getOutputStream
某些头字段需要经常访问。以下方法:
getContentEncoding
getContentLength
getContentType
getDate
getExpiration
getLastModifed
提供对这些字段的便捷访问。getContent 方法使用 getContentType 方法以确定远程对象类型;子类重写 getContentType 方法很容易。
我们来具体分析几个函数:
URL.openConnection():返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。
在这里运用openConnection()dedaoURL后,应把其转为HttpUrlConnection对象,以便运用到HttpUrlConnection的API。
注意,我们在connection的时候,实际值创建了一个tcp链接,并没有实际发送http请求。真正的http请求是在getInputStream的时候发送。注意getOutputSteream必须在getInputStream之后执行,而且在执行getOutPUtStream时会隐式的调用connect方法。注意,我们向后台传递数据是以流的方式。所以解码和编码格式用格外注意。我们将数据传递之前将数据解码变成以比特流的方式传给后台,后台必须用相同的方式重新编码,才能得到原来的编码格式,否则很容易出现乱码。
然后我们需要注意的是getOutPutStream是向后台传入数据,getInputStream是接收response响应给我们的数据,所以我们传递数据也一定要以单字节的方式传递。
的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。
package wangcc.servlet;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class TestConnectionServlet
*/
@WebServlet("/TestConnectionServlet")
public class TestConnectionServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
public TestConnectionServlet() {
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
this.doGet(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
InputStream in=request.getInputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(in,"GBK"));
String line=null;
StringBuffer sb=new StringBuffer();
while((line=reader.readLine())!=null)
{
sb.append(line);
}
reader.close();
String returnStr=sb.toString();
returnStr=returnStr.substring(0, 5);
OutputStream out=response.getOutputStream();
out.write(returnStr.getBytes("GBK"));
}
}