package com.hyf.base.connection;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Vector;
/**
* <br>
* description: HttpURLConnection学习
* </br>
* DateTime: 2012-2-16 上午11:18:03
*
* @author haoyf
* @version 1.0
*/
public class HttpConnect {
/**
* 1.打开一个连接
* 2.设置属性和头部信息
* 3.连接实际连接
* 4.访问
*/
private HttpURLConnection httpConn;
private InputStream in;
private OutputStream out;
/**
* <br>
* description: 初始化
* </br>
* @param connectURL
* URL连接地址
* @throws MalformedURLException
* @throws IOException
*/
public HttpConnect(String connectURL) throws MalformedURLException, IOException {
httpConn = (HttpURLConnection) new URL(connectURL).openConnection(); //打开一个新的连接
httpConn.setRequestMethod("POST"); //设置请求方式
httpConn.setDoInput(true); //设置true:应用程序要从URL连接读取数据
httpConn.setDoOutput(true); //设置true:应用程序将数据写入URL连接
httpConn.setRequestProperty("Content-Type", "text/html"); //设置头信息,拥有多个具有相同键的实例的请求属性,使用以逗号分隔的列表语法,这样可实现将多个属性添加到一个属性中
httpConn.setConnectTimeout(2*60*1000); //连接超时,以毫秒不单位
}
/**
* <br>
* description: 初始化
* </br>
* @param connectUrl
* URL连接地址
* @param method
* 请求方式
* @throws MalformedURLException
* @throws IOException
*/
public HttpConnect(String connectUrl, String method) throws MalformedURLException, IOException {
httpConn = (HttpURLConnection) new URL(connectUrl).openConnection();
httpConn.setRequestMethod(method);
httpConn.setDoInput(true);
httpConn.setDoOutput(true);
}
/**
* <br>
* description: 设置头部
* </br>
* @param key
* 请求的关键字
* @param value
* 该键关联的值
*/
public void setHeader(String key, String value) {
httpConn.setRequestProperty(key, value);
}
/**
* <br>
* description: 向URL发送数据
* </br>
* @param data
* 发送的数据
* @throws IOException
*/
public void SendData(String data) throws IOException {
byte[] f = data.getBytes("UTF-8");
out = httpConn.getOutputStream(); //getOutputStream()方法,自动调用connect()连接方法
out.write(f, 0, f.length);
out.flush();
out.close();
}
/**
* <br>
* description: 收到的数据
* </br>
* @return
* String
* @throws IOException
*/
public String ReceiveData() throws IOException {
in = new DataInputStream(httpConn.getInputStream());
StringBuffer reMsg = new StringBuffer();
int ch;
while ((ch = in.read()) != -1) {
reMsg.append((char) ch);
}
String ret = reMsg.toString();
return ret;
}
/**
* <br>
* description: 释放连接
* </br>
*/
public void releaseHttpConnect() {
try {
if (httpConn != null) {
httpConn.disconnect();
}
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* <br>
* description: 读取UTF数据
* </br>
* String
* @return
* @throws IOException
*/
public String ReceiveUTFString() throws IOException {
in = new DataInputStream(httpConn.getInputStream());
Vector<byte[]> bufLst = new Vector<byte[]>();
int len = 0;
while (true) {
byte[] buf = new byte[256];
int l = in.read(buf, 1, 255);
if (l == -1) {
break;
}
buf[0] = (byte) ((byte) l & 0xFF);
len += (int) buf[0] & 0xFF;
bufLst.add(buf);
}
byte[] bigBuf = new byte[len];
int off = 0;
for (int i = 0; i < bufLst.size(); i++) {
System.arraycopy(bufLst.get(i), 1, bigBuf, off,
(int) bufLst.get(i)[0] & 0xFF);
off += (int) bufLst.get(i)[0] & 0xFF;
}
String ret = new String(bigBuf, "UTF-8");
return ret;
}
/**
* <br>
* description: 根据编码获取数据
* </br>
* @param encoding
* 编码方式
* @return
* String
*/
public String receiveByEncode(String encoding) {
DataInputStream in;
try {
in = new DataInputStream(httpConn.getInputStream());
InputStreamReader inread = new InputStreamReader(in, encoding);
StringBuffer reMsg = new StringBuffer();
int ch;
while ((ch = inread.read()) != -1) {
reMsg.append((char) ch);
}
String ret = reMsg.toString();
return ret;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/*****************流的附加方法**********************************/
/**
* <br>
* description: 将UTF-8byte转换成String
* </br>
* @param rec
* byte
* @return
*/
public String BytesToString(byte[] rec) {
ByteArrayInputStream bais = new ByteArrayInputStream(rec);
DataInputStream dis = new DataInputStream(bais);
String BTS = null;
try {
BTS = new String(rec, "UTF-8");
bais.close();
dis.close();
} catch (Exception e) {
e.printStackTrace();
}
return BTS;
}
/**
* <br>
* description: 数据流拷贝
* </br>
* @param in
* 输入流
* @param out
* 输出流
* @throws IOException
*/
private void copy(InputStream in, OutputStream out) throws IOException {
try {
byte[] buffer = new byte[4096];
int nrOfBytes = -1;
while ((nrOfBytes = in.read(buffer)) != -1) {
out.write(buffer, 0, nrOfBytes);
}
out.flush();
} catch (IOException e) {
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
}
try {
if (out != null) {
out.close();
}
} catch (IOException ex) {
}
}
}
/**
* <br>
* description: 读取文件数据
* @param fileName
* 文件名
* @return
* byte
*/
public byte[] getFileByte(String fileName) {
InputStream fileInputStream = getClass().getResourceAsStream(fileName);
return getFileByte(fileInputStream);
}
/**
* <br>
* description: 读取文件数据
* </br>
* @param fileName
* 文件名
* @return
* String
*/
public String getFileString(String fileName) {
InputStream fileInputStream = getClass().getResourceAsStream(fileName);
return getFileString(fileInputStream);
}
/**
* <br>
* description: 读取文件数据
* </br>
* @param in
* 输入流
* @return
* String
*/
public String getFileString(InputStream in) {
ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
try {
copy(in, out);
} catch (IOException e) {
e.printStackTrace();
}
return out.toString();
}
/**
* <br>
* description: 读取文件数据
* </br>
* @param in
* 输入流
* @return
* byte
*/
public byte[] getFileByte(InputStream in) {
ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
try {
copy(in, out);
} catch (IOException e) {
e.printStackTrace();
}
return out.toByteArray();
}
}
1. HttpURLConnection 的connect ()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。
无论是post还是get,http请求实际上直到HttpURLConnection 的getInputStream()这个函数里面才正式发送出去。
2. 在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重,
对connection对象的一切配置(那一堆set函数)
都必须要在connect ()函数执行之前完成。而对outputStream的写操作,又必须要在inputStream的读操作之前。
这些顺序实际上是由http请求的格式决定的。
如果inputStream读操作在outputStream的写操作之前,会抛出例外:
java.net.ProtocolException: Cannot write output after reading input.......
3. http请求实际上由两部分组成,
一个是http头,所有关于此次http请求的配置都在http头里面定义, 一个是正文content。
connect ()函数会根据HttpURLConnection 对象的配置值生成http头部信息,因此在调用connect 函数之前,
就必须把所有的配置准备好。
4. 在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的,
实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,
而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。
至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求
正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于http
请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数
之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改)
都是没有意义的了,执行这些操作会导致异常的发生。