1. 利用URLConnection发送GET和POST请求:
1) 其实不管是发送GET还是POST请求都需要一些必不可少的步骤,这些步骤不外乎:
i. 构造URL对象;
ii. 用URL对象打开一个连接句柄conn;
iii. 在实际发送请求之前先对conn的请求属性进行设置(setProperty等);
iv. 发送请求;
2) 当然在上一个例子中我们显式使用了URLConnection.setRequestedMethod指定了请求方法,但实际中GET和POST请求都有自己的默认请求方式;
3) GET方法在第iv.步默认使用URLConnection.connect方法发送请求(表示请求连接URL中所指定的资源或服务);
4) POST方法在第iii.步默认用setDoOutput和setDoInput方法设置请求属性(都传true),表示后面的请求都是用POST方式发送的;
!!注意:由于POST请求要求请求参数放在请求体中而不是URL中,因此如果请求是包含请求参数的,就必须通过URLConnection的getOutputStream获得输出流,然后将请求参数加入输出流中输出给服务器才行,得到的OutputStream就是用来向请求体中写额外数据的;
5) 示例:
public class Test {
public static URLConnection getConnection(String s) throws IOException {
URL url = new URL(s);
URLConnection conn = url.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
return conn;
}
public static String reqGet(String s, String param) throws IOException {
String res = "";
URLConnection conn = getConnection(s + "?" + param); // GET要求请求参数写在URL末尾,中间用?隔开
conn.connect(); // GET方法默认用connect发送连接请求
Map<String, List<String>> map = conn.getHeaderFields(); // 得到响应标头的所有属性键值
for (String key : map.keySet()) { // 遍历打印
System.out.println(key + "---->" + map.get(key));
}
try ( // 正常的请求(获取资源的请求)
BufferedReader in = new BufferedReader( // 用BufferedReader包装响应得到的数据
new InputStreamReader(conn.getInputStream(), "utf-8"))
) {
String line;
while ((line = in.readLine()) != null) { // 一行行读取(由于读取的都是文本文件:JSP文件)
res += line + "\n";
}
} catch (Exception e) {
System.out.println("Get Error Occured!");
e.printStackTrace();
}
return res;
}
public static String reqPost(String s, String param) throws IOException {
String res = "";
URLConnection conn = getConnection(s); // POST要求URL中不包含请求参数
conn.setDoOutput(true); // 必须设置这两个请求属性为true,就表示默认使用POST发送请求
conn.setDoInput(true);
// 请求参数必须使用conn获取的OutputStream输出到请求体中
PrintWriter out = new PrintWriter(conn.getOutputStream()); // 用PrintWriter进行包装
out.println(param);
out.flush(); // 立即充刷至请求体)PrintWriter默认先写在内存缓存中
try ( // 发送正常的请求(获取资源)
BufferedReader in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "utf-8"))
) {
String line;
while ((line = in.readLine()) != null) {
res += line + "\n";
}
} catch (Exception e) {
System.out.println("Get Error Occured!");
e.printStackTrace();
}
return res;
}
public static void main(String[] args) throws IOException {
String res = "";
res = Test.reqGet("http://localhost:8888/abc/a.jsp", null);
System.out.println(res);
res = Test.reqPost("http://localhost:8888/abc/login.jsp", "name=Peter&pass=leegang");
System.out.println(res);
}
}
!!请求的资源必须要部署在服务器上,服务器应用需要使用Apache等软件进行部署,这里先不管,就先理解代码即可;
!!!注意:在使用POST时,一定要在获取输入流(得到响应结果)之前使用conn的输出流往标头中写入请求参数,否则会导致异常发生(设置请求参数永远在获取数据之前进行);
2. URLConnection中用于设置请求属性的方法:
》》通用属性:基本所有版本的网络通信都需要用到的属性(属性的键都是固定(通用的,约定好的))
1) void setAllowUserInteraction(boolean allowuserinteraction); // 设置Allow User Interaction字段
2) void setIfModifiedSince(long ifmodifiedsince); // 设置if modified since字段
3) void setUseCaches(boolean usecaches); // 设置use caches字段
!!使用POST方法必须设置的两个字段(都设置为true):
4) void setDoOutput(boolean dooutput);
5) void setDoInput(boolean doinput);
》》自定义属性:根据服务器应用或者其它需求而有所不同的属性
6) void setRequestProperty(String key, String value); // 自定义属性的键值
7) void addRequestProperty(String key, String value); // 允许一个键拥有多个值,该方法就是为一个键添加额外的值(追加在后面),如果key原本不存在就创建该键(和set方法一样了)
3. URLConnection中获取和响应有关的信息:只要以get开头的方法都是获取响应数据的
1) Object getContent(); // 获取连接本身的内容
2) String getHeaderField(String key); // 获得响应标头中的属性的值,给的是键返回的是值
3) Map<String,List<String>> getHeaderFields(); // 获取响应标头中所有的键值(表),有些键有多个值,因此值是String的列表
4) InputStream getInputStream(); // 获取资源(但是在远程服务器上),以本地输入流的形式展现,在本地可以用InputStreamReader+BufferedReader包装,用纯Java的方式处理
5) OutputStream getOutputStream(); // 获取请求体的输出流(向请求体中写数据),用于POST方法中向请求体中请求参数,可以使用PrintWriter进行包装,用纯Java的方式处理
!!考虑到有些响应属性的值会频繁使用,Java提供了如下方法可以快速获取这些响应属性的值:
6) String getContentEncoding(); // Content Encoding字段
7) int getContentLength(); // Content length字段
8) String getContentType();
9) long getDate();
10) long getExpiration(); // expires字段
11) long getLastModified();