1、Servlet的本质是什么?
Servlet是服务器端的小java程序,这个小java程序不能随意编写,必须实现SUN制定的javax.servlet.Servlet接口,实现其中的方法。Servlet是一个满足java规范的java类。Servlet既然满足Servlet规范,Tomcat服务器我们可以叫做“WEB容器(Container)”,那么Servlet 就可以叫做容器中的“组件(Component)”。
2、关于Servlet对象的生命周期
- 什么是生命周期?
- 生命周期表示一个java对象从最初被创建到最终销毁经历的所有过程。
- Servlet对象的生命周期是谁来管理的?程序员可以干涉吗?
- Servlet对象的生命周期,javaweb程序员是无权干涉的,包括该Servlet对象的相关方法的调用,javaweb程序员也是无权干涉的。
- Servlet对象从最初的创建,方法的调用,以及最对象的销毁整个过程,是由WEB容器来管理的。
- Web Container管理Servlet对象的生命周期。
- 默认情况下,Servlet对象在WEB服务器启动阶段不会被实例化。【若希望在web服务器启动阶段实例化Servlet对象,需要进行特殊的设置】
- 描述Servlet对象的生命周期
- 用户在浏览器地址栏上输入URL:http:// localhost:8080/pnj-servlet-03/testLifeCycle
- web容器截取请求路径:/servlet-03/testLifeCycle
- web容器在容器上下文中找请求路径/pnj-servlet-03/testLifecycle对应的Servlet对象
- 若没有找到相应的Servlet对象
- 通过web.xml文件中相关的配置信息,得到请求路径/testLifeCycle对应的Servlet完整类名
- 通过反射机制,调用Servlet类的无参数构造方法完成Senvlet对象的实例化
- web容器调用Servlet对象的init方法完成初始化操作
- web容器调用Servlet对象的service方法提供服务
- 若找到应的Senvlet对象
- web容器直接调用Servlet对象的service方法提供服务
- Servlet对象从最初的创建,方法的调用,以及最对象的销毁整个过程,是由WEB容器来管理的。
- web容器关闭的时候/webapp重新部署的时候/该Servlet对象长时间没有用户再次访问的时候web容器会将该Servlet对象销毁。在销毁该对象之前,web容器会调用Servlet对象的destroy方法,完成销毁之前的准备。
- Servlet对象是单例,但是不符合单例模式,只能称为伪单例。真单例的构造方法是私有化的,Tomcat服务器是支持多线程的【单实例多线程环境下运行的一个java对象】。所以Servlet对象在单实例多线程的环境下运行的。那么Servlet对象中若有实例变里,并且实例变里涉及到修改操作,那么这个Servlet对象一定会存在线程安全问题,不建议在Servlet对象中使用实例变量,尽量使用局部变量。
-
若希望在web服务器启动阶段实例化Servlet对象,需要在web.xml文件中进行相关的配置,例如:
-
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0"> <servlet> <servlet-name>testLifeCycle</servlet-name> <servlet-class>myweb.testLifeCycle</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>testLifeCycle</servlet-name> <url-pattern>/testLifeCycle</url-pattern> </servlet-mapping> <servlet> <servlet-name>WelcomeServlet</servlet-name> <servlet-class>myweb.WelcomeServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>WelcomeServlet</servlet-name> <url-pattern>/WelcomeServlet</url-pattern> </servlet-mapping> </web-app>
-
<load-on-startup>1</ load-on-startup>自然数越小优先级越高
-
- web.xml文件在服务器启动阶段被解析,若web.xml文件编写有错误,启动Tomcat服务器的时候,当前webapp启动失败。
- Servlet对象“默认情况”下,在服务器启动阶段是不会实例化的,不会创建对象。
- 在Servlet类中最好不要手动编写任何构造函数,这样做可能会导致无参数构造函数不存在,这样通过反射机制创建对象的时候,会出现实例化异常。Servlet对象创建失败
3、Servlet对象的生命周期是什么样的,什么时候创建,创建几次,什么时候销毁?
- 假设客户端向web服务器发送的请求是/login请求,当用户向web服务器第一次发送/login请求的时候,Tomcat在容器中搜索/login对象的Servlet对象,但是没有找到该对象,此时会从web.xml文件中获取/login对象的完整Servlet类名,通过反射机制,调用Servlet的无参数构造方法创建Servlet对象,马上调用init方法完成Servlet对象的初始化操作,然后调用service方法提供核心服务。
- 当用户第2+次再发送/login请求的时候,Tomcat还是在容器中搜索/login对象的Servlet对象,此时可以找到该对象,直接调用该对象的service方法提供核心服务。
- 当用户长时间没有访问该Servlet,或者服务器关闭,或者项目重新部署的时候,Tomcat容器会去回收Servlet对象所占用的内存,在回收该内存之前调用该Servlet对象的destroy方法,完成回收之前的准备。
- 结论:
- Servlet类的构造方法只执行一次。
- Senvlet对象的init方法只执行一次,init方法执行的时候,Servlet对象已经被创建好了。
- Servlet对象的service方法,只要用户请求一次,则执行一次。service方法执行次数最多,因为在这个方法中需要提供服务,处理当前的请求,这是核心方法,用户访问的每一次都是要执行的。
- Servlet对象的destroy方法只执行一次,destroy方法执行的时候,Servlet对象还没有被销毁,即将被销毁。
- 其实init、destroy方法都是SUN公司为javaweb程序员准备的特殊的时刻,初始化时刻/销毁时刻,一般这两个方法中是不需要编写任何代码的,但是在特殊的情况下,例如:需求要求在对象被初始化的那一刻记录日志,那么记录日志的代码就编写到init方法中,例如:需求要求在该Servlet对象被销毁的那一刻记录日志,那么记录日志的代码就需要编写到destroy方法。自然会被服务器调用并执行。
4、Servlet对象的生命周期由Tomcat容器管理,对象的创建,对象内存的释放,还有对象中的方法调用都是由Tomcat容器完成,程序员不能干涉,只能编写该类实现Servlet接口,将其配置在web.xml文件中。
5、Servlet对象是单实例的,并且是在多线程的环境下运行,可能存在线程并发带来的安全问题。
6、什么情况下在init方法中编写程序?什么情况下在service方法中编写程序?什么情况下在destroy方法中编写程序?
- init方法是SUN规范中为程序员提供的一个对象初始化时机,这是一个特定的时刻,有的时候我们需要在这个特定的时刻执行一段特定的程序,此时将该程序写入init方法,例如:项目经理要求在Servlet对象创建时刻记录日志,请将该程序编写到init方法中。对象第一次创建的时候执行记录日志,并且只执行一次,记录一次日志信息。(init方法一般很少用)
- Service方法是Servlet的核心业务方法,核心业务都在该方法中完成,只要编写一个Servlet,service方法是一定要编写代码的,完成业务的处理。(常用)
- destroy方法init方法相同,只不过是一个不同的时机。(destroy方法一般很少使用)
7、Senxlet对象实例化之后,这个Servlet对象被存储到哪里了?
大多数的WEB容器都是将该Servlet对象以及对应的url-pattern存储到Nap集合中了。
在WEB容器中有这样一个Map集合 Map<String,Servlet>集合 | |
key | value |
/login | Loginservlet对象引用 |
/delete | DeleteServlet对象引用 |
/save | SaveServlet对象引用 |
服务器在启动的时候就会解析各个webapp的web.xml文件,将web.xml文件中的url-pattern和对应的Servlet完整类名存储到Map集合中了。
8、Servlet接口中的这些方法中编写什么代码?什么时候使用这些方法?
- 无参数构造方法【以后就不需要再考虑构造函数了,尽量别动构造函数】
- init方法
- 以上两个方法执行时间几乎是相同的,执行次数都是一次,构造方法执行的时候对象正在创健,init方法执行的时候对象已经创建。
- 若系统要求在对象创建时刻执行一段特殊的程序,这段程序尽里写到init方法中。
- 为什么不建议将代码编写到构造函数中呢?存在风险!当程序员编写构造方法的时候,可能会导致无参数构造方法不存在。一个类不编写任何构造函教,默认有一个无参数的构造方法,但是一旦编写一个有参数的构造方法之后,系统则不再提供无参数枸造函数。
- Servlet中的init方法是SUN公司为javaweb程序员专门提供的一个初始化时刻。若希望在初始化时刻执行一段特殊的程序,这个程序可以编写到init
- service方法
- 这个方法是必然要重写的,因为在这个方法需要完成业务逻辑的处理、请求的处理、以及完成响应。而且这个方法中的代码是最有价值的。
- 也是最难写的,因为最难编写的就是业务代码啦。
- destroy方法
- 这个方法也是SUN公司为javaweb程序员提供的一个特殊的时刻,这个特殊的时刻被称为对象销毁时刻,若希望在销毁时刻执行一段特殊的代码,需要将这段代码编写到destroy方法,自动被容器调用。
- 回顾:类加载时刻执行程序,代码写到哪里?编写到静态代码块中。
- 结论:sun公司为我们程序员提供了很多个不同的时刻。若在这个特殊时刻执行特殊程序,这些程序是有位置编写的。