JavaWeb-Servlet基础

前言

ServletJavaWeb中最核心的组件.

Servlet规范为JavaWeb应用制定了对象模型:

  • 请求对象(ServletRequest): Servlet从该对象中获取来自客户端的请求信息.
  • 相应对象(ServletResponse): Servlet通过该对象来生成响应结果.
  • Servlet配置对象(ServletConfig): 当容器初始化一个Servlet对象时,会向Servlet提供一个ServletConfig对象(对应web.xml当中的<servlet>元素),Servlet通过该对象来获取初始化参数信息即ServletContext对象.
  • Servlet上下文(ServletContext): Servlet通过该对象来访问容器为当前Web应用提供的各种资源.

生命周期

JavaWeb应用的生命周期是由Servlet容器来控制的:

  • 启动阶段: 加载Web应用的相关数据,创建ServletConfig对象,对Filter和一些Servlet进行初始化.
  • 运行时阶段: 为客户端提供服务.
  • 终止阶段: 释放Web应用所占用的各种资源.

启动阶段

Servlet容器在启动JavaWeb应用时,会完成如下操作:

  1. web.xml文件中的数据加载到内存中.
  2. JavaWeb应用创建一个ServletContext对象.
  3. 对所有的Filter进行初始化
  4. 对那些需要在Web应用启动时就被初始化的Servlet进行初始化

运行时阶段

这是JavaWeb应用最主要的生命阶段,对应Servlet接口的service方法

终止阶段

Servlet容器在终止时,会完成如下操作:

  1. 销毁JavaWeb应用中所有处于运行时状态的Servlet
  2. 销毁所有Filter
  3. 销毁所有与JavaWeb应用相关的对象,如ServletContext对象等,并且释放Web应用所占的资源.

可视化

最常用的Servlet容器之一Tomcat提供了管理界面,可以通过界面来管理Servlet容器的生命周期:

在这里插入图片描述

不过需要提前配置tomcat-user.xml,添加一个角色为manager-gui的用户信息,不同的Tomcat版本可能需要配置的角色不同,比如6.X可能需要配置manager角色,主要根据界面提示来配即可,tomcat-user.xml位于$CATALINA_HOME/conf/目录下:

<tomcat-users>
    <role rolename="manager-gui"/>
    <user username="tomcat" password="tomcat" roles="manager-gui"/>
</tomcat-users>

Servlet的生命周期

初始化阶段

Servlet的初始化阶段包括4个步骤:

  1. Servlet容器加载Servlet类,把它的.class文件中的数据读入到内存中

  2. Servlet容器创建ServletConfig对象

  3. Servlet容器创建Servlet对象

  4. Servlet容器调用init(ServletConfig)方法,在GenericServlet实现类的复写下,建立了Servlet对象与ServletConfig对象的关系:

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

    通过ServletConfig可以得到ServletContext对象.

在以下情况之一,Servlet会进入初始化状态:

  1. 当前Web应用处于运行时阶段,特定Servlet被客户端首次请求访问.多数Servlet都会在这种情况下被启动
  2. 如果在web.xml中为Servlet设置了<load-on-startup>元素,那么当所属Web应用启动时,该Servlet就会初始化.
  3. Web应用被重新启动时,Web应用中的所有Servlet都会在特定的时刻被重新初始化.

运行时阶段

Servlet容器接收到请求,会创建针对这个请求的ServletRequestServletResponse对象,然后调用相应Servlet对象的service方法.service()根据ServletRequest得到请求参数,经过处理后用ServletResponse生成响应结果.

Servlet容器吧Servlet生成的响应结果发送给了客户,Servlet容器就会销毁ServletRequestServletResponse对象.

销毁阶段

当应用终止,会西安调用所有Servlet对象的destroy方法,然后再销毁这些Servlet对象,同时销毁与Servlet对象关联的ServletConfig对象.

ServletContext与Web应用范围

启动一个JavaWeb应用,会创建唯一的ServletContext对象,销毁容器也会对应销毁上下文.

简单来说,ServletContext是用来存放Web应用范围内的共享数据的.但要注意多线程的问题,它不是线程安全的.

通过ServletContext::getInitParam来获取.

ServletContextListener

Servlet中有一个ServletContextListener接口,它能够监听ServletContext对象的生命周期,实际上就是监听Web应用的生命周期.

Servlet容器启动或终止Web应用时,会触发ServletContextEvent事件,该事件由ServletContextListener处理:

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;

public class ServletContextListener implements javax.servlet.ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext servletContext = sce.getServletContext();
        //do something with servlet context...
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        ServletContext servletContext = sce.getServletContext();
        //do something with servlet context...
    }
}

Servlet API

接口与类 作用 生命周期
Servlet接口 1. 负责相应客户请求
2.GenericServletServlet接口的通用实现,而HttpServlet提供了与HTTP协议相关的实现
1. 对于多数Servlet,只有当客户端首次请求访问时,才会被容器初始化:对于少数被设置为随Web应用启动时启动的Servlet,将在容器启动时初始化.
2. 当Web应用被终止时,所有运行中的Servlet都被销毁
ServletRequest接口
HttpServletRequest接口
1. 表示客户端请求
2. HttpServletRequest接口表示HTTP请求
1. 容器每次接收到来自客户端的要求访问特定Servlet的请求,就会创建ServletRequest对象
2. 当服务器端相应请求完毕,容器就会销毁ServletRequest对象
ServletResponse接口
HttpServletResponse接口
1. Servlet通过ServletResponse接口来生成响应结果
2. Servlet通过HttpServletResponse接口来生成HTTP响应结果
1. 容器每次接收到来自客户端的要求访问特定Servlet的请求,就会创建ServletResponse对象
2. 当服务器端响应请求完毕,容器就会销毁ServletResponse对象
ServletConfig接口 包含了Servlet的初始化参数信息,并且与当前Web应用的ServletContext对象关联 1. 当容器初始化一个Servlet时,先创建一个ServletConfig对象,使Servlet对象与这个ServletConfig对象关联
2. 容器销毁时随之销毁
ServletContext接口 这是容器为每个Web应用进行分配的大管家.Servlet通过它来存取Web应用范围内的共享数据,还可以通过它来访问Servlet容器的各种资源 1. 当容器启动一个Web应用时,会为它创建一个ServletContext对象
2. 当容器终止一个Web应用时,会销毁它的ServletContext对象

转发和包含

Servlet对象由Servlet容器创建,并且Servlet对象的service()方法也由容器调用.一个Servlet对象可否直接调用另一个Servlet对象的service()方法呢?答案是否定的,因为一个Servlet对象无法获得另一个Servlet对象的引用.

Web应用在响应客户端的一个请求时,有可能响应过程很复杂,需要多个Web组件共同写作,才能生成响应结果.尽管一个Servlet对象无法直接调用另一个Servlet对象的service()方法,但Servlet规范为Web组价之间的写作提供了两种途径:

  • 请求转发:先对客户请求做一些预处理操作,然后把请求转发给其他组件来完成包括生成响应结果在内的后续操作
  • 包含:把其他组件生成的响应结果包含到自身的响应结果中

需要借助ServletContext对象获取RequestDispatcher,再调用相关方法(forwardinclude)来实现:

getServletContext()
    .getRequestDispatcher("/another_servlet_path")
    .forward(req, resp);

面试

  1. 过滤器、监听器、拦截器的区别
posted @ 2020-04-10 15:12  舒山  阅读(334)  评论(0编辑  收藏  举报