我成功地使用这段代码通过GET方法发送带有一些参数的HTTP请求
void sendRequest(String request)
{
// i.e.: request = "http://example.com/index.php?param1=a¶m2=b¶m3=c";
URL url = new URL(request);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "text/plain");
connection.setRequestProperty("charset", "utf-8");
connection.connect();
}
现在我可能需要通过POST方法发送参数(即param1, param2, param3),因为它们非常长。
我想添加一个额外的参数,该方法(即字符串httpMethod)。
我怎样才能尽可能少地更改上面的代码,以便能够通过GET或POST发送参数?
我希望情况会有所改变
connection.setRequestMethod("GET");
to
connection.setRequestMethod("POST");
可以完成这个任务,但是参数仍然通过GET方法发送。
HttpURLConnection有任何方法可以帮助吗?
有什么有用的Java构造吗?
任何帮助都将不胜感激。
现在我要做一个HTTP请求类,它可能不是最有效的类,但它可以工作。
我从这个页面中收集了一些代码,并使其更加动态。
任何需要完整代码的人,我在下面附上了它。
关于如何使用它的示例,您可以查看main方法。
此外,如果你愿意改进在线课程,非常欢迎你来帮助我使这门课变得更好。
import java.net.*;
import java.util.*;
import java.nio.charset.*;
import java.io.*;
public class HttpRequest {
String result = "";
HttpRequest(String _url, String _method, Map<String, String> _postData, String _contentType) {
try {
URL url = new URL( _url );
URLConnection con = url.openConnection();
HttpURLConnection http = (HttpURLConnection)con;
http.setRequestMethod(_method); // PUT is another valid option
http.setDoOutput(true);
StringJoiner sj = new StringJoiner("&");
for(Map.Entry<String,String> entry : _postData.entrySet())
sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + entry.getValue());
//sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue()));
byte[] out = sj.toString().getBytes(StandardCharsets.UTF_8);
int length = out.length;
http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", _contentType);
http.setRequestProperty( "charset", "utf-8");
http.setRequestProperty( "Content-Length", Integer.toString( length ));
http.setInstanceFollowRedirects( false );
http.setUseCaches( false );
http.connect();
try(OutputStream os = http.getOutputStream()) {
os.write(out);
}
if (http.getResponseCode() == HttpURLConnection.HTTP_OK) {
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(http.getInputStream()))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
result = result + line;
}
}
} else {
System.out.println("Bad response!");
}
}catch (IOException e) {
// writing exception to log
e.printStackTrace();
}
}
HttpRequest(String _url, String _method, Map<String, String> _postData) {
this(_url, _method, _postData, "text/html");
}
HttpRequest(String _url, String _method) {
this(_url, _method, new HashMap<String, String>());
}
HttpRequest(String _url) {
this(_url, "GET");
}
public String toString() {
return result;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Map<String, String> postData = new HashMap<String, String>();
postData.putIfAbsent("email", "test@test.com");
postData.putIfAbsent("password", "test");
HttpRequest result = new HttpRequest("https://httpbin.org/anything", "POST", postData, "application/x-www-form-urlencoded");
System.out.println(result.toString());
}
}
我用Boann的答案创建了一个更灵活的查询字符串构建器,支持列表和数组,就像php的http_build_query方法一样:
public static byte[] httpBuildQueryString(Map<String, Object> postsData) throws UnsupportedEncodingException {
StringBuilder postData = new StringBuilder();
for (Map.Entry<String,Object> param : postsData.entrySet()) {
if (postData.length() != 0) postData.append('&');
Object value = param.getValue();
String key = param.getKey();
if(value instanceof Object[] || value instanceof List<?>)
{
int size = value instanceof Object[] ? ((Object[])value).length : ((List<?>)value).size();
for(int i = 0; i < size; i++)
{
Object val = value instanceof Object[] ? ((Object[])value)[i] : ((List<?>)value).get(i);
if(i>0) postData.append('&');
postData.append(URLEncoder.encode(key + "[" + i + "]", "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(val), "UTF-8"));
}
}
else
{
postData.append(URLEncoder.encode(key, "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(value), "UTF-8"));
}
}
return postData.toString().getBytes("UTF-8");
}
对于那些使用$_POST在php页面上接收请求的问题,因为你期望键值对:
虽然所有的答案都很有帮助,但我对实际发布哪个字符串缺乏一些基本的了解,因为在我使用的旧apache HttpClient中
new UrlEncodedFormEntity(nameValuePairs); (Java)
然后可以在php中使用$_POST获取键值对。
据我的理解,现在已经在发布之前手动构建该字符串。所以字符串应该是这样的
val data = "key1=val1&key2=val2"
而是只是把它添加到它被张贴的url(在头)。
另一种方法是使用json-string:
val data = "{\"key1\":\"val1\",\"key2\":\"val2\"}" // {"key1":"val1","key2":"val2"}
然后把它拉到php中,不需要$_POST:
$json_params = file_get_contents('php://input');
// echo_p("Data: $json_params");
$data = json_decode($json_params, true);
下面是Kotlin中的示例代码:
class TaskDownloadTest : AsyncTask<Void, Void, Void>() {
override fun doInBackground(vararg params: Void): Void? {
var urlConnection: HttpURLConnection? = null
try {
val postData = JsonObject()
postData.addProperty("key1", "val1")
postData.addProperty("key2", "val2")
// reformat json to key1=value1&key2=value2
// keeping json because I may change the php part to interpret json requests, could be a HashMap instead
val keys = postData.keySet()
var request = ""
keys.forEach { key ->
// Log.i("data", key)
request += "$key=${postData.get(key)}&"
}
request = request.replace("\"", "").removeSuffix("&")
val requestLength = request.toByteArray().size
// Warning in Android 9 you need to add a line in the application part of the manifest: android:usesCleartextTraffic="true"
// https://stackoverflow.com/questions/45940861/android-8-cleartext-http-traffic-not-permitted
val url = URL("http://10.0.2.2/getdata.php")
urlConnection = url.openConnection() as HttpURLConnection
// urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded") // apparently default
// Not sure what these are for, I do not use them
// urlConnection.setRequestProperty("Content-Type", "application/json")
// urlConnection.setRequestProperty("Key","Value")
urlConnection.readTimeout = 5000
urlConnection.connectTimeout = 5000
urlConnection.requestMethod = "POST"
urlConnection.doOutput = true
// urlConnection.doInput = true
urlConnection.useCaches = false
urlConnection.setFixedLengthStreamingMode(requestLength)
// urlConnection.setChunkedStreamingMode(0) // if you do not want to handle request length which is fine for small requests
val out = urlConnection.outputStream
val writer = BufferedWriter(
OutputStreamWriter(
out, "UTF-8"
)
)
writer.write(request)
// writer.write("{\"key1\":\"val1\",\"key2\":\"val2\"}") // {"key1":"val1","key2":"val2"} JsonFormat or just postData.toString() for $json_params=file_get_contents('php://input'); json_decode($json_params, true); in php
// writer.write("key1=val1&key2=val2") // key=value format for $_POST in php
writer.flush()
writer.close()
out.close()
val code = urlConnection.responseCode
if (code != 200) {
throw IOException("Invalid response from server: $code")
}
val rd = BufferedReader(
InputStreamReader(
urlConnection.inputStream
)
)
var line = rd.readLine()
while (line != null) {
Log.i("data", line)
line = rd.readLine()
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
urlConnection?.disconnect()
}
return null
}
}
我也有同样的问题。我想通过POST发送数据。
我使用了以下代码:
URL url = new URL("http://example.com/getval.php");
Map<String,Object> params = new LinkedHashMap<>();
params.put("param1", param1);
params.put("param2", param2);
StringBuilder postData = new StringBuilder();
for (Map.Entry<String,Object> param : params.entrySet()) {
if (postData.length() != 0) postData.append('&');
postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
String urlParameters = postData.toString();
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(urlParameters);
writer.flush();
String result = "";
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = reader.readLine()) != null) {
result += line;
}
writer.close();
reader.close()
System.out.println(result);
我使用Jsoup进行解析:
Document doc = Jsoup.parseBodyFragment(value);
Iterator<Element> opts = doc.select("option").iterator();
for (;opts.hasNext();) {
Element item = opts.next();
if (item.hasAttr("value")) {
System.out.println(item.attr("value"));
}
}