提交表单数据

在向Web服务器发送信息时,通常有两个命令会被用到:GET和POST。

在使用GET命令时,只需将参数附在URL的结尾处即可。格式如下

1
http://host/script?parameters

其中每个参数都具有“名字=值”的形式,而且这些参数之间用&字符分隔开。参数的值遵循以下规则。使用URL编码模式进行编码

  • 保留字符A-Z、a-z、1-9以及. - * _
  • 用+字符替换所有的空格。
  • 将其他所有字符编码为UTF-8,并将每个字节都编码为%后面紧跟一个两位的十六进制数字。例如,若要发送街道名S. Main, 可以使用S%2e+Main,因为十六进制数2e是“.”的ASCII码值

使用POST命令时,并不需要在URL中添加任何参数,而是从URLConnection中获取输出流并将名-值对写入该流中。当然,仍然需要对这些值进行编码,并用&字符将它们隔开。过程如下

1
2
3
4
5
6
7
8
9
10
11
URL url= new URL("http://host/script");
URLConnection connection=url.openConnection();
connection.setDoOutput("true");
//设置可输出
PrintWriter out = new PrintWriter(connection.getOutputStream());
//得到输出流
out.print(name1+"="+URLEncoder.encode(value1,"UTF-8")+"&");
out.print(name2+"="+URLEncoder.encode(value2,"UTF-8"));
//发送数据
out.close();
//关闭输出流

最后,调用getInputStream方法读取服务器的响应,在读取响应的过程中有个问题,若脚本运行出现错误,那么connection.getInputStream()时就会抛出一个FileNotFoundException异常,但是此时服务器依然会向浏览器发送一个错误页面。为了捕获该异常,可以将URLConnection对象转型为HTTPURLConnection类并调用它的getErrorStream方法

1
InputStream err = ((HttpURLConnection)connection).getErrorStream()

URLConnection对象首先向服务器发送了一个请求头,当提交表单数据时,请求头必须包含:

1
Content-Type: application/x-www-form-urlencoded

而POST的请求头还必须包括内容的长度

1
Content-Length: 124

请求头必须以空白行结尾,紧跟其后的才是数据部分

示例程序如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;

/**
* This program demonstrates how to use the URLConnection class for a POST request.
* @version 1.20 2007-06-25
* @author Cay Horstmann
*/
public class PostTest
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new PostTestFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}

class PostTestFrame extends JFrame
{
/**
* Makes a POST request and returns the server response.
* @param urlString the URL to post to
* @param nameValuePairs a map of name/value pairs to supply in the request.
* @return the server reply (either from the input stream or the error stream)
*/
public static String doPost(String urlString, Map<String, String> nameValuePairs)
throws IOException
{
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);

PrintWriter out = new PrintWriter(connection.getOutputStream());

boolean first = true;
for (Map.Entry<String, String> pair : nameValuePairs.entrySet())
{
if (first) first = false;
else out.print('&');
String name = pair.getKey();
String value = pair.getValue();
out.print(name);
out.print('=');
out.print(URLEncoder.encode(value, "UTF-8"));
}

out.close();

Scanner in;
StringBuilder response = new StringBuilder();
try
{
in = new Scanner(connection.getInputStream());
}
catch (IOException e)
{
if (!(connection instanceof HttpURLConnection)) throw e;
InputStream err = ((HttpURLConnection) connection).getErrorStream();
if (err == null) throw e;
in = new Scanner(err);
}

while (in.hasNextLine())
{
response.append(in.nextLine());
response.append("\n");
}

in.close();
return response.toString();
}

public PostTestFrame()
{
setTitle("PostTest");

northPanel = new JPanel();
add(northPanel, BorderLayout.NORTH);
northPanel.setLayout(new GridLayout(0, 2));
northPanel.add(new JLabel("Host: ", SwingConstants.TRAILING));
final JTextField hostField = new JTextField();
northPanel.add(hostField);
northPanel.add(new JLabel("Action: ", SwingConstants.TRAILING));
final JTextField actionField = new JTextField();
northPanel.add(actionField);
for (int i = 1; i <= 8; i++)
northPanel.add(new JTextField());

final JTextArea result = new JTextArea(20, 40);
add(new JScrollPane(result));

JPanel southPanel = new JPanel();
add(southPanel, BorderLayout.SOUTH);
JButton addButton = new JButton("More");
southPanel.add(addButton);
addButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
northPanel.add(new JTextField());
northPanel.add(new JTextField());
pack();
}
});

JButton getButton = new JButton("Get");
southPanel.add(getButton);
getButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
result.setText("");
final Map<String, String> post = new HashMap<String, String>();
for (int i = 4; i < northPanel.getComponentCount(); i += 2)
{
String name = ((JTextField) northPanel.getComponent(i)).getText();
if (name.length() > 0)
{
String value = ((JTextField) northPanel.getComponent(i + 1)).getText();
post.put(name, value);
}
}
new SwingWorker<Void, Void>()
{
protected Void doInBackground() throws Exception
{
try
{
String urlString = hostField.getText() + "/" + actionField.getText();
result.setText(doPost(urlString, post));
}
catch (IOException e)
{
result.setText("" + e);
}
return null;
}
}.execute();
}
});

pack();
}

private JPanel northPanel;
}
Donate comment here