Servlet运行原理以及生命周期
一、Servlet生命周期:
Servlet加载、实例化、初始化、服务、销毁。

1、初始化init():
当服务启动时,Servlet被装入tomcat或者其他服务器容器时执行(服务器容器从启动到停止期间唯一的一次)init()初始化方法,负责初始化Servlet对象,无论有多少个请求访问Servlet,初始化init()只会启动一次,不会重复执行。

2、服务service:
服务service方法是Servlet核心,该方法有两个参数HttpServletRequest arg0, HttpServletResponse arg1:
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。
request和response对象即然代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了。要向客户机输出数据,只需要找response对象就行了。
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。
HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法。查看HttpServletResponse的API,可以看到这些相关的方法。
在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的do功能(这种doXxx的方法也叫钩子方法如doGet,doPost)。
如果在继承HttpServlet的类中对Serlvet进行重写,那么客户端请求Serlvet的时候,就会
去子类中调用重写的service方法(一般不对Serlvet方法进行重写)

3、销毁destroy():
Serlvet在tomcat等服务器停止运行且卸载它时调用销毁destroy()方法,因为service方法运行时有可能有多个线程,当执行了销毁destroy()方法,这些线程就全部终止。

二、Servlet与Tomcat等服务器关系:
- web客户端 向Servlet容器(Tomcat)发出Http请求
- Servlet容器接收web客户端的请求
- Servlet容器创建一个HttpRequest对象,将Web
Client请求的信息封装到这个对象中。 - Servlet容器创建一个HttpResponse对象
- Servlet容器调用HttpServlet对象的service方法,把HttpRequest对象与HttpResponse对象作为参数传给 HttpServlet 对象。
- HttpServlet调用HttpRequest对象的有关方法,获取Http请求信息。
- HttpServlet调用HttpResponse对象的有关方法,生成响应数据。
- Servlet容器把HttpServlet的响应结果传给Web
Client。

三、Servlet工作原理:
1、当web客户端发送一个Http请求,Servlet创建HttpRequest对象和HttpResponse对象,将web客户端请求的信息封装到HttpRequest对象中,Servlet将HttpRequest对象和HttpResponse对象作为参数传递给HttpServlet中的service()方法,通过HttpRequest中封装的Http请求信息获取请求方式对请求进行响应的,选择调用doGet,doPost等这些钩子方法,然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应。在Servlet接口和GenericServlet中是没有doGet()、doPost()等等这些钩子方法的,HttpServlet中定义了这些方法,但是都是返回error信息,所以,我们每次定义一个Servlet的时候,都必须实现doGet或doPost等这些方法。
如果服务器启动时就创建Servlet,那么还需要在web.xml文件中配置<load-on-startup>1</load-on-startup>。Servlet是在第一次被访问时由服务器创建的,而且一个Servlet类型,服务器只创建一个实例对象,它是单例的。
2、每一个自定义的Servlet都必须实现Servlet的接口,Servlet接口中定义了五个方法,其中比较重要的三个方法涉及到Servlet的生命周期,分别是上文提到的init(),service(),destroy()方法。GenericServlet是一个通用的,不特定于任何协议的Servlet,它实现了Servlet接口。而HttpServlet继承于GenericServlet,因此HttpServlet也实现了Servlet接口。所以我们定义Servlet的时候只需要继承HttpServlet即可。
服务器接收到一次请求,就会调用service() 方法一次。
3、Servlet接口和GenericServlet是不特定于任何协议的,而HttpServlet是特定于HTTP协议的类,所以HttpServlet中实现了service()方法,并将请求ServletRequest、ServletResponse 强转为HttpRequest 和 HttpResponse。
四、创建Servlet对象
1、Servlet容器启动时:读取web.xml配置文件中的信息,构造指定的Servlet对象,创建ServletConfig对象,同时将ServletConfig对象作为参数来调用Servlet对象的init方法。
2、在Servlet容器启动后:客户首次向Servlet发出请求,Servlet容器会判断内存中是否存在指定的Servlet对象,如果没有则创建它,然后根据客户的请求创建HttpRequest、HttpResponse对象,从而调用Servlet 对象的service方法。
3、Servlet Servlet容器在启动时自动创建Servlet,这是由在web.xml文件中为Servlet设置的<load-on-startup>属性决定的。从中我们也能看到同一个类型的Servlet对象在Servlet容器中以单例的形式存在。

三、Servlet概述
Servlet是JavaWeb的三大组件之一,它属于动态资源。都会在web.xml中配置,例如如上图
Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:
Tomcat服务器会帮助我们将请求的数据封装在request对象
Tomcat同样会创建respose对象给我们使用,让我们响应 HttpServletRequest extends ServletRequest
例如客户端发出登录请求,或者输出注册请求,这些请求都应该由Servlet来完成处理!
我们需要实现自己的逻辑业务就需要自己来编写Servlet,每个Servlet必须实现javax.servlet.Servlet接口。
实现Servlet有三种方式:
1.实现javax.servlet.Servlet接口;
2.继承javax.servlet.GenericServlet类;
3.继承javax.servlet.http.HttpServlet类;
开发中通常我们会去继承HttpServlet类来完成我们的Servlet,生命周期方法由Tomcat来调用,我们只是完成接受请求,然后响应,完成业务逻辑代码
Tomcat服务器帮助我们完成不变的代码,我们来完成业务需求变化的代码
我们的代码和Tomcat代码合起来构成一个完成的代码
四、补充:
近期发现对:
1、为什么不建议重写service方法?
2、servlet中为什么一定要重写doGet以及doPost方法?
3、servlet的父类;
有了新的认识,进行补充;
1、为什么不建议重写service方法?
因为客户端每一次发送请求,服务端都会调用一次servlet中service方法,而service方法其实是类似调度的功能,
service方法源码:
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod();
if(method.equals("GET"))
{
long lastModified = getLastModified(req);
if(lastModified == -1L)
{
doGet(req, resp);
} else
{
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if(ifModifiedSince < (lastModified / 1000L) * 1000L)
{
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else
{
resp.setStatus(304);
}
}
} else
if(method.equals("HEAD"))
{
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else
if(method.equals("POST"))
doPost(req, resp);
else
if(method.equals("PUT"))
doPut(req, resp);
else
if(method.equals("DELETE"))
doDelete(req, resp);
else
if(method.equals("OPTIONS"))
doOptions(req, resp);
else
if(method.equals("TRACE"))
{
doTrace(req, resp);
} else
{
String errMsg = lStrings.getString("http.method_not_implemented");
Object errArgs[] = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
可以看出来,如果我们重写了service方法,没有实现对doGet和doPost等doxxx方法的调用,那么请求就得不到处理。
如果不对service方法重写,那么会执行HttpServlet方法中service方法。
2、servlet中为什么一定要重写doGet以及doPost方法?
因为在service方法对请求的方式进行了匹配,如Get方法就调用doGet方法,所以一定要根据业务逻辑对doGet或者doPost等doxxx方法进行重写
3、servlet的父类
GenericServlet是Servlet接口的实现类,我们可以通过继承GenericServlet来编写自己的Servlet。
GenericServlet还实现了ServletConfig接口,所以可以直接调用getInitParameter()、getServletContext()等ServletConfig的方法。
具体源码可以反编译去查看:









GenericServlet的init()方法
在GenericServlet中,定义了一个ServletConfig config实例变量,并在init(ServletConfig)方法中把参数ServletConfig赋给了实例变量。然后在该类的很多方法中使用了实例变量config。
如果子类覆盖了GenericServlet的init(StringConfig)方法,那么this.config=config这一条语句就会被覆盖了,也就是说GenericServlet的实例变量config的值为null,那么所有依赖config的方法都不能使用了。如果真的希望完成一些初始化操作,那么去覆盖GenericServlet提供的init()方法,它是没有参数的init()方法,它会在init(ServletConfig)方法中被调用。




HttpServlet类是GenericServlet的子类,它提供了对HTTP请求的特殊支持,所以通常我们都会通过继承HttpServlet来完成自定义的Servlet。










HttpServlet覆盖了service()方法
HttpServlet类中提供了service(HttpServletRequest,HttpServletResponse)方法,这个方法是HttpServlet自己的方法,不是从Servlet继承来的。在HttpServlet的service(ServletRequest,ServletResponse)方法中会把ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse,然后调用service(HttpServletRequest,HttpServletResponse)方法,这说明子类可以去覆盖service(HttpServletRequest,HttpServletResponse)方法即可,这就不用自己去强转请求和响应对象了。
就是直接继承HttpServlet,然后无需进行重写,就可以实现ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse,因为在HttpServlet类已经实现了这一操作

借鉴于https://blog.csdn.net/tanyunlong_nice/article/details/42536461
Servlet运行原理以及生命周期的更多相关文章
- HTTP协议 Servlet入门 Servlet工作原理和生命周期 Servlet细节 ServletConfig对象
1 HTTP协议特点 1)客户端->服务端(请求request)有三部份 a)请求行--请求行用于描述客户端的请求方式.请求的资源名称,以及使用的HTTP协议版本号 请求行中的GET ...
- jsf的运行原理及生命周期
一.jsf(java server faces)的运行原理(工作方式) 1.jsf应用是事件驱动的,当一个事件发生时(比如用户单击一个按钮),事件通知通过HTTP发往服务器,服务器端使用叫做Faces ...
- SpringMVC内容略多 有用 熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器、过滤器等Web组件以及MVC架构模式进行Java Web项目开发的经验。
熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器.过滤器等Web组件以及MVC架构 ...
- Servlet 运行原理
一:servlet定义 Servlet是一个Java应用程序,运行在服务器端,用来处理客户端请求并作出响应的程序. 二:简单servlet实例 //导入所需的包 import javax.servle ...
- JavaWeb之 Servlet执行过程 与 生命周期
Servlet的概念 什么是Servlet呢? Java中有一个叫Servlet的接口,如果一个普通的类实现了这个接口,这个类就是一个Servlet.Servlet下有一个实现类叫HttpServle ...
- [转]JavaWeb之 Servlet执行过程 与 生命周期
https://www.cnblogs.com/vmax-tam/p/4122105.html Servlet的概念 什么是Servlet呢? Java中有一个叫Servlet的接口,如果一个普通的类 ...
- PHP的工作原理和生命周期
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u013778883/article/details/79831035 php是一门适用于web开 ...
- JavaEE Servlet 核心方法及生命周期
做JavaWeb开发,免不了要和Servlet打交道.Servlet是Sun(Oracle)官方定义的一个Web开发规范,所有Servlet开发都必须遵守.自己以前也没有从头做过Web开发,所以这方面 ...
- 【servlet】Servlet的API和生命周期]
创建时间:6.15 一.Servlet的API(生命周期) (1)Servlet接口中的方法 1)init(ServletConfig config) 何时执行:servlet对象创建的时候执行 Se ...
随机推荐
- Laravel 5.4设置logout注销账户的重定向路径
当我们修改Laravel默认Auth默认路径时,在点击logout按钮注销时,默认跳转的地址为项目的根目录, 若想设置成自定义的重定向路径,可以按照如下设置: 方法一: 在Auth \ LoginCo ...
- jq 点击按钮显示div,点击页面其他任何地方隐藏div
css .bl_rencai_32{ float: left; height: 35px; line-height: 35px; } .bl_rencai_32 >input{ width: 3 ...
- 补充:MySQL整理
1.连接Mysql 格式: mysql -h主机地址 -u用户名 -p用户密码 1.连接到本机上的MYSQL.首先打开DOS窗口,然后进入目录mysql\bin,再键入命令mysql -u root ...
- C语言定义的操作mysql数据库的接口
编写的环境:centos7系统下,对mysql的衍生mariadb进行数据库的操作,包含设置访问数据库的参数,查询数据库和增删改数据库的三个功能.对于查询数据库,我这里允许不返回查询结果,用于判断查询 ...
- windows系统dos下查看无线网密码
(1)采用命令:netsh wlan show profiles 查看电脑连接过的无线网: (2)采用命令:netsh wlan show profile name ="wifi 名字&qu ...
- springboot+mybatis+druid数据库连接池
参考博客https://blog.csdn.net/liuxiao723846/article/details/80456025 1.先在pom.xml中引入druid依赖包 <!-- 连接池 ...
- Gym 101981J - Prime Game - [数学题][线性筛+分解质因数][2018-2019 ACM-ICPC Asia Nanjing Regional Contest Problem J]
题目链接:http://codeforces.com/gym/101981/attachments 题意: 令 $mul(l,r) = \prod_{i=l}^{r}a_i$,且 $fac(l,r)$ ...
- 复习C++:VS2008中的宏干嘛用的
VS2008中有宏,可也进行编辑和设置. 好处: 1.快速生成代码,帮助开发. 2.个人定制化功能,IDE更合适自己用. 3.提升编程效率. 缺点: 使用VB开发,一开始用起来费事.不过有官方参考 ...
- 自动化安装-【kickstart】
批量自动安装软件介绍 kickstart 是一种无人值守的安装方式,工作原理是在安装过程中记录人工干预填写的各种参数,并生成以个名为ks.cfg(自动应答文件)的文件,如果在自动安装过程中出现要填写参 ...
- Linux下批量杀掉筛选进程
在做项目的时候,由于情况要求,需要把服务器上符合某一条件的进程全部kill掉,但是又不能使用killAll直接杀掉某一进程名称包含的所有运行中的进程(即我们可能只需要杀掉某一类含有特定参数命令的进程) ...