这些天自己学习了一下Servlet,有一些收获,写一个博客复习一下,同时分享给大家
首先我们需要了解一下什么是Servlet?
servlet在我看来是用来沟通服务器和java程序的桥梁。用户首先在浏览器上向服务器发出请求,服务器接受到请求之后通过servlet里面的doget或者dopost方法进行处理,处理结果提交给服务器,同时服务器对请求的浏览器发出响应。
而Servlet是一个java的接口,我们通过实现这个接口从而在web服务器那里实现功能
假设我们与后端交互的服务器是Tomcat服务器,那么一个servlet对象的生命周期是:
- 当用户在地址栏输入url: http://localhost:8080/
- web容器截取请求路径,并且在容器上下文中找请求路径
- 如果没有找到对应的Servlet对象咋么办?(实际服务器启动的时候就已经把web.xml文件解析好了,放入map中)
通过web.xml文件中相关的配置信息,得到请求 通过反射机制调用servlet类的无参数构造方法,完成Servlet类的实例化
web容器调用servlet对象的init方法完成初始化操作
web容器调用Servlet对象的方法提供服务
- 若找到对应的Servlet对象web容器直接调用servlet对象的service方法提供服务
- web容器关闭的时候/webapp重新部署的时候/该Servlet对象长时间不访问的时候 web容器会将该servlet对象销毁,在销毁该对象之前web容器调用destory方法销毁
我们可以总结一下:
- Servlet类的构造方法只执行一次
- Servlet对象的init方法值只执行一次
- Servlet对象的service方法,只要用户请求一次,则执行一次
- Servlet对象的destory方法只执行一次
注意重点:
service方法是只要用户请求一次就执行一次的
init方法执行的时候,Servlet对象已经创建好了
destroy方法执行的时候,Servlet对象还没有被销毁,即将被销毁
Servlet对象是单例,但是不符合单例模式,只能称为伪单例。
真单例的构造方法是私有化的,Tomcat服务器是支持多线程的
所以Servlet对象在单实例多线程的环境下运行的
那么servlet对象中若有实例变量,并且实例变量涉及到修改操作,那么这个Servlet对象一定会存在线程安全问题
不建议在Servlet对象中使用实例变量,尽量使用局部变量
那么问题来了--------------------->Servlet对象实例化后,这个对象存到哪里了?
大多数WEB容器都是将该Servlet对象以及对应的url-pattern存储到map集合中:
WEB容器中有这样一个MAP集合
Map<String,Servlet>
key value
-------------------------------
/login LoginServlet对象引用
/delate DelateServlet对象引用
/save SaveServlet对象引用
服务器在启动的时候就会解析各个Webapp的web.xml文件,所以需要把配置文件中的类的名字和对应的路径放到某一个集合中
将web.xml中的url-pattern 和对应类名存储到map中:
Map<String,String>
key value
-------------------------------
/login com.anine.test.LoginServlet
.......
下面我们研究一下servlet中的几个方法什么时候编写什么代码:
-
无参数的构造方法[尽量别动构造函数] :创建对象之后执行的
-
init方法
-----------以上两个方法,执行时间几乎相同,执行次数都是一次*****-----------------
其实尽量别在构造方法里面写东西,尽量把对象创建时刻要写的方法写在init中
因为写在构造函数中存在风险 :当程序员编写构造方法的时候,可能会导致无参数的构造方法不存在
比如突然写了一个有参数的构造方法init是SUN公司为javaweb程序员专门提供的初始化时刻,若希望在初始化时刻执行一段特殊的程序,这个程序可以编写到init方法中
-
service 方法
必然要重写的,因为需要完成业务所及的处理,请求的处理,以及完成响应,
而且这个方法中的代码最有价值
也是最难写的。 -
这个方法是SUN公司为javaweb程序员提供的一个特殊时刻,这个特殊时刻被称为对象的销毁时刻
若希望在销毁时刻执行一段特殊的代码,需要将这段代码编写到destory方法,自动被容器调用
下面我们了解一下ServletConfig接口
我们可以创建两个Servlet对象产生一下对应的ServletConfig接口对象
AServlet’s ServletConfig is org.apache.catalina.core.StandardWrapperFacade@49ab9c7d
BServlet’s ServletConfig is org.apache.catalina.core.StandardWrapperFacade@2c8a75d0
我们可以观察出,不同的Servlet对象拥有不同的ServletConfig对象
插一句嘴:
其实我们一直在面向接口编程
-
javax.servlet.ServletConfig是接口
-
Apache Tomcat服务器实现了servlet规范,Tomcat服务器专门写了一个ServletConfig接口的实现类
实现的类名org.apache.catalina.core.StandardWrapperFacade -
面向这个ServletConfig接口编程的
WEB容器实现了接口,我们可以调用 -
同学!Tomcat服务器你怎么理解?
Tomcat服务器是一个实现了Servlet规范和JSP规范的容器 -
研究ServletConfig接口都有啥方法
-String getInitParameter(String name); 获取所有初始化参数的名字 -Enumeration getInitParameterNames(); 返回一堆东西,应该是集合 -String getServletContext();获取ServletName <servlet-name>b</servlet-name> -String getServletName();获取Servlet上下文
好了,我们继续研究ServletConfig到底是个啥?
ServletConfig是一个Servlet对象的适配信息对象,ServletConfig对象中封装了一个servlet对象的配置信息。
Servlet对象的配置信息在web.xml文件中。
web.xml的配置信息封装到了ServletConfig中
因为一个Servlet对应一个标签,所以内存地址是不一样的
一个Servlet对象对应一个servletConfig对象。
我们再来看一下ServletContext是一个什么接口?
还是举一个例子:假设有两个Servlet对象
AServletContext is org.apache.catalina.core.ApplicationContextFacade@43df86ff
BServletContext is org.apache.catalina.core.ApplicationContextFacade@43df86ff
我们可以进一步总结出,所有的Servlet对象共享一个ServletContext
ServletContext到底是什么?什么时候被创建?什么时候被销毁?
ServletContext被翻译为:Servlet上下文
一个WEBAPP只有一个ServletContext对象
一个WEBAPP只有一个web.xml文件
web.xml在服务器启动的时候被解析
ServletContext在服务器启动阶段实例化
ServletContext在服务器关闭阶段被销毁
ServletContext对应的是web.xml文件,是web.xml文件的代表
还有人说ServletContex是所有Servlet对象四周的环境代表
.ServletContext接口中有哪些方法?
- void setAttribute(String name,Object object);//向ServletContext范围中绑定数据map.put(key,value)
- Object getAttribute(String name);//从ServletContext范围中获取数据map.get(key)
- void removeAttributes(String name);//移除ServletContext范围中的数据map.remove(key)
- String getInitParamter(String name);
- Enumeration getInitParamterNames();
- String getRealPath(String path);
//获取文件绝对路径
最后的最后,我们来研究一下Servlet、ServletConfig、ServletContext之间的关系?
-- 一个Servlet对应一个ServletConfig
-- 100个Servlet对应100个servletConfig
--所有的Servlet共享一个ServletContext对象[在同一个webapp中,所有的Servlet对象共享同一个四周环境对象,该对象就是ServletContext]
所有用户若想共享同一个数据,可以将这个数据放到ServletContext对象中。
一般放到ServletContext中的数据,是不建议涉及到修改操作的,因为ServletContext是多线程共享的对象,修改的时候会存在线程安全问题