這篇也是接上一篇猬错,發(fā)送請求的url就是前面創(chuàng)建的java web工程中有的饥漫。
1犀变、HTTP中GET和POST的區(qū)別
首先要了解下GET和POST的區(qū)別妹孙。
HTTP定義了4種與服務(wù)器交互方法:GET,POST获枝,PUT蠢正,DELETE。URL全稱是資源描述符映琳,可以這樣認為:一個URL地址机隙,它用于描述一個網(wǎng)絡(luò)上的資源蜘拉,而HTTP中的GET萨西,POST,PUT旭旭,DELETE可以理解為就對應(yīng)著對這個資源的查谎脯,改,增持寄,刪4個操作源梭。GET一般用于獲取/查詢資源信息,而POST一般用于更新資源信息稍味。GET和POST的區(qū)別主要從以下幾個方面理解:
- 用途
根據(jù)HTTP規(guī)范废麻,GET用于信息獲取,用于獲取信息而非修改信息模庐。GET請求一般不應(yīng)產(chǎn)生副作用烛愧。它僅僅是獲取資源信息,就像數(shù)據(jù)庫查詢一樣,不會修改怜姿,增加數(shù)據(jù)慎冤,不會影響資源的狀態(tài)。對同一URL的多個請求應(yīng)該返回同樣的結(jié)果沧卢。 POST可能修改變服務(wù)器上的資源的請求蚁堤。 - 請求數(shù)據(jù)的傳遞方式
GET請求的數(shù)據(jù)會附在URL之后(就是把數(shù)據(jù)放置在HTTP協(xié)議頭中),以?分割URL和傳輸數(shù)據(jù)但狭,參數(shù)之間以&相連披诗,如:buy.jsp?product=apple&amount=1111&verify=%E4%BD%A0%E5%A5%BD
。如果數(shù)據(jù)是英文字母或者數(shù)字立磁,原樣發(fā)送藤巢,如果是空格,轉(zhuǎn)換為+
息罗,如果是中文或者其他字符掂咒,則直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD迈喉,其中%XX中的XX為該符號以16進制表示的ASCII绍刮。而POST把提交的數(shù)據(jù)則放置在是HTTP包的包體中。 - 提交數(shù)據(jù)的大小限制
GET方式提交的數(shù)據(jù)最多只能是1024字節(jié)(GET請求中參數(shù)是附在url后面的挨摸,實際上這個長度是url長度的要求)孩革。理論上POST沒有限制,可傳較大量的數(shù)據(jù)得运。這一點可以先簡單這么理解膝蜈。 - 安全性
POST的安全性要比GET的安全性高。比如熔掺,通過GET提交數(shù)據(jù)饱搏,用戶名和密碼將明文出現(xiàn)在URL上。 - 常見場景
在FORM表單中置逻,Method默認為"GET"推沸。在瀏覽器地址欄中輸入url發(fā)生請求都是GET,如果要發(fā)送POST請求就需要通過提交form表單來完成券坞。
2鬓催、Java代碼發(fā)送GET和POST請求
Java中應(yīng)該有好多種方式,可以發(fā)送GET和POST請求恨锚。這里介紹兩種:通過HttpURLConnection和通過Apache HttpClient庫宇驾。
2.1 通過HttpURLConnection發(fā)送GET和POST請求
這種方式基本上算是java原生的,不需要導入任何jar包依賴就可以運行猴伶。代碼如下:
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by chengxia on 2018/12/4.
*/
public class HttpURLConnectionDemo {
public String doPost(String URL){
OutputStreamWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
HttpURLConnection conn = null;
try{
URL url = new URL(URL);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
//發(fā)送POST請求必須設(shè)置為true
conn.setDoOutput(true);
conn.setDoInput(true);
//設(shè)置連接超時時間和讀取超時時間
conn.setConnectTimeout(30000);
conn.setReadTimeout(10000);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
//獲取輸出流
out = new OutputStreamWriter(conn.getOutputStream());
String jsonStr = "{\"qry_by\":\"name\", \"name\":\"Tim\"}";
out.write(jsonStr);
out.flush();
out.close();
//取得輸入流课舍,并使用Reader讀取
if (200 == conn.getResponseCode()){
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null){
result.append(line);
System.out.println(line);
}
}else{
System.out.println("ResponseCode is an error code:" + conn.getResponseCode());
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(out != null){
out.close();
}
if(in != null){
in.close();
}
}catch (IOException ioe){
ioe.printStackTrace();
}
}
return result.toString();
}
public String doGet(String URL){
HttpURLConnection conn = null;
InputStream is = null;
BufferedReader br = null;
StringBuilder result = new StringBuilder();
try{
//創(chuàng)建遠程url連接對象
URL url = new URL(URL);
//通過遠程url連接對象打開一個連接菌瘫,強轉(zhuǎn)成HTTPURLConnection類
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
//設(shè)置連接超時時間和讀取超時時間
conn.setConnectTimeout(15000);
conn.setReadTimeout(60000);
conn.setRequestProperty("Accept", "application/json");
//發(fā)送請求
conn.connect();
//通過conn取得輸入流,并使用Reader讀取
if (200 == conn.getResponseCode()){
is = conn.getInputStream();
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String line;
while ((line = br.readLine()) != null){
result.append(line);
System.out.println(line);
}
}else{
System.out.println("ResponseCode is an error code:" + conn.getResponseCode());
}
}catch (MalformedURLException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(br != null){
br.close();
}
if(is != null){
is.close();
}
}catch (IOException ioe){
ioe.printStackTrace();
}
conn.disconnect();
}
return result.toString();
}
public static void main(String[] args) throws Exception {
HttpURLConnectionDemo http = new HttpURLConnectionDemo();
System.out.println("Testing 1 - Do Http GET request");
http.doGet("http://localhost:8080");
System.out.println("\nTesting 2 - Do Http POST request");
http.doPost("http://localhost:8080/json");
}
}
運行的輸出如下:
Testing 1 - Do Http GET request
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Hello Word!</h1>
</body>
</html>
Testing 2 - Do Http POST request
[{name:'Kobe', team:‘Lakers’},{name:'Tim', team:‘Spurs’}]
Process finished with exit code 0
從這個例子的代碼中就可以看出布卡,GET請求向服務(wù)器發(fā)送的數(shù)據(jù)雨让,都放在url中,這樣在發(fā)送請求是不用向請求正文中寫入數(shù)據(jù)忿等。而POST請求在發(fā)送時栖忠,必須先將發(fā)送的數(shù)據(jù),寫入到請求正文中贸街。下面的apache httpclient實現(xiàn)中庵寞,也能看出這個區(qū)別。
2.2 通過Apache HttpClient發(fā)送GET和POST請求
這里需要用到Apache HttpClient的依賴包薛匪,所以要先去官網(wǎng)下載依賴的jar包:
Apache官網(wǎng)下載依賴jar包
解壓之后捐川,將lib目錄下所有的jar包文件,導入到工程的依賴目錄(我曾經(jīng)天真的以為只需要一個
httpclient-4.5.6.jar
逸尖,然而在編譯時各種報錯古沥,全部導入到就好了):下載的jar包解壓之后
全部導入到工程的依賴目錄中
最后,Java代碼如下:
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
/**
* Created by chengxia on 2018/12/5.
*/
public class ApacheHttpClientDemo {
public String doGet(String url){
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
String result = "";
try{
//通過默認配置創(chuàng)建一個httpClient實例
httpClient = HttpClients.createDefault();
//創(chuàng)建httpGet遠程連接實例
HttpGet httpGet = new HttpGet(url);
//httpGet.addHeader("Connection", "keep-alive");
//設(shè)置請求頭信息
httpGet.addHeader("Accept", "application/json");
//配置請求參數(shù)
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(35000) //設(shè)置連接主機服務(wù)超時時間
.setConnectionRequestTimeout(35000)//設(shè)置請求超時時間
.setSocketTimeout(60000)//設(shè)置數(shù)據(jù)讀取超時時間
.build();
//為httpGet實例設(shè)置配置
httpGet.setConfig(requestConfig);
//執(zhí)行g(shù)et請求得到返回對象
response = httpClient.execute(httpGet);
//通過返回對象獲取返回數(shù)據(jù)
HttpEntity entity = response.getEntity();
//通過EntityUtils中的toString方法將結(jié)果轉(zhuǎn)換為字符串娇跟,后續(xù)根據(jù)需要處理對應(yīng)的reponse code
result = EntityUtils.toString(entity);
System.out.println(result);
}catch (ClientProtocolException e){
e.printStackTrace();
}catch (IOException ioe){
ioe.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}finally {
//關(guān)閉資源
if(response != null){
try {
response.close();
}catch (IOException ioe){
ioe.printStackTrace();
}
}
if(httpClient != null){
try{
httpClient.close();
}catch (IOException ioe){
ioe.printStackTrace();
}
}
}
return result;
}
public String doPost(String url){
//創(chuàng)建httpClient對象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String result = "";
try{
//創(chuàng)建http請求
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("Content-Type", "application/json");
//創(chuàng)建請求內(nèi)容
String jsonStr = "{\"qry_by\":\"name\", \"name\":\"Tim\"}";
StringEntity entity = new StringEntity(jsonStr);
httpPost.setEntity(entity);
response = httpClient.execute(httpPost);
result = EntityUtils.toString(response.getEntity(),"utf-8");
System.out.println(result);
}catch (Exception e){
e.printStackTrace();
}finally {
//關(guān)閉資源
if(response != null){
try {
response.close();
}catch (IOException ioe){
ioe.printStackTrace();
}
}
if(httpClient != null){
try{
httpClient.close();
}catch (IOException ioe){
ioe.printStackTrace();
}
}
}
return result;
}
public static void main(String[] args) throws Exception {
ApacheHttpClientDemo http = new ApacheHttpClientDemo();
System.out.println("Testing 1 - Do Http GET request");
http.doGet("http://localhost:8080");
System.out.println("\nTesting 2 - Do Http POST request");
http.doPost("http://localhost:8080/json");
}
}
由于是向相同的url發(fā)送請求岩齿,這個例子的輸出和前面的例子是一樣的。
參考
-
How to send HTTP request GET/POST in Java
分別介紹了Standard HttpURLConnection和Apache HttpClient library發(fā)送http請求的方法苞俘,有例子盹沈。 -
Java - sending HTTP parameters via POST method easily
這個鏈接中提到了get請求參數(shù)通過url傳遞,post通過正文傳遞吃谣。
In a GET request, the parameters are sent as part of the URL.
In a POST request, the parameters are sent as a body of the request, after the headers. - 淺談HTTP中Get與Post的區(qū)別
-
Java 通過HttpURLConnection Post方式提交json乞封,并從服務(wù)端返回json數(shù)據(jù)
一個通過HTTPURLconnection發(fā)送json數(shù)據(jù)的例子