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. HBase 基本入门

    目录 一.简介 有什么特性 与RDBMS的区别 二.数据模型 三.安装HBase 四.基本使用 表操作 五.FAQ 参考文档 无论是 NoSQL,还是大数据领域,HBase 都是非常"炙热& ...

  2. IDEA连接Redis

    1.创建一个Maven项目 2.在src下的pom.xml文件里,添加相关包引用 <?xml version="1.0" encoding="UTF-8" ...

  3. 【Luogu P1439】最长公共子序列(LCS)

    Luogu P1439 令f[i][j]表示a的前i个元素与b的前j个元素的最长公共子序列 可以得到状态转移方程: if (a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1; d ...

  4. MySql分库分表与分区的区别和思考

    一.分分合合 说过很多次,不要拘泥于某一个技术的一点,技术是相通的.重要的是编程思想,思想是最重要的.当数据量大的时候,需要具有分的思想去细化粒度.当数据量太碎片的时候,需要具有合的思想来粗化粒度. ...

  5. NLog日志框架使用探究-2

    目录 前言 自定义参数 日志输出方式 文件 网络传输 数据库 科学使用 参考文档 前言 在一年前,我写过一篇关于NLog入门文章<NLog日志框架使用探究-1>,文章简单的介绍了Nlog的 ...

  6. 2019牛客暑期多校训练营(第九场) E-All men are brothers(并查集+组合数学)

    >传送门< 题意:最初有 n个人且互不认识,接下来 m行,每行有 x,y表示x和y交朋友,朋友关系满足自反性和传递性,每次输出当前选取4个人且互不认识的方案数. 思路:比赛的时候知道是用并 ...

  7. 【Android - 控件】之MD - CoordinatorLayout的使用

    CoordinatorLayout是Android 5.0新特性——Material Design中的一个布局控件,主要用来协调各个子视图之间的工作,也可以用来作为顶部布局.CoordinatorLa ...

  8. 腾讯iphone面试题(转)

    1Objective-C内部的实现 2CALayer和View的关系 3 http协议,tcp/ip 4 UITableView的那些元素是可以自定义的? 5 c语言的,定义变量,比如int,在什么情 ...

  9. c, ANSI C, embedded c, after IKM online assessment

    C programming language was developed in 1972 by Dennis Ritchie at bell laboratories of AT&T (Ame ...

  10. 还在用背单词App?使用Python开发英语单词自测工具,助你逆袭单词王!

    学英语广告 最近也许是刚开学的原因,不管是公众号,还是刷抖音,导出都能看到关于学英语.背单词的广告. 不知道现在学生们背单词买的什么辅导材料.反正我们上学那会,<星火阅读>特别的火.记得当 ...