Servlet--HttpServlet实现doGet和doPost请求的原理

Servlet--HttpServlet实现doGet和doPost请求的原理

一、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代码展示

     

[java] view plain copy
 
  1. package httpserve;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5.   
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.HttpServlet;  
  8. import javax.servlet.http.HttpServletRequest;  
  9. import javax.servlet.http.HttpServletResponse;  
  10.   
  11. public class HttpServ extends HttpServlet {  
  12.   
  13.       
  14.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  15.             throws ServletException, IOException {  
  16.           
  17.         System.out.println("发送get请求。。。。。。。。。。。");  
  18.           
  19.     }  
  20.   
  21.     protected void doPost(HttpServletRequest req, HttpServletResponse resp)  
  22.             throws ServletException, IOException {  
  23.         // TODO Auto-generated method stub  
  24.         resp.setContentType("text/html;charset=UTF-8");  
  25.         System.out.println("发送post方法。。。。。。。。。。");  
  26.     }  
  27.   
  28. }  

5、web.xml配置文件代码展示

[html] view plain copy
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="3.0"  
  3.     xmlns="http://java.sun.com/xml/ns/javaee"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">  
  6.   <servlet>  
  7.     <description>This is the description of my J2EE component</description>  
  8.     <display-name>This is the display name of my J2EE component</display-name>  
  9.     <servlet-name>HttpServ</servlet-name>  
  10.     <servlet-class>httpserve.HttpServ</servlet-class>  
  11.   </servlet>  
  12.   
  13.   <servlet-mapping>  
  14.     <servlet-name>HttpServ</servlet-name>  
  15.     <url-pattern>/http</url-pattern>  
  16.   </servlet-mapping>  
  17.   
  18. </web-app>  



C、在index.jsp页面创建一个超链接请求

[html] view plain copy
 
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
  2. <%  
  3. String path = request.getContextPath();  
  4. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
  5. %>  
  6.   
  7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  8. <html>  
  9.   <head>  
  10.     <base href="<%=basePath%>">  
  11.       
  12.     <title>My JSP 'index.jsp' starting page</title>  
  13.     <meta http-equiv="pragma" content="no-cache">  
  14.     <meta http-equiv="cache-control" content="no-cache">  
  15.     <meta http-equiv="expires" content="0">      
  16.     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  17.     <meta http-equiv="description" content="This is my page">  
  18.     <!-- 
  19.     <link rel="stylesheet" type="text/css" href="styles.css"> 
  20.     -->  
  21.   </head>  
  22.     
  23.   <body>  
  24.     This is my JSP page. <br>  
  25.     <href="http://localhost:8080/test06/http">get请求1</a><br/>  
  26.     <!-- 对于一个html页面来说,如果没有以http开始,则默认的前面会加上  
  27.         协议类型://目前这个页面所在的服务器:目前端口/目前项目/你给的这个名称 -->  
  28.     <href="http">get请求2</a><hr/>  
  29.     <form method = "post" action="http">  
  30.         <input type="submit" value="提交"/>  
  31.     </form>  
  32.   </body>  
  33. </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) 方法源码如下:

[java] view plain copy
 
  1. public void service(ServletRequest req, ServletResponse res)  
  2.        throws ServletException, IOException {  
  3.   
  4.        HttpServletRequest  request;  
  5.        HttpServletResponse response;  
  6.          
  7.        try {  
  8.            request = (HttpServletRequest) req;  
  9.            response = (HttpServletResponse) res;  
  10.        } catch (ClassCastException e) {  
  11.            throw new ServletException("non-HTTP request or response");  
  12.        }  
  13.        service(request, response);  
  14.    }  

4、 调用的service(request, response) 方法功能是判断用户发出是什么请求,如果是get则调用子类(HttpSevr)的doGet方法,如果是post则调用子类(HttpSevr)的doPost方法。

service(request, response) 方法源码如下:

[java] view plain copy
 
  1. protected void service(HttpServletRequest req, HttpServletResponse resp)  
  2.       throws ServletException, IOException {  
  3.   
  4.       String method = req.getMethod();  
  5.   
  6.       if (method.equals(METHOD_GET)) {  
  7.           long lastModified = getLastModified(req);  
  8.           if (lastModified == -1) {  
  9.               // servlet doesn't support if-modified-since, no reason  
  10.               // to go through further expensive logic  
  11.               doGet(req, resp);  
  12.           } else {  
  13.               long ifModifiedSince;  
  14.               try {  
  15.                   ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);  
  16.               } catch (IllegalArgumentException iae) {  
  17.                   // Invalid date header - proceed as if none was set  
  18.                   ifModifiedSince = -1;  
  19.               }  
  20.               if (ifModifiedSince < (lastModified / 1000 * 1000)) {  
  21.                   // If the servlet mod time is later, call doGet()  
  22.                   // Round down to the nearest second for a proper compare  
  23.                   // A ifModifiedSince of -1 will always be less  
  24.                   maybeSetLastModified(resp, lastModified);  
  25.                   doGet(req, resp);  
  26.               } else {  
  27.                   resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);  
  28.               }  
  29.           }  
  30.   
  31.       } else if (method.equals(METHOD_HEAD)) {  
  32.           long lastModified = getLastModified(req);  
  33.           maybeSetLastModified(resp, lastModified);  
  34.           doHead(req, resp);  
  35.   
  36.       } else if (method.equals(METHOD_POST)) {  
  37.           doPost(req, resp);  
  38.             
  39.       } else if (method.equals(METHOD_PUT)) {  
  40.           doPut(req, resp);          
  41.             
  42.       } else if (method.equals(METHOD_DELETE)) {  
  43.           doDelete(req, resp);  
  44.             
  45.       } else if (method.equals(METHOD_OPTIONS)) {  
  46.           doOptions(req,resp);  
  47.             
  48.       } else if (method.equals(METHOD_TRACE)) {  
  49.           doTrace(req,resp);  
  50.             
  51.       } else {  
  52.           //  
  53.           // Note that this means NO servlet supports whatever  
  54.           // method was requested, anywhere on this server.  
  55.           //  
  56.   
  57.           String errMsg = lStrings.getString("http.method_not_implemented");  
  58.           Object[] errArgs = new Object[1];  
  59.           errArgs[0] = method;  
  60.           errMsg = MessageFormat.format(errMsg, errArgs);  
  61.             
  62.           resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);  
  63.       }  
  64.   }  

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/zxtceq/p/8533392.html