TCP/IP協議,關注的是客戶端與服務器端之間數據是否傳輸成功!html
HTTP協議,是在TCP/IP協議之上封裝的一層協議,關注的是數據傳輸的格式是否規範。java
HTTP請求由四部分組成:請求行、請求頭、一個空行和實體內容(可選)。web
HTTP請求的組成:瀏覽器
|--請求行緩存
|--請求頭tomcat
|--(一個空行)服務器
|--實體內容(只有POST請求時纔有)cookie
HTTP請求的一個示例:app
GET /myweb/hello HTTP/1.1 --請求行 Host: localhost:8080 --請求頭(多個key-value對象) User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,en-us;q=0.8,zh;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive -- 一個空行 name=rk&password=123456 --(可選)實體內容
GET /myweb/hello HTTP/1.1 --請求行
#http協議版本less
http1.0:當前瀏覽器客戶端與服務器端創建鏈接以後,只能發送一次請求,一次請求以後鏈接關閉。
http1.1:當前瀏覽器客戶端與服務器端創建鏈接以後,能夠在一次鏈接中發送屢次請求。(如今基本上都使用1.1)
#請求資源
URL: 統一資源定位符。http://localhost:8080/myweb/hello.html。只能定位互聯網資源。是URI的子集。
URI: 統一資源標記符。/myweb/hello。用於標記任何資源。能夠是本地文件系統,局域網的資源(//192.168.14.10/myweb/index.html),能夠是互聯網資源。
#請求方式
常見的請求方式: GET 、 POST、 HEAD、 TRACE、 PUT、 CONNECT 、DELETE
經常使用的請求方式: GET 和 POST
表單提交:
<form action="提交地址" method="GET/POST">
</form>
GET方式 | POST方式 |
---|---|
a)地址欄(URI)會跟上參數數據。以?開頭,多個參數之間以&分割。 b)GET提交參數數據有限制,不超過1KB。 c)GET方式不適合提交敏感密碼。 d)注意: 瀏覽器直接訪問的請求,默認提交方式是GET方式 |
a)參數不會跟着URI後面。參數而是跟在請求的實體內容中。 b)POST提交的參數數據沒有限制。 c)POST方式提交敏感數據。 |
Accept: text/html,p_w_picpath/* -- 瀏覽器接受的數據類型 Accept-Charset: ISO-8859-1 -- 瀏覽器接受的編碼格式 Accept-Encoding: gzip,compress --瀏覽器接受的數據壓縮格式 Accept-Language: en-us,zh- --瀏覽器接受的語言 Host: www.it315.org:80 --(必須的)當前請求訪問的目標地址(主機:端口) If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT --瀏覽器最後的緩存時間 Referer: http://www.it315.org/index.jsp -- 當前請求來自於哪裏 User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0) --瀏覽器類型 Cookie:name=rk -- 瀏覽器保存的cookie信息 Connection: close/Keep-Alive -- 瀏覽器跟服務器鏈接狀態。close: 鏈接關閉 keep-alive:保存鏈接。 Date: Tue, 11 Jul 2000 18:23:51 GMT -- 請求發出的時間
只有POST提交的參數會放到實體內容中
HttpServletRequest對象做用是用於獲取請求數據。
類別 | API |
---|---|
請求行 | request.getMethod(); 請求方式 request.getRequetURI() / request.getRequetURL() 請求資源 request.getProtocol() 請求http協議版本 |
請求頭 | request.getHeader("名稱") 根據請求頭獲取請求值 request.getHeaderNames() 獲取全部的請求頭名稱 |
實體內容 | request.getInputStream() 獲取實體內容數據 |
Servlet繼承關係以下:
|-javax.servlet.Servlet接口
|-javax.servlet.GenericServlet抽象類
|-javax.servlet.http.HttpServlet抽象類
在javax.servlet.Servlet接口中有一個service方法,以下:
public void service(ServletRequest req, ServletResponse res)
在javax.servlet.http.HttpServlet類當中除了覆寫public的service方法以外,還定義了本身的protected的service方法。
public void service(ServletRequest req, ServletResponse res)實現以下:
//Dispatches client requests to the protected service method. //There's no need to override this method. public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; try { request = (HttpServletRequest) req; response = (HttpServletResponse) res; } catch (ClassCastException e) { throw new ServletException("non-HTTP request or response"); } service(request, response); }
protected void service(HttpServletRequest req, HttpServletResponse resp)實現以下:
//Receives standard HTTP requests from the public service method and // dispatches them to the doXXX methods defined in this class. //This method is an HTTP-specific version of the javax.servlet.Servlet.service method. //There's no need to override this method. protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); } catch (IllegalArgumentException iae) { // Invalid date header - proceed as if none was set ifModifiedSince = -1; } if (ifModifiedSince < (lastModified / 1000 * 1000)) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { // // Note that this means NO servlet supports whatever // method was requested, anywhere on this server. // String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } }
tomcat服務器首先會調用servlet的service方法,而後在service方法中再根據請求方式來分別調用對應的doXX方法。
在瀏覽器發送HTTP協議的時候,GET方式是將參數放在URI的後面,POST方式是將參數放在實體內容中。
獲取請求參數的API
獲取GET方式參數:request.getQueryString();
獲取POST方式參數:request.getInputStream();
問題:可是以上兩種不通用,並且獲取到的參數還須要進一步地解析。因此可使用統一方便的獲取參數的方式:
request.getParameter("參數名"); 根據參數名獲取參數值(注意,只能獲取一個值的參數)
request.getParameterValue("參數名「);根據參數名獲取參數值(能夠獲取多個值的參數)
request.getParameterNames(); 獲取全部參數名稱列表
修改POST方式參數編碼(這種方式只對POST請求的實體內容有效):
request.setCharacterEncoding("utf-8");
修改GET方式參數編碼:
手動解碼:String name = new String(name.getBytes("iso-8859-1"),"utf-8");