zoukankan      html  css  js  c++  java
  • Servlet学习笔记【1】--- 背景和基础知识(CGI、Web服务器发展史、Servlet简介、任务、继承结构)

    本文主要讲Servlet的基础知识和背景知识。

    1 CGI简介

    CGI(Common Gateway Interface 公共网关接口)是WWW技术中最重要的技术之一,有着不可替代的重要地位。CGI是外部应用程序(CGI程序)与WEB服务器之间的接口标准,是在CGI程序和Web服务器之间传递信息的过程。CGI规范允许Web服务器执行外部程序,并将它们的输出发送给Web浏览器,CGI将Web的一组简单的静态超媒体文档变成一个完整的新的交互式媒体。

    Common Gateway Interface,简称CGI。在物理上是一段程序,运行在服务器上,提供同客户端HTML页面的接口。这样说大概还不好理解。那么我们看一个实际例子:现在的个人主页上大部分都有一个留言本。留言本的工作是这样的:先由用户在客户端输入一些信息,如评论之类的东西。接着用户按一下“发布或提交”(到目前为止工作都在客户端),浏览器把这些信息传送到服务器的CGI目录下特定的CGI程序中,于是CGI程序在服务器上按照预定的方法进行处理。在本例中就是把用户提交的信息存入指定的文件中。然后CGI程序将执行结果返回给服务器(webServer),然后服务器将结果返回给客户端,表示请求的任务已经结束。此时用户在浏览器里将看到“留言结束”的字样,整个过程结束。

    2 Web服务器发展历史

    通过服务器可以访问静态资源和动态资源。

    静态资源就是一些图片、视频等文件。访问流程:读取磁盘文件到内存中--->启动IO流-->将文件内容以字符串形式返回给浏览器。

    动态资源是一些代码,需要执行后将结果返回给浏览器端。而要在本地执行对应的代码,就需要有执行环境和标准接口规范(个人理解就是上边的CGI)。

    1)早期CGI模式服务器

    CGI模式的特点:是将服务端的动态资源基于进程(process)方法来运行。由于进程的执行非常耗费时间,且内存空间浪费,所以效率极其低下。

    2)FastCGI模式服务器

    所谓的fastCGI的模式其实就是当前的CGI模式中添加的一个pooling(资源池)的概念,在服务器启动时初始化固定的进程来提高处理客服端的请求的速度,但是该方法治标不治本。

    3)Servlet模式服务器

    技术特点:

    与传统的CGI模式不同,Servlet运行模式改为单进程多线程的模式(线程程运行在进程中)。

    单进程:服务器;

    多线程:服务端的Servlet。

    这样就大大提高了运行效率。

    3 Servlet简介

    Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

    使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

    Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:

    • 性能明显更好。
    • Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。
    • Servlet 是独立于平台的,因为它们是用 Java 编写的。
    • 服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。
    • Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。

    4 Servlet架构

    下图显示了 Servlet 在 Web 应用程序中的位置。

    5 Servlet任务

    Servlet 执行以下主要任务:

    • 读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
    • 读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
    • 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
    • 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
    • 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。

    6 Servlet的继承结构

    在Tomcat项目包中,有个lib目录,下边有个servlet-api.jar文件包,该jar包就是Tomcat对Servlet的接口实现。通过解压和反编译后,可以查看里边的实现代码。

    解压方式:将jar包扩展名改为rar,然后解压。

    反编译方式:通过jd-gui.exe反编译工具实现将class文件反编译为可读的java代码文件。

    通过上边解压和反编译,在servlet-apijavaxservlet文件夹下,我们可以看到Servlet.class,其反编译后代码如下:

     1 package javax.servlet;
     2 
     3 import java.io.IOException;
     4 
     5 public abstract interface Servlet
     6 {
     7   public abstract void init(ServletConfig paramServletConfig)
     8     throws ServletException;
     9 
    10   public abstract ServletConfig getServletConfig();
    11 
    12   public abstract void service(ServletRequest paramServletRequest, ServletResponse paramServletResponse)
    13     throws ServletException, IOException;
    14 
    15   public abstract String getServletInfo();
    16 
    17   public abstract void destroy();
    18 }

    GenericServlet.class反编译后代码如下:

     1 package javax.servlet;
     2 
     3 import java.io.IOException;
     4 import java.io.Serializable;
     5 import java.util.Enumeration;
     6 
     7 public abstract class GenericServlet
     8   implements Servlet, ServletConfig, Serializable
     9 {
    10   private static final long serialVersionUID = 1L;
    11   private transient ServletConfig config;
    12 
    13   public void destroy()
    14   {
    15   }
    16 
    17   public String getInitParameter(String name)
    18   {
    19     return getServletConfig().getInitParameter(name);
    20   }
    21 
    22   public Enumeration<String> getInitParameterNames()
    23   {
    24     return getServletConfig().getInitParameterNames();
    25   }
    26 
    27   public ServletConfig getServletConfig()
    28   {
    29     return this.config;
    30   }
    31 
    32   public ServletContext getServletContext()
    33   {
    34     return getServletConfig().getServletContext();
    35   }
    36 
    37   public String getServletInfo()
    38   {
    39     return "";
    40   }
    41 
    42   public void init(ServletConfig config)
    43     throws ServletException
    44   {
    45     this.config = config;
    46     init();
    47   }
    48 
    49   public void init()
    50     throws ServletException
    51   {
    52   }
    53 
    54   public void log(String msg)
    55   {
    56     getServletContext().log(getServletName() + ": " + msg);
    57   }
    58 
    59   public void log(String message, Throwable t)
    60   {
    61     getServletContext().log(getServletName() + ": " + message, t);
    62   }
    63 
    64   public abstract void service(ServletRequest paramServletRequest, ServletResponse paramServletResponse)
    65     throws ServletException, IOException;
    66 
    67   public String getServletName()
    68   {
    69     return this.config.getServletName();
    70   }
    71 }

    在servlet-apijavaxservlethttp文件夹下,可以找到HttpServlet.class文件,反编译后内容如下:

     1 package javax.servlet.http;
     2 
     3 // ...省略代码
     4 import javax.servlet.GenericServlet;
     5 
     6 public abstract class HttpServlet extends GenericServlet
     7 {
     8   // ...省略代码
     9   
    10   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    11     throws ServletException, IOException
    12   {
    13     // ...省略实现代码
    14   }
    15 
    16   protected long getLastModified(HttpServletRequest req)
    17   {
    18     return -1L;
    19   }
    20 
    21   protected void doHead(HttpServletRequest req, HttpServletResponse resp)
    22     throws ServletException, IOException
    23   {
    24     // ...省略实现代码
    25   }
    26 
    27   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
    28     throws ServletException, IOException
    29   {
    30     // ...省略实现代码
    31   }
    32 
    33   protected void doPut(HttpServletRequest req, HttpServletResponse resp)
    34     throws ServletException, IOException
    35   {
    36     // ...省略实现代码
    37   }
    38 
    39   protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
    40     throws ServletException, IOException
    41   {
    42     // ...省略实现代码
    43   }
    44 
    45   private static Method[] getAllDeclaredMethods(Class<?> c)
    46   {
    47     // ...省略实现代码
    48   }
    49 
    50   protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
    51     throws ServletException, IOException
    52   {
    53     Method[] methods = getAllDeclaredMethods(super.getClass());
    54     // ...省略实现代码
    55   }
    56 
    57   protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
    58     throws ServletException, IOException
    59   {
    60     String CRLF = "
    ";
    61     StringBuilder buffer = new StringBuilder("TRACE ").append(req.getRequestURI()).append(" ").append(req.getProtocol());
    62     // ...省略实现代码
    63   }
    64 
    65   protected void service(HttpServletRequest req, HttpServletResponse resp)
    66     throws ServletException, IOException
    67   {
    68     String method = req.getMethod();
    69     long lastModified;
    70     // ...省略实现代码
    71   }
    72 
    73   private void maybeSetLastModified(HttpServletResponse resp, long lastModified)
    74   {
    75     if (resp.containsHeader("Last-Modified"))
    76       return;
    77     if (lastModified >= 0L)
    78       resp.setDateHeader("Last-Modified", lastModified);
    79   }
    80 
    81   public void service(ServletRequest req, ServletResponse res)
    82     throws ServletException, IOException
    83   {
    84     // ...省略实现代码
    85   }
    86 }

    从上边源码中可以发现:

    servlet.class文件就是实现SUN公司JavaEE制定的Servlet标准接口的代码;

    GenericServlet.class 中间层 抽象类 直接实现Servlet,并没有将Servlet所有方法实现,添加了一些自己的方法;

    http目录下的HttpServlet继承了GenericServlet,该主要实现与http协议相关的接口(doPost、doGet、doPut、doDelete)。

    GenericServlet存在的原因:解除http协议和Servlet之间的耦合。随着技术发展后续可能会替换http,改为其它协议。这样如果要切换,可复用的部分在GenericServlet中,并不需要重新开发,只需要将httpServlet基于新协议重新开发即可。这就是开闭原则,需要更改时,只需要修改一部分代码即可。

    Servlet是基于Http协议的。

    参考资料&内容来源:

    百度百科:https://baike.baidu.com/item/CGI/607810?fr=aladdin&fromid=6717913&fromtitle=%EF%BC%A3%EF%BC%A7%EF%BC%A9

    速学堂:http://www.sxt.cn/tomcat/1-1-1.html

    菜鸟教程:http://www.runoob.com/servlet/servlet-intro.html

  • 相关阅读:
    Get distinct count of rows in the DataSet
    单引号双引号的html转义符
    PETS Public English Test System
    Code 39 basics (39条形码原理)
    Index was outside the bounds of the array ,LocalReport.Render
    Thread was being aborted Errors
    Reportviewer Error: ASP.NET session has expired
    ReportDataSource 值不在预期的范围内
    .NET/FCL 2.0在Serialization方面的增强
    Perl像C一样强大,像awk、sed等脚本描述语言一样方便。
  • 原文地址:https://www.cnblogs.com/zhaoweikai/p/9877222.html
Copyright © 2011-2022 走看看