import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.io.PrintWriter;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* get请求获取数据
*/
public static String getJson(String httpUrl, String httpArg) {
BufferedReader reader = null;
String result = null;
StringBuffer sbf = new StringBuffer();
httpUrl = httpUrl + "?" + httpArg;
try {
URL url = new URL(httpUrl);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("GET");
/**setRequestProperty(key,value)
* Sets the general request property. If a property with the key already
* exists, overwrite its value with the new value.
* 设置通用的请求属性。如果该key对应的的属性值已经存在,那么新值将覆盖以前的值
* <p> NOTE: HTTP requires all request properties which can
* legally have multiple instances with the same key
* to use a comma-seperated list syntax which enables multiple
* properties to be appended into a single property.
*提示:HTTP要求拥有相同key值的多个实例的所有请求属性,可以使用逗号分隔的列表语法,这样就可以将多个属性附加到单个属性中
* @param key the keyword by which the request is known
* (e.g., "<code>Accept</code>").
* @param value the value associated with it.
* @throws IllegalStateException if already connected
* @throws NullPointerException if key is <CODE>null</CODE>
* @see #getRequestProperty(java.lang.String)
*/
connection.setRequestProperty("apikey", "71e4b699*********cf44ebb02cd2");
connection.connect();
InputStream is = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String strRead = null;
while ((strRead = reader.readLine()) != null) {
sbf.append(strRead);
sbf.append("\r\n");
}
reader.close();
result = sbf.toString();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* POST请求获取数据
*/
public static String postDownloadJson(String path,String post){
URL url = null;
try {
url = new URL(path);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("POST");// 提交模式
// conn.setConnectTimeout(10000);//连接超时 单位毫秒
// conn.setReadTimeout(2000);//读取超时 单位毫秒
// 发送POST请求必须设置如下两行
httpURLConnection.setDoOutput(true);//http正文内,因此需要设为true, 默认情况下是false;
httpURLConnection.setDoInput(true);// 设置是否从httpUrlConnection读入,默认情况下是true;
// 获取URLConnection对象对应的输出流 此处getOutputStream会隐含的进行connect(即:如同调用上面的connect()方法,
PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
// 发送请求参数
printWriter.write(post);//post的参数 xx=xx&yy=yy
// flush输出流的缓冲
printWriter.flush();
//开始获取数据 将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端
BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream());//实际发送请求的代码段就在这里
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int len;
byte[] arr = new byte[1024];
while((len=bis.read(arr))!= -1){
bos.write(arr,0,len);
bos.flush();
}
bos.close();
return bos.toString("utf-8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
总结:a:) HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。
无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。
b:) 在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重,
对connection对象的一切配置(那一堆set函数)
都必须要在connect()函数执行之前完成。而对outputStream的写操作,又必须要在inputStream的读操作之前。
这些顺序实际上是由http请求的格式决定的。
如果inputStream读操作在outputStream的写操作之前,会抛出例外:
java.net.ProtocolException: Cannot write output after reading input.......
c:) http请求实际上由两部分组成,
一个是http头,所有关于此次http请求的配置都在http头里面定义,
一个是正文content。
connect()函数会根据HttpURLConnection对象的配置值生成http头部信息,因此在调用connect函数之前, 就必须把所有的配置准备好。
d:) 在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的,
实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络, 而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。 至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求 正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于http 请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数 之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改) 都是没有意义的了,执行这些操作会导致异常的发生。