Servlet学习补充
=============================================================================
Servlet是sun公司提供的一门用于开发动态web资源的技术。
Sun公司在其API中提供了一个servlet接口,用户若想开发一个动态web资源(即开发一个Java程序向浏览器输出数据),
需要完成以下2个步骤:
1. 编写一个Java类,实现servlet接口。
2. 把开发好的Java类部署到web服务器中。
提示:按照一种约定俗成的称呼习惯,通常我们也把实现了servlet接口的java程序,称之为Servlet。
-----------------------------------------------------------------------------
Servlet的运行过程
Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后:
1. Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第4步,否则,执行第2步。
2. 装载并创建该Servlet的一个实例对象。
3. 调用Servlet实例对象的init()方法。
4. 创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个用于封装HTTP响应消息的HttpServletResponse对象,
然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
5. WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。
-----------------------------------------------------------------------------
Servlet的生命周期(1)
1. Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。
2. 针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象(单实例),
也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。
3. 在Servlet的整个生命周期内,Servlet的init方法只被调用一次。
而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。
对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,
然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXxx方法。
Servlet的生命周期(2)
如果在<servlet>元素中配置了一个<load-on-startup>元素,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。
举例:
<servlet>
<servlet-name>servletDemo1</servlet-name>
<servlet-class>com.itheima.servlet.ServletDemo1</servlet-class>
<!-- 设置启动时就加载,数值越小越先启动 (但不建议写0) -->
<load-on-startup>2</load-on-startup>
</servlet>
用途:为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据。
从提高Servlet容器运行性能的角度出发,Servlet规范为Servlet规定了不同的初始化情形。
如果有些Servlet专门负责在web应用启动阶段为web应用完成一些初始化操作,则可以让它们在web应用启动时就被初始化。
对于大多数Servlet,只需当客户端首次请求访问时才被初始化。
假设所有的Servlet都在web应用启动时被初始化,那么会大大增加Servlet容器启动web应用的负担,
而且Servlet容器有可能加载一些永远不会被客户访问的Servlet,白白浪费容器的资源。
-----------------------------------------------------------------------------
Servlet接口实现类
Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet、HttpServlet。
HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。
因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。
HttpServlet在实现Servlet接口时,重写了service方法,该方法体内的代码会自动判断用户的请求方式,
如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用HttpServlet的doPost方法。
因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。
注:doGet和doPost方法里面的形参分别是HttpServletRequest、HttpServletResponse。
-----------------------------------------------------------------------------
Servlet的线程安全
当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,
并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。
如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。
SingleThreadModel接口中没有定义任何方法,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。
对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,
其采用的方式是产生多个Servlet实例对象(资源浪费大),并发的每个线程分别调用一个独立的Servlet实例对象。
实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,
而真正意义上解决多线程安全问题是指:一个Servlet实例对象被多个线程同时调用的问题。
事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为Deprecated(过时的)。
-----------------------------------------------------------------------------
资源文件通常有两种方式:
对于简单的资源文件,即包含key=value的形式,我们一般采用properties,这些文件的扩展名一般为*.properties。
对于较复杂的资源文件,采用XML格式。
通常资源文件放在src目录或者WEB-INF目录下。
在web工程中,要获得某个文件的路径,我们一般都采取相对于web工程"/"的相对路径。
在src下放置的db.properites配置文件,
法一:利用Servletcontext.getResourceAsStream("/WEB-INF/classes/db.properties"); 来获取。
法二:利用ServeltContext.getRealPath("/WEB-INF/classes/db.properties"); 来获取。
web project工程目录结构图:
=============================================================================