JavaWeb-servlet详解

什么是servlet

Java Servlet(Java服务器小程序)是一个基于Java技术的Web组件,运行在服务器端,它由Servlet容器所管理,用于生成动态的内容。 Servlet是平台独立的Java类,编写一个Servlet,实际上就是按照Servlet规范编写一个Java类。Servlet被编译为平台独立 的字节码,可以被动态地加载到支持Java技术的Web服务器中运行。
简而言之:

  • servlet是javaEE规范之一,规范就是接口
  • servlet是Java Web三大组件之一,三大组件分别是:request response servlet
  • servlet是运行在服务器上的用java开发的小程序,用于接收客户端的消息并响应

什么是servlet容器

在理解servlet执行过程和原理之前,先要弄清楚什么是web服务器,什么是servlet容器
1.Web服务器使用HTTP协议来传输数据。
最简单的一种情况是,用户在浏览器(客户端,client)中输入一个URL(如,www.programcreek.com/static.html),然后就能获取网页进行阅览。因此,服务器完成的工作就是发送网页至客户端。传输过程遵循HTTP协议,它指明了请求(request)消息和响应(response)消息的格式。Tomcat就是我们常用的web服务器之一
2.Servlet容器
Servlet容器的基本思想是在服务器端使用Java来动态生成网页。因此,Servlet容器是Web服务器和servlet进行交互的必不可少的组件,Servlet容器就是用来装Servlet的,我们可以把Tomcat理解一个web服务器中包含了ervlet容器,且servlet生命周期实例化、初始化、调用、销毁受控于Tomcat
3.Tomcat服务器是一个开源的servlet容器
Tomcat服务器接受客户请求并做出响应的过程如下:

  • 客户端(通常都是浏览器)访问Web服务器,发送HTTP请求。
  • Web服务器接收到请求后,传递给Servlet容器。
  • Servlet容器加载Servlet,产生Servlet实例后,向其传递表示请求和响应的对象。
  • Servlet实例使用请求对象得到客户端的请求信息,然后进行相应的处理。
  • Servlet实例将处理结果通过响应对象发送回客户端,容器负责确保响应正确送出,同时将控制返回给Web服务器。

servlet快速入门

使用方法:Servlet技术的核心是Servlet,用户在实现servlet时可以直接实现servlet或者间接实现它的实现类,一个servlet容器可以有多个servlet实现类以及与他相关的配置,public class DemoServlet1 extends HttpServlet
public class servletDemo01 implements Servlet
注意:每种servlet只能有一个实例,可以有多个servlet类,效率高,线程不安全

在这里插入图片描述

在这里插入图片描述

Servlet方法

public interface Servlet {
    void init(ServletConfig var1) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

  • init()初始化方法,在servlet被创建时执行,且只执行一次
  • service()每次访问servlet都会执行此方法
  • destory()服务器正常关闭时执行,且只执行一次
  • getServletConfig()这个方法会返回由Servlet容器传给init( )方法的ServletConfig对象
  • getServletInfo()返回Servlet的一段描述,信息,作者,版本

Servlet生命周期

用servlet里的init() service()destory()来描述servlet生命周期会非常形象
1.被创建:
执行init()方法,只执行一次,引出问题:servlet什么时候被创建?
解决:第一次被访问时创建,也可以修改创建时机,如下图所示

在这里插入图片描述

2.提供服务:
执行service()方法
3.销毁:
执行destory()方法,只有在服务器正常关闭才会执行

Servlet继承体系

Tomcat自动导入了servlet API,如图所示
在这里插入图片描述
共包含四个部分:

  • javax.servlet 其中包含定义servlet和servlet容器之间契约的类和接口。

  • javax.servlet.http 其中包含定义HTTP Servlet 和Servlet容器之间的关系。

    扫描二维码关注公众号,回复: 10524675 查看本文章
  • javax.servlet.annotation 其中包含标注servlet,Filter,Listener的标注。它还为被标注元件定义元数据。

  • javax.servlet.descriptor,其中包含提供程序化登录Web应用程序的配置信息的类型。

罗列出最常用的servlet接口,全部位于javax.servlet包下,每个接口的使用方法请参考我的其他博客
在这里插入图片描述

Servlet执行原理

当前环境使用的web服务器为Tomcat

用户通过单击某个链接或者直接在浏览器的地址栏中输入URL来访问web服务器,web服务器根据配置在xml中的信息去磁盘中加载对应的servlet实现类,并加载到servlet容器中,Tomcat根据http协议将用户输入的内容封装为request对象并转发到对应的servlet去实现,Tomcat将经过servlet的各种实现类处理过的信息(经过service()或doGet()doPost()方法处理)封装到response对象中,并经过http协议返回给用户所在的客户端
如图所示:
在这里插入图片描述
运行过程中的response和request对象是由Tomcat创建的,不需要用户自己创建
对于每一个应用程序,Servlet容器还会创建一个ServletContext对象。这个对象中封装了上下文(应用程序)的环境详情。每个应用程序只有一个ServletContext。每个Servlet对象也都有一个封装Servlet配置的ServletConfig对象,下面来介绍这些类

ServletConfig

是servlet程序的配置信息类,由Tomcat创建,每个servlet创建时都会创建与之对应的ServletConfig,有三个作用

  • 获取servlet的别名servletConfig.getServletName()
  • 获取servlet的初始化参数init-param,servletConfig.getIniteParameter("");
  • 获取servletContext对象servletConfig.getServletContext();
ServletContext

ServletContext是一个接口,它表示servlet上下文对象,一个web工程只有一个servletContext对象实例,在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象。是一个域对象,什么是域对象?
域对象:可以像map存储数据的对象,这里的域是指存储数据的操作范围

对象 存数据 取数据 删除数据
Map put() get() remove()
域对象 setAttribute() getAttribute removeAttribute()

GenericServlet

前面我们编写Servlet一直是通过实现Servlet接口来编写的,但是,使用这种方法,则必须要实现Servlet接口中定义的所有的方法,即使有一些方法中没有任何东西也要去实现,并且还需要自己手动的维护ServletConfig这个对象的引用。因此,这样去实现Servlet是比较麻烦的,GenericServlet抽象类的出现很好的解决了这个问题。本着尽可能使代码简洁的原则,GenericServlet实现了Servlet和ServletConfig接口,代码中出现了空实现方法


public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
    private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
    private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.LocalStrings");
    private transient ServletConfig config;

    public GenericServlet() {
    }

    public void destroy() {
    }

    public String getInitParameter(String name) {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getInitParameter(name);
        }
    }

    public Enumeration getInitParameterNames() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getInitParameterNames();
        }
    }

    public ServletConfig getServletConfig() {
        return this.config;
    }

    public ServletContext getServletContext() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getServletContext();
        }
    }

    public String getServletInfo() {
        return "";
    }

    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }

    public void init() throws ServletException {
    }

    public void log(String msg) {
        this.getServletContext().log(this.getServletName() + ": " + msg);
    }

    public void log(String message, Throwable t) {
        this.getServletContext().log(this.getServletName() + ": " + message, t);
    }

    public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    public String getServletName() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getServletName();
        }
    }
}

HttpServlet

HttpServlet抽象类是继承于GenericServlet抽象类而来的。使用HttpServlet抽象类时,还需要借助分别代表Servlet请求和Servlet响应的HttpServletRequest和HttpServletResponse对象。
HttpServletRequest接口扩展于javax.servlet.ServletRequest接口,HttpServletResponse接口扩展于javax.servlet.servletResponse接口。
HttpServlet抽象类覆盖了GenericServlet抽象类中的Service( )方法

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    HttpServletRequest request;
    HttpServletResponse response;
    try {
        request = (HttpServletRequest)req;
        response = (HttpServletResponse)res;
    } catch (ClassCastException var6) {
        throw new ServletException("non-HTTP request or response");
    }
 
    this.service(request, response);
}

调用了本类中的另一个service方法:

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String method = req.getMethod();
    long lastModified;
    if (method.equals("GET")) {
        lastModified = this.getLastModified(req);
        if (lastModified == -1L) {
            this.doGet(req, resp);
        } else {
            long ifModifiedSince = req.getDateHeader("If-Modified-Since");
            if (ifModifiedSince < lastModified) {
                this.maybeSetLastModified(resp, lastModified);
                this.doGet(req, resp);
            } else {
                resp.setStatus(304);
            }
        }
    } else if (method.equals("HEAD")) {
        lastModified = this.getLastModified(req);
        this.maybeSetLastModified(resp, lastModified);
        this.doHead(req, resp);
    } else if (method.equals("POST")) {
        this.doPost(req, resp);
    } else if (method.equals("PUT")) {
        this.doPut(req, resp);
    } else if (method.equals("DELETE")) {
        this.doDelete(req, resp);
    } else if (method.equals("OPTIONS")) {
        this.doOptions(req, resp);
    } else if (method.equals("TRACE")) {
        this.doTrace(req, resp);
    } else {
        String errMsg = lStrings.getString("http.method_not_implemented");
        Object[] errArgs = new Object[]{method};
        errMsg = MessageFormat.format(errMsg, errArgs);
        resp.sendError(501, errMsg);
    }
 
}

在service方法在解析HttpServletRequest中的方法参数,并调用以下方法之一:doGet,doPost,doHead,doPut,doTrace,doOptions和doDelete。这7种方法中,每一种方法都表示一个Http方法。doGet和doPost是最常用的。

参考:

https://blog.csdn.net/qq_19782019/article/details/80292110?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
附:servlet继承树图:
在这里插入图片描述

发布了37 篇原创文章 · 获赞 11 · 访问量 3905

猜你喜欢

转载自blog.csdn.net/Alphr/article/details/104589636
今日推荐