先说说几个概念关键字HttpURLConnection,HttpClient,CloseableHttpClient。
在 JDK 的 java.net 包中已经提供了访问 HTTP 协议的基本功能:HttpURLConnection。但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。 HttpURLConnection是java的标准类,什么都没封装,用起来太原始,不方便,比如重访问的自定义,以及一些高级功能等。
HttpClient是个很不错的开源框架,封装了访问http的请求头,参数,内容体,响应等等, HttpClient模块用来提供高效的、最新的、功能丰富的支持 HTTP 协议工具包,并且它支持 HTTP 协议最新的版本和建议。使用HttpClient可以快速开发出功能强大的Http程序。
HttpClient就是一个增强版的HttpURLConnection,HttpURLConnection可以做的事情HttpClient全部可以做;HttpURLConnection没有提供的有些功能,HttpClient也提供了,但它只是关注于如何发送请求、接收响应,以及管理HTTP连接。
最后org.apache.http.impl.client.CloseableHttpClient它是一个抽象类,它实现了org.apahce.http.client.HttpClient接口。
一、HttpClient HttpPost
使用 httpclient 传递键值对
需要导入的包有
org.apache.httpcomponents
httpclient
4.3.5
public static String post(String url,List params) throws Exception{
CloseableHttpClient httpclient = HttpClients.createDefault();
String responseText = "";
CloseableHttpResponse httpResponse = null;
try {
HttpPost httppost = new HttpPost(url);
httppost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
httpResponse = httpclient.execute(httppost);
if(httpResponse.getStatusLine().getStatusCode()==200){
responseText = EntityUtils.toString(httpResponse.getEntity());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (httpResponse != null){
httpResponse.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return responseText;
}
使用样例String url = "http://yunpian.com/v1/sms/send.json";
List nameValuePairs = new ArrayList<>();
nameValuePairs.add(new BasicNameValuePair("apikey","xxx"));
nameValuePairs.add(new BasicNameValuePair("mobile",tel));
nameValuePairs.add(new BasicNameValuePair("text", text));
String response = HttpRequest.post(url, nameValuePairs);
直接传入二进制实体//byte[] data
httpPost.setEntity(new ByteArrayEntity(data, ContentType.APPLICATION_FORM_URLENCODED));
二、URLConnection 直接传入 post 实体内容的方式public static String sendPost(String url, String content) {
OutputStreamWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new OutputStreamWriter(conn.getOutputStream());
out.write(content);
out.flush();
out.close();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
if(result.lenght() > 0){
result += "\n" + line;
}
result += line;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
如果服务器端用 php 来接收echo file_get_contents("php://input");
echo "\n";
var_export($_POST);
发送这样的两个请求System.out.println(sendPost("http://localhost/3.php","a=1&b=2"));
System.out.println(sendPost("http://localhost/3.php","123"));
结果如下a=1&b=2
array (
'a' => '1',
'b' => '2',
)
123
array (
)
第二种方式用$_POST方式是接收不到的,这也是与第一种以键值对的形式发送的区别。
三、从文件读取数据 POST
主要是FileInputStream的使用,对得到的数据content是采用键值对的形式还是直接放入 http 实体,取决于服务器的接收方式了。//文件的读取
String content = "";
try {
FileInputStream fileInputStream = new FileInputStream(new File("./test.log"));
byte[] b = new byte[fileInputStream.available()];
fileInputStream.read(b);
fileInputStream.close();
content = new String(b,"UTF-8");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
顺便记录下文件的写入//文件的写入
try {
FileOutputStream fileOutputStream = new FileOutputStream(new File("./test.log"));
fileOutputStream.write(content.getBytes());
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
四、二进制安全流方式的 POST
三方法中把byte转成String的时候,不传如字符编码,也会默认带有编码。实际测试发现在把byte转成String编码时,是不安全的,数据会被篡改。
OutputStream默认是支持write byte[]的。public void write(byte b[]) throws IOException {
write(b, 0, b.length);
}public static String post(String url, byte[] content) {
OutputStream out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setDoOutput(true);
conn.setDoInput(true);
out = conn.getOutputStream();
out.write(content);
out.flush();
out.close();
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
if (result.length() > 0){
result += "\n" + line;
}
result += line;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
直接从文件读取二进制数据public static String post(String url, File file) {
FileInputStream stream = null;
try {
stream = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
DataOutputStream out = null;
BufferedReader in = null;
String result = "";
byte b[] = new byte[1024];
try {
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setDoOutput(true);
conn.setDoInput(true);
out = new DataOutputStream(conn.getOutputStream());
int len = 0;
while ((len = stream.read(b)) != -1){
out.write(b, 0, len);
}
stream.close();
out.flush();
out.close();
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
if (result.length() > 0){
result += "\n" + line;
}
result += line;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
return result;
}