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. 4.vim编辑器

    把光标移动文件头 gg 把光标移动文件尾 G 移动到行首 ^ 移动到行尾 $ 移动到指定行 :n 回车

  2. nslookup命令查找域名

    了解 DNS 域名服务 熟悉使用 nslookup 查找 DNS 服务器上登记的域名,记录几次查询的结果, 及服务器的 ip. 1. 某个子域下的一部分主机的名字- IP 地址对应关系,如 flame ...

  3. 【POJ 2823】【Luogu P1886】Sliding Window 滑动窗口

    POJ 2823 Luogu P1886 [解题思路] 这是一个单调队列算法的经典题目,几乎学习单调队列的人都接触过这题. 利用单调队列算法求出每一个固定区间内的最(大/小)值. 以下以最大值为例: ...

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

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

  5. 跨平台c开发库tbox:内存库使用详解

    TBOX是一个用c语言实现的跨平台开发库. 针对各个平台,封装了统一的接口,简化了各类开发过程中常用操作,使你在开发过程中,更加关注实际应用的开发,而不是把时间浪费在琐碎的接口兼容性上面,并且充分利用 ...

  6. 用 python 分析基金!让赚钱赢在起跑线!

    你不理财,财不理你!python 也能帮你理财? 效果预览 累计收益率走势图 基本信息结果 如何使用: python3 + 一些第三方库 import requests import pandas i ...

  7. C++桌面计算机

    #include<iostream> #include<string> #include<map> #include<cctype> using nam ...

  8. Chapter 07-Basic statistics(Part2 Frequency and contingency tables)

    这一部分使用在vcd包中的Arthritis数据集. > library(vcd) 载入需要的程辑包:MASS 载入需要的程辑包:grid 载入需要的程辑包:colorspace > he ...

  9. centOS7 可以ping通主机不能访问外网

    前言: 突然打开自己前不久在虚拟机安装的centOS7系统,发现以前可以来联网突然不能访问外网,在网上看了很多方法,终于解决 问题描述: 连上网,但是ping 不同外网,如ping www.baodu ...

  10. Maven项目多环境之间的配置文件的切换

    前言:对于一个项目,开发和生产环境之间会使用不同的配置文件,最简单的例子就是数据库连接池的配置了.当然,可以在打包上线前对配置文件进行替换,不过这也太low了吧. 简单的pom.xml中的配置内容 比 ...