1. 程式人生 > 其它 >Servlet--HttpServlet實現doGet和doPost請求的原理(轉)

Servlet--HttpServlet實現doGet和doPost請求的原理(轉)

  • Servlet(Server Applet):全稱Java Servlet。是用Java編寫的伺服器端程式。其主要功能在於互動式地瀏覽和修改資料,生成動態Web內容。
    • 狹義的Servlet是指 Java語言實現的一個介面,廣義的Servlet是指任何實現了這個Servlet介面的類。
  • HttpServlet: 指能夠處理 HTTP 請求的 servlet,它在原有 Servlet 介面上添加了一些與 HTTP 協議處理方法,它比 Servlet 介面的功能更為強大。因此開發人員在編寫Servlet時,通常應繼承這個類,而避免直接去實現Servlet介面。
    • HttpServlet 在實現 Servlet 介面時,覆寫了 service 方法
      ,該方法體內的程式碼會自動判斷使用者的請求方式,如為 GET 請求,則呼叫 HttpServlet 的 doGet 方法,如為 Post 請求,則呼叫 doPost 方法。因此,開發人員在編寫 Servlet 時,通常只需要覆寫 doGet 或 doPost 方法,而不要去覆寫 service 方法。

  參考:https://blog.csdn.net/HeatDeath/article/details/79057168

  

轉:https://blog.csdn.net/m0_38039437/article/details/75264012

一、HttpServlet簡介

1、HttpServlet是GenericServlet的子類,又是在GenericServlet的基礎上做了增強。

2、HttpServlet方法

二、HTTP實現doGet或doPost請求專案介紹

1、通過實現doGet請求和doPost請求例項來了解內部的工作原理。

2、doGet請求和doPost請求例項程式碼介紹:

  A:建立一個Servlet類繼承HttpServlet類

  B:在index.jsp頁面建立一個超連結請求

3、doGet請求和doPost請求例項實施介紹:

  A、建立一個webproject專案。

  

  B、建立一個Servlet類的名稱為HttpServ繼承HttpServlet類同時覆寫doGet方法和doPost方法。

1、

2、

3、配置web.xml檔案

4、建立Servlet程式碼展示

package httpserve;
 
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class HttpServ extends HttpServlet {
 
    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        System.out.println("傳送get請求。。。。。。。。。。。");
        
    }
 
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        resp.setContentType("text/html;charset=UTF-8");
        System.out.println("傳送post方法。。。。。。。。。。");
    }

5、web.xml配置檔案程式碼展示

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>HttpServ</servlet-name>
    <servlet-class>httpserve.HttpServ</servlet-class>
  </servlet>
 
  <servlet-mapping>
    <servlet-name>HttpServ</servlet-name>
    <url-pattern>/http</url-pattern>
  </servlet-mapping>
 
</web-app>

C、在index.jsp頁面建立一個超連結請求

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>
  
  <body>
    This is my JSP page. <br>
    <a href="http://localhost:8080/test06/http">get請求1</a><br/>
    <!-- 對於一個html頁面來說,如果沒有以http開始,則預設的前面會加上
        協議型別://目前這個頁面所在的伺服器:目前埠/目前專案/你給的這個名稱 -->
    <a href="http">get請求2</a><hr/>
    <form method = "post" action="http">
        <input type="submit" value="提交"/>
    </form>
  </body>
</html>

D、傳送doGet請求和doPost請求

a、在瀏覽器中輸入測試地址,http://127.0.0.1:8080/test06/

b、開啟專案的首頁後分別點選get請求1、get請求2、和 post請求(提交按鈕)

c、在控制檯可以觀察到分別呼叫了doGet和doPost方法。

三、HTTP實現doGet或doPost請求原理介紹

  1、瀏覽器傳送請求到HttpSevr類呼叫HttpServ的service(servletRequest, servletReponse)方法

  2、由於沒有找到這個方法,去呼叫父類(HttpServlet)的同名方法。

  3、父類的service方法將ServletRequest req請求轉換成HttpServletRequest請求,再去呼叫service(request, response) 方法。

 將ServletRequest req請求轉換成HttpServletRequest請求再呼叫service(request, response) 方法原始碼如下:

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);
    }

4、 呼叫的service(request, response) 方法功能是判斷使用者發出是什麼請求,如果是get則呼叫子類(HttpSevr)的doGet方法,如果是post則呼叫子類(HttpSevr)的doPost方法。

service(request, response)方法原始碼如下:

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);
        }
    }

5、呼叫關係圖

四、注意事項:

1、如果在HttpServ中覆蓋了service(ServletRequest,SerlvetResonse)方法則這個類的所實現的doGet/doPost都不會再執行了。

因為service(ServletRequest,SerlvetResonse)是最高介面Servlet定義規範。在tomcat呼叫時,一定會在最終的子類中去找這個方法且呼叫它。

如果最終的子類沒有則會呼叫父的service(ServletRequest,SerlvetResonse)。

2、如果覆蓋了serivce(HttpServletRequest,HtpServletResponse)則會執行httpServlet中的service(ServletRequest,SerlvetResonse),但是由於子類中已經覆蓋了serivce(HttpServletRequest,HtpServletResponset)所以,httpServlet中的serivce(HttpServletRequest,HtpServletResponset)就不再執行了,而是直接執行子類中同名同參數方法,且doXxxx也不會執行了,因為子類的serivce(HttpServletRequest,HtpServletResponset)沒有呼叫doXxxx.

3、如果繼承了HttpServlet沒有實現任何的doXxx方法則會丟擲一個異常

五:客戶端請求和返回資料用到的常用方法https://www.cnblogs.com/xdp-gacl/p/3798347.html