Servlet生命周期

五个部分,从加载到卸载,如同人类的出生到死亡

  1. 加载:Servlet容器自动处理
  2. 初始化:init方法 该方法会在Servlet被加载并实例化后执行
  3. 服务:service抽象方法:具体实现是doGet(),doPost()方法
  4. 销毁:destroy(),Servlet被系统回收时执行
  5. 卸载:Servlet容器自动处理

init():

  • 默认第一次访问Servlet时会被执行(只执行这一次,可以修改为Tomcat启动时自动执行:
  • 2.5:web.xml中<servlet>字段添加<load-on-startup>1(代表第1个Servlet)..
  • 3.0:@WebServlet(value = "/Servlet3",loadOnStartup = 1)

service():->doGet() doPost:调用几次,则执行几次

destroy():关闭tomcat服务时

Servlet API

由两个大类四个软件包组成::



即Servlet API可以适用于任何通信协议。但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

我们学习的Servlet,是位于javax.servlet.http包中的类和接口,是基础HTTP协议。

Servlet继承关系

ServletConfig:接口

ServletContext getServletContext():获取Servlet上下文对象 application

String getInitParameter(String name):在当前Servlet范围内,获取名为name的参数值(初始化参数)

a.ServletContext中的常见方法(application):

getContextPath():相对路径

getRealPath():绝对路径

setAttribute()、getAttribute()

---->

String getInitParameter(String name);在当前Web容器范围内,获取名为name的参数值(初始化参数)

初始化全局参数

    <context-param>
<param-name>globalParam</param-name>
<param-value>global value...</param-value>
</context-param>

初始化Servlet参数

  • Servlet2.5
    <servlet>
<servlet-name>my</servlet-name>
<servlet-class>com.hacker.servlet.MyServlet</servlet-class>
<load-on-startup>2</load-on-startup>
<!--配置当前Servlet初始化参数 -->
<init-param>
<param-name>servletparamname</param-name>
<param-value>servletparamvalue...</param-value>
</init-param>
</servlet>
  • Servlet3.0
@WebServlet(value = "/Servlet3",loadOnStartup = 1,initParams = {@WebInitParam(name="servletparamname30",value = "servletparamvalue30")})

注意:此注解只隶属于某一个具体的Servlet,因此无法为整个Web容器设置初始化参数(如果要通过3.0方式设置,仍需在web.xml中设置)

获取全局参数

ServletContext对象表示Servlet应用程序。每个Web应用程序都只有一个ServletContext对象。在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象。

通过在ServletConfig中调用getServletContext方法,也可以获得ServletContext对象。

    @Override
public void init() throws ServletException {
System.out.println("init...");
//获取整个Web容器的初始化参数
String str=super.getServletContext().getInitParameter("globalParam");
System.out.println("当前Web容器的初始化的参数为"+str);
}

获取当前Servlet参数

当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init( )方式传入一个ServletConfig对象

其中几个方法如下:

    @Override
public void init() throws ServletException {
System.out.println("init...");
//获取当前Servlet的初始化参数
String str=super.getInitParameter("servletparamname");
System.out.println("当前Servlet的初始化参数为"+str);
}

请求与响应

当我们在在请求Servlet容器具体的执行流程的细节是什么呢?一起来看一看

首先我们知道请求的过程最终传给了名为service的方法,那service方式到底是怎么执行的,我们先来简单的了解下

首先查看入口类继承的HTTPServlet类





点进去发现继承至GenericServlet,继续跟进



GenericServlet实现了一个Servlet接口



接口中定义了service方法,并且有两个参数ServletRequest和ServletResponse代表请求和响应,那么我们自定义的Servlet肯定不是实现的这个service方法,因为我们重写的service方法形参为HttpServletRequest和HttpServletResponse



现在就来找找到底是重写的那个service方法,首先来看GenericServlet类



在GenericServlet类中发现实现了service的抽象方法,传入参数为ServletRequest,明显也不是,继续跟进HTTPServlet类

在HTTPServlet类中发现两个service方法,很明显第二个service方法参数也是ServletRequest,所以第二个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(lStrings.getString("http.non_http"));
} this.service(request, response);
}

可以看到该实现方法将Servlet强转为了HttpServlet,

HttpServlet继承自Servlet,将父类变为了子类,把通用的响应,转换为了特需的HTTP响应,之所以能够这样强制的转换,是因为在调用Servlet的Service方法时,Servlet容器总会传入一个HttpServletRequest对象和HttpServletResponse对象,预备使用HTTP。因此,转换类型当然不会出错了。

PS:Java中父类想要转换为子类,父类的实例必须指向子类的应用,形如

    public static void main(String[] args) {
//Car为父类,BigCar为子类
Car car=new BigCar();//这里car父类对象的引用为BigCar子类 父类是子类构造出来的实例
BigCar bc=(BigCar)car;//所以这里可以将父类对象car强转为子类对象BigCar
bc.setName("ssss");//这里就可以调用子类的方法
test(new BigCar());
}
public static void test(Car car) {
BigCar bigCar = (BigCar) car;
if (bigCar instanceof Car) {
System.out.println("1");
}
}

最后调用了当前类中的重载方法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;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
} if (ifModifiedSince < lastModified / 1000L * 1000L) {
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方法实际上是接收了所有类型的请求,那么可以针对不同请求重写相应的方法,来简化我们的操作。

一般装饰者就是在主体组件扩展到具体的实现类时,会引入一个中间层,把装饰者的公布部分引入进来,在引入具体的实现时,只需要实现自己特定的部分就行了。公共的就放在上面,中间层中。而GenericServlet类就可以看作是那个中间层,它在空实现Servlet类的方法后,子类在继承的时候就可以只重写需要的方法,不必重写Servlet类的所有方法了。

MVC案例

学了这么多,现在就来动手实现一个MVC简单登录案例

MVC模式与Servlet执行流程的更多相关文章

  1. Servlet执行流程和生命周期【慕课网搬】

    Servlet执行流程(GET方式为例) 首先用户客户端浏览器发出Get方式(点击超链接方式)向浏览器发出请求. 服务器接收到客户端点击超链接,接收到GET请求之后,服务器到WEB.xml中<s ...

  2. 【JAVA】servlet执行流程

    servlet执行流程 客户端发出http请求,web服务器将请求转发到servlet容器,servlet容器解析url并根据web.xml找到相对应的servlet,并将request.respon ...

  3. Servlet执行流程和生命周期

    Servlet执行流程 Get方式请求HelloServlet ---> <a href="servlet/HelloServlet"> ↓ 服务器在配置文档中查 ...

  4. Spring 框架基础(06):Mvc架构模式简介,执行流程详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.SpringMvc框架简介 1.Mvc设计理念 MVC是一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集 ...

  5. Spring MVC必须知道的执行流程

    Spring MVC的执行流程 一.名词解释 1.前端控制器(DispatcherServlet) 接收请求,响应结果,相当于转发器,中央处理器 2.处理器映射器(HandlerMapping) 根据 ...

  6. Spring MVC 原理介绍(执行流程)

    Spring MVC工作流程图   图一   图二    Spring工作流程描述       1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServle ...

  7. Servlet 执行流程 生命周期 ServletConfig 线程安全

    Day34 servlet 三.如何使用Servlet 1.继承GenericServlet类(通用) (1)GenericServlet类有一个关键的设计,定义了一个私有的ServletConfig ...

  8. servlet执行流程

    视频地址:http://www.imooc.com/video/5550      1-6 用户输入地址:localhost:8080/MyFirstServletDemo/index.jsp (My ...

  9. java web简易网上书店项目系列,使用MVC模式(servlet+jstl+dbutils),开篇

    一. 针对很多java web初学者入门困难的问题,笔者利用一个小型web项目,一步一步的展示java web开发方法,每一个章节引入一些java web开发的重点知识,让同学们可以将java web ...

随机推荐

  1. vue实现无缝滚动

    vue实现无缝滚动 标签部分 <div style="height: 260px; width: 50%;display: inline-block;float: right; ove ...

  2. Netflix 开源 Polynote:对标 Jupyter,一个笔记本运行多种语言

    谈到数据科学领域的开发工具,Jupyter 无疑是非常知名的一种.它具有灵活高效的特点,非常适合进行开发.调试.分享和教学.近日,Netflix(奈飞)居然也玩起了跨界,他们开源了一个名为 Polyn ...

  3. 常见 MIME 类型列表(转)

    本文转自:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MI ...

  4. Windows之Java开发环境快速搭建

    说明:Node.js非必须,通常中小公司或创业公司,基本上都要求全栈. 补充说明: 除此之外,当公司固定JDK.Maven.Idea.Git.Node.js及其相关IDE等版本时,运维人员或者Team ...

  5. Linux 系统调用 —— fork 内核源码剖析

    系统调用流程简述 fork() 函数是系统调用对应的 API,这个系统调用会触发一个int 0x80 的中断: 当用户态进程调用 fork() 时,先将 eax(寄存器) 的值置为 2(即 __NR_ ...

  6. 【RN - 基础】之React Native常见问题及解决方案

    unable to load script from assets index.android.bundle... 问题原因: 找不到Android项目中的assets文件夹. 解决方案: 1.在An ...

  7. OSI-传输层

    OSI-传输层 端口号(2字节 SYN(1bit) ACK(1bit) 会话多路复用(为什么一个IP地址可以做很多事情?) 源端口地址可以不同 五元组(世界上没有相同的2个五元组) 源IP地址-目的I ...

  8. Find命令、文件名后缀、Linux和Windows互传文件 使用介绍

    第2周第5次课(3月30日) 课程内容: 2.23/2.24/2.25 find命令2.26 文件名后缀 2.27 Linux和Windows互传文件 find命令 文件查找: 1.which(一般用 ...

  9. 爬取豆瓣热销书榜前250 生成.csv文件

    from lxml import etreeimport requestsimport csvfp = open('E:/doubanbook.csv','wt',newline='',encodin ...

  10. 谁说微服务是Spring Cloud的独角戏?Service Mesh了解一下?

    Service Mesh 的概念自 2017 年初提出之后,受到了业界的广泛关注,作为微服务的下一代发展架构在社区迅速发酵,并且孵化出了诸如 Istio 等广受业界关注的面向于云原生 (Cloud N ...