JavaWeb——Servlet(全网最详细教程)

本文详细介绍了Servlet的概念、在程序中的地位、工作模式及其与Tomcat的关系。阐述了Servlet API、主要类型、继承结构和服务原理,并探讨了Servlet的生命周期、ServletConfig和ServletContext。此外,还讲解了GenericServlet、HttpServlet的使用,以及请求转发、重定向、会话管理和Cookie、HttpSession的管理。最后,文章总结了Servlet的三大域对象,包括Request、Session和Application域的使用方法。
摘要由CSDN通过智能技术生成

什么是Servlet?

   Servlet是Server Applet的简称,是用Java编写的服务器端程序,是JavaEE平台下的技术标准。其主要功能在于和浏览器交互并生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。

   Servlet通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。从原理上来讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。Servlet有三种实现方式:实现Servlet接口、继承抽象类GenericServlet、继承HttpServlet。

Servlet在程序中到底处于一个什么地位?

1. Servlet是可以接收http请求并作出响应的一种技术,是JAVA语言编写的一种动态资源;
2. Servlet是前后端衔接的一种技术,不是所有的JAVA类都可以接收请求和作出响应,但是Servlet可以;
3. 在MVC模式中,Servlet作为Controller层(控制层)主要技术,用于和浏览器完成数据交互,控制交互逻辑;

Servlet的工作模式

  • 客户端发送请求至服务器
  • 服务器运行并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器,响应内容动态生成,通常取决于客户端的请求
  • 服务器将响应返回客户端

Servlet体系结构与Tomcat的关系

Servlet是Tomcat的一个组件,Servlet的功能需要依赖一个servlet-api.jar,这个包是由Tomcat提供的,Tomcat在初始化Servlet时,首先读取web.xml文件,根据web.xml文件中的参数信息初始化ServletConfig、ServletContext对象,同时帮助我们创建HttpServletRequest和HttpServletResponse对象一并交给Servlet实例,此时,Servlet就具有了相关的功能。

Servlet API 概览

Servlet API 包含以下4个Java包:

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

2. javax.servlet.http:主要定义了与HTTP协议相关的HttpServlet类,HttpServletRequest接口和HttpServletResponse接口。

3. javax.servlet.annotation: 其中包含标注Servlet、Filter、Listener的标注。它还为被标注元件定义元数据。

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

Servlet的主要类型

Servlet、ServletConfig、ServletContext、ServletRequest、ServletResponse、GenericServlet(抽象类)

Servlet的继承结构

Servlet接口,只负责定义Servlet程序的访问规范;

GenericServlet抽象类实现了Servlet接口,做了很多空实现,并持有一个ServletConfig类的引用,并提供了一些ServletConfig的使用方法;

HttpServlet抽象类实现了service方法,并实现了请求分发处理;

Servlet的使用方法

Servlet技术的核心是Servlet,它是所有Servlet类必须直接或者间接实现的一个接口。在编写实现Servlet接口的类时,直接实现它,在扩展实现Servlet这个接口的类时,间接实现它。

Servlet的工作原理

 Servlet接口定义了Servlet与Servlet容器之间的契约,这个契约是:Servlet容器将Servlet类载入内存,生成Servlet实例并调用它具体的方法。但是要注意的是,在一个应用程序中,每种Servlet类型只能有一个实例

    用户发起请求使Servlet容器调用Servlet的service()方法,并传入一个ServletRequest对象和一个ServletResponse对象。ServletRequest对象和ServletResponse对象都是由Servlet容器(例如Tomcat)封装好的,并不需要开发人员去实现,开发者可以直接使用这两个对象。

    ServletRequest中封装了当前的Http请求,因此,开发人员不必解析和操作原始的Http数据。ServletResponse表示当前用户的Http响应,开发人员只需直接操作ServletResponse对象就能把响应轻松的返回给用户。

    对于每一个应用程序,Servlet容器还会创建一个ServletContext对象,这个对象中封装了上下文(应用程序)的环境详情。每个应用程序只有一个ServletContext,每个Servlet对象也都有一个封装Servlet配置的ServletConfig对象

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( )、service( )、destroy( )是Servlet生命周期的方法,代表了Servlet从“诞生”到“执行”再到“销毁 ”的过程。

Servlet的生命周期

Servlet的生命周期是由容器管理的,Servlet容器(例如Tomcat)会根据下面的规则来调用这三个方法:

1. 初始化方法init( ),只会执行一次(启动Tomcat的时候默认是不执行的,在访问的时候才会执行)当Servlet第一次被请求时,Servlet容器会实例化这个Servlet,然后就会调用这个方法来初始化Servlet,但是这个方法在后续请求中不会在被Servlet容器调用,我们可以利用init()方法来执行相应的初始化工作。

2. 服务方法service( ),每当请求Servlet时,Servlet容器就会调用这个方法。第一次请求时,Servlet容器会先调用init( )方法初始化一个Servlet对象出来,然后会调用它的service( )方法进行工作,但在后续的请求中,Servlet容器只会调用service方法了。

3. 销毁方法destory(),当要销毁Servlet时,Servlet容器就会调用这个方法,卸载应用程序或者关闭Servlet容器时,就会发生这种情况,一般在这个方法中会写一些清除代码。

一般在实际项目开发中,都是使用继承HttpServlet类的方式去实现 Servlet 程序,下面编写一个简单的Servlet程序来验证一下它的生命周期:

public class ServletLifeCycle extends HttpServlet {
    
   
    @Override
    public void init() throws ServletException {
        System.out.println("ServletLifeCycle 初始化方法执行" );
    }


    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws 
        //执行服务
        System.out.println("ServletLifeCycle service方法执行" );
    }


    @Override
    public void destroy() {
        System.out.println("ServletLifeCycle 销毁方法执行" );
    }

    @Override
    public ServletConfig getServletConfig() {
        return super.getServletConfig();
    }

    @Override
    public String getServletInfo() {
        return super.getServletInfo();
    }

    

}
<servlet>
  <servlet-name>ServletLifeCycle</servlet-name>
  <servlet-class>com.cgcstudy.servlet.ServletLifeCycle</servlet-class>
 <!-- <load-on-startup>6</load-on-startup>-->
</servlet>
<servlet-mapping>
  <servlet-name>ServletLifeCycle</servlet-name>
  <url-pattern>/servletLifeCycle.do</url-pattern>
</servlet-mapping>

在xml中配置正确的映射关系,在浏览器中访问Servlet,第一次访问时,控制台输出了如下信息:

再次访问Servlet,控制台输出的信息变成了下面这样:

接下来,关闭Servlet容器,控制台输出了Servlet的销毁信息:

这就是一个Servlet的完整生命周期。

通过以上案例发现Servlet默认情况下是在第一次访问时被创建并初始化的,如果初始化的工作比较多,那么第一次访问就会比较耗时,我们可否改变它的创建时机呢?
     我们可以在web.xml文件中配置<load-on-startup>,使得Servlet在服务器启动时创建并初始化,<load-on-startup>节点必须写在<servlet>节点的内部,且作为最后一个节点,取值必须是整数,如果是大于等于0的整数表示在服务器启动时就被创建并初始化,如果有多个Servlet设置了<load-on-startup>节点的值,那么值越小越优先执行;如果是负数则表示第一次被访问时创建并初始化,也就是默认情况,可以省略不写。

 总结

Servlet的生命周期是由容器管理的,Servlet从创建到销毁的全过程,共分为四个阶段:

1. 创建阶段:创建Servlet对象;

2. 初始化阶段:会执行init方法,只会执行一次。默认是在第一次访问Servlet时执行,可以在web.xml进行配置,配置<load-on-startup> 让Servlet随着Tomcat的启动而进行初始化,配置的值大于0即可,配置为负数就是默认情况,当多个 Servlet配置了<load-on-startup>值越小的优先执行;

3. 服务阶段:执行service方法,会执行多次;

4. 销毁阶段:会执行destroy方法,只会执行一次;

 注意点
      访问Servlet会实例化Servlet对象,发现构造方法只会执行一次,说明对象只创建了一
次,即单例模式。

Servlet 的其它两个方法:

getServletInfo(),这个方法会返回Servlet的一段描述,可以返回一段字符串;

getServletConfig(),这个方法会返回由Servlet容器传给init()方法的ServletConfig对象;

ServletConfig接口

ServletConfig对象对应web.xml文件中的<servlet>节点,当Servlet容器(如Tomcat)初始化Servlet时,会将该Servlet的配置信息,封装到一个ServletConfig对象中,我们可以通过该对象读取<servlet>节点中的配置信息

<servlet>
  <servlet-name>servletName</servlet-name>
  <servlet-class>servletClass</servlet-class>
  <init-param>
     <param-name>key</param-name>
     <param-value>value</param-value>
   </init-param>
</servlet>

当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init( )方式传入一个ServletConfig对象,ServletConfig其中几个方法如下:

public interface ServletConfig {

    String getServletName(); //获得Servlet在web.xml中配置的name值

    ServletContext getServletContext(); //获得ServletContext对象

    String getInitParameter(String var1); //获得Servlet的初始化参数

    Enumeration<String> getInitParameterNames(); //获得所有Servlet的初始化参数的名称
}

servletConfig.getInitParameter("key"),该方法可以读取web.xml文件中<servlet>标签中<init-param>标签中的配置信息;

servletConfig.getInitParameterNames(),该方法可以读取web.xml文件中当前<servlet>标签中所有<init-param>标签中的值;

ServletContext

ServletContext官方叫Servlet上下文。ServletContext对象表示Servlet应用程序,服务器会为每一个Web应用创建一个ServletContext对象,每个Web应用程序都只有一个ServletContext对象,这个对象全局唯一,而且Web应用中的所有Servlet都共享这个对象,所以叫全局应用程序共享对象;在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象。

那么为什么要存在一个ServletContext对象呢?因为有了ServletContext对象,可以利用该对象获取整个Web 应用程序的初始化信息、读取资源文件等,并且可以动态注册Web对象。这些信息是保存在ServletContext中的一个内部Map中,保存在ServletContext中的对象被称作属性。

ServletContext获取方式有两种:

1. request.getServletContext();         

2. this.getServletContext();

ServletContext的作用:

1. 获取web.xml文件中的信息,可以为所有的Servlet提供初始化数据;

<context-param>
   <param-name>key</param-name>
   <param-value>value</param-value>
</context-param>

<context-param>配置是一组键值对, <context-param>的作用:这个元素用来声明应用范围内的上下文初始化参数,其中的 <param-name> 设定上下文的参数名称,这个必须是唯一的,而<param-value>设定的参数名称的值。当服务器启动时,服务器会读取web.xml配置,当读到<context-param></context-param>这个节点的时候,容器会将这个节点中配置的值set到ServletContext(上下文对象)中,这样我们在程序中就能通过这个上下文对象去取得我们这个配置值。

servletContext.getInitParameter("key"),该方法可以读取web.xml文件中<context-param>标签中的配置信息。

servletContext.getInitParameterNames(),该方法可以读取web.xml文件中所有 <param-name> 标签中的值。

<context-param>配置和<init-param>的区别:

我们可以看到<init-param>是放在一个Servlet内的,所以这个参数是只针对某一个Servlet而言的,所以它们的区别就有点像全局变量和局部变量的,<context-param>是针对整个项目,所有的Servlet都可以取得使用,<init-param>只能是在某个Servlet下面配置,就在那个Servlet里面调用。

2. 域对象,共享数据(ServletContext对象是最大的域对象,被Web应用中的所有Servlet共享,而且 ServletContext可以帮助我们实现数据的传递);

ServletContext中的下列方法负责处理属性: 

Object getAttribute(String var1);
 
Enumeration<String> getAttributeNames(); //从全局容器中获取数据
 
void setAttribute(String var1, Object var2); //向全局容器中存放数据
 
void removeAttribute(String var1); //根据key删除全局容器中的value

ServletContext对象生命周期:当容器启动时会创建ServletContext对象并一直缓存该对象,直到容器关闭后该对象生命周期结束,ServletContext对象的生命周期非常长,所以在使用全局容器时不建议存放业务数据。

GenericServlet抽象类

    我们可以通过实现Servlet接口来编写Servlet程序,但是,使用这种方法,必须要实现Servlet接口中定义的所有的方法,即使有一

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值