HTTP協議簡介
http(Hypertext transfer protocol)超文本傳輸協議,通過瀏覽器和服務器進行數據交互,進行超文本(文本、圖片、視頻等)傳輸的規定。也就是說,http協議規定了超文本傳輸所要遵守的規則。但HTTP協議的本質是一段在網絡環境中傳輸的文本,這段文本包含特定的格式。這些格式包括請求行,請求頭,請求體等等。
在http請求中比較常用的請求方法是get請求與post請求。
在java web中:
如果是get請求,參數需要拼接在URL的查詢字符串中才能被服務器端接收。
如果是post請求,在請求體與URL中的查詢字符串中攜帶的參數都可以被服務器端接收。
在發送get請求時,客戶端向服務器端傳遞的參數一般是通過URL中的查詢字符(querystring)串攜帶的,在請求體中的參數服務器端是接收不到的。在發送post請求時 ,查詢字符串與請求體中的參數都可以被接收到,我們寫一個Servlet來驗證一下tomcat是如何獲取get與post請求中的參數的。
get請求實驗
servlet代碼:
package com.haojie.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String queryString = req.getQueryString();
System.out.println("queryString="+queryString);
System.out.println("username="+req.getParameter("username"));
System.out.println("password="+req.getParameter("password"));
System.out.println("age="+req.getParameter("age"));
System.out.println("address="+req.getParameter("address"));
}
}
postman發送get請求
如上圖所示,用postman發送一個get請求,在查詢字符串中傳遞username與password這兩個參數,在請求體中攜帶age與address這兩個參數
servlet中 接收get請求參數結果
運行結果如上圖所示,在servlet中沒有獲取到請求體中傳遞的參數
通過socket接收get請求
我們通過自己寫的socket程序來接收postman發送的http請求,看看打印的http協議是怎么樣的。
package com.haojie.socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpListener {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
int port = 8080;
try {
serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
Socket clntSock = serverSocket.accept();
InputStream input = clntSock.getInputStream();
OutputStream output= clntSock.getOutputStream();
StringBuffer request = new StringBuffer(2048);
int i;
byte[] buffer = new byte[2048];
try {
i = input.read(buffer);
} catch (IOException e) {
e.printStackTrace();
i = -1;
}
for (int j = 0; j < i; j++) {
request.append((char) buffer[j]);
}
// 打印http協議內容
System.out.println(request);
// file not found
String errorMessage = "HTTP/1.1 200 success\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: 23\r\n" +
"\r\n" +
"<h1>success</h1>";
output.write(errorMessage.getBytes());
clntSock.close();
}
}
運行結果如下:
從上圖中我們可以看到,postman發送的http get請求,這個請求中的請求體與查詢參數傳遞的值傳遞到了服務器端。由此可以知道,http 協議的get請求的請求體也可以攜帶參數,只是tomcat在遇到get請求時沒有從請求體中取參數。
post請求實驗
代碼:
package com.haojie.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String queryString = req.getQueryString();
System.out.println("queryString="+queryString);
System.out.println("username="+req.getParameter("username"));
System.out.println("password="+req.getParameter("password"));
System.out.println("age="+req.getParameter("age"));
System.out.println("address="+req.getParameter("address"));
}
}
postman發送post請求
如上圖所示,通過postman發送post請求,在查詢字符串與請求體中都傳參
接收post請求結果
可以看到,在servlet中,通過查詢參數與請求體中傳遞的參數都可以接收到。
通過socket接收post請求
代碼:
package com.haojie.socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpListener {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
int port = 8080;
try {
serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
Socket clntSock = serverSocket.accept();
InputStream input = clntSock.getInputStream();
OutputStream output= clntSock.getOutputStream();
StringBuffer request = new StringBuffer(2048);
int i;
byte[] buffer = new byte[2048];
try {
i = input.read(buffer);
} catch (IOException e) {
e.printStackTrace();
i = -1;
}
for (int j = 0; j < i; j++) {
request.append((char) buffer[j]);
}
// 打印http協議內容
System.out.println(request);
// file not found
String errorMessage = "HTTP/1.1 200 success\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: 23\r\n" +
"\r\n" +
"<h1>success</h1>";
output.write(errorMessage.getBytes());
clntSock.close();
}
}
socket接收post請求結果圖:
總結
在http協議中,get請求與post請求都可以在URL與請求體中攜帶參數,如果是tomcat來接收http協議,tomcat在遇到get請求時,不會去請求體中獲取請求參數,因此在tomcat環境中,不能在get請求的請求體中傳遞參數,而在post請求時,URL與請求體都可以傳遞參數。