第一章
servlet2.3规范用到了一下的一些规范:J2EE、JSP1.1、JNDI
在14章中讲述了规范中的所有的classes类或接口(改文中不讲述)。对开发者而言以下的有些相关的
协议:URI、URL、HTTP/1.0、MIME、HTCPCP/1.0、XML
1.1 什么是servlet?
servlet是一个基于java技术的web组件,该组件被容器管理,能被编译成字节码被web服务调
用;容器也被称之为引擎,是支持servlet功能的web服务的扩展。servlet之间的通信是通过客户
端请求被引擎执行成request/response对象进行的。
1.2 什么是servlet引擎?
servlet引擎是web服务器或应用服务器的一部分,服务器能够支持网络的请求/响应,基于请求
解析MIME,基于响应格式化MIME。servlet引擎是一个servlet容器,也掌管着servlet的生命周
期。
所有的servlet引擎都必须支持HTTP的请求/响应模式,但HTTPS的请求/响应模式也是被支持
的。HTTP的版本最小要HTTP/1.0,最好是HTTP/1.1。servlet引擎也具有安全和权限的一些特
性,这些特性其服务器应提供。
1.3 例子
一个典型的事件执行的顺序是:
1) 客户端向web服务器发起一个HTTP请求
2) HTTP请求被web服务器接受,并移交给servlet引擎,servlet引擎可以在主机的
同一个进程、不同的进程或其他的web服务主机的进程中启动。
3) servlet引擎根据servlet的配置档确定调用的servlet,并把request对象、
response对象传给它。
4) 4.servlet通过request对象知道客户端的使用者是谁,客户的请求信息是什么
和其他的一些信息。servlet处理完请求后把要返回的信息放入response对象返回到
客户端
5) 一旦servlet完成了请求的处理,servlet引擎就会刷新response,把控制权返回给
web服务器
1.4与其它技术的比较
与其它服务相比servlet有以下的一些优点
1) 运行速度上比CGI快,因为使用了多线程
2) servlet使用了标准的api,可被许多web服务支持
3) 与系统无关性,一次编译多次使用
第二章
servlet接口是servlet api核心部分,所有的servlet都是直接或间接的实现了这些接口。两个最重
要的servlet api 接口是GenericServlete 和 HttpServlet,更多的开发者都继承HttpServlet去实现
他们的servlet
2.1 Request 包含的方法
一个基本的servlet接口应该定义一个方法包含客户端的信息,每次servlet引擎把一个request发
送到一个servlet事例,这个方法都要被调用。
对于并发的请求,web应用需要设计者设计的servlet引擎能分配多个线程执行这个方法。
2.1.1 HTTP 请求处理的方法
HttpServlet是实现了Servlet接口的抽象类,增加了一些新的方法,这些方法在处理HTTP请求时
会被service方法自动调用,这些方法是:
doGet 接受 HTTP 的GET请求
doPost 接受 HTTP 的POST请求
doPut 接受 HTTP的PUT请求
doDelete 接受 HTTP的DELETE请求
doHead 接受 接受 HTTP的HEAD请求
doOptions 接受 HTTP的OPTIONS请求
doTrace 接受 HTTP的TRACE请求
一个开发者只会涉及到doGet和doPost方法,其它的方法是为非常熟悉HTTP的设计师准备的
2.1.2
HTTP/1.0只定义了doGet,doHead,doPost方法,没有定义PUT,DELETE,OPTIOONS和
TRACE方法
2.1.3
HttpServlet接口定义了getLastModified方法
2.2 实例数
2.2.1
在分布式环境中servlet引擎为每个servlet只能声明一个实例,当一个servlet实现了
SingleThreadModel接口时,servlet引擎可以声明多个实例去处理请求,servlet在应用服务的部
署描述中定义发布.
2.2.2单线程servlet
SingleThreadModel接口保证了在同一时刻一个servlet实例的service方法只会被一个线程执行。
这对于每个请求发送给每个实例是很重要的。引擎可以从对象池中选择,对象池可以在同一时
刻保持多个实例,如HttpSession可以被多个servlet在任何时候调用包括实现了
SingleThreadModel接口的servlet
2.3 servlet的生命周期
一个好的生命周期的定义应该是servlet怎么被引入了,怎么实例化的,怎么初始化的?当请求从客
户端来的时候,是怎么从服务器中取出来的,这些在javax.servlet.Servlet的接口的init,service,
destroy方法中都有明确的定义。
所有的servlet都必须实现GenericServlet或HttpServlet抽象类
2.3.1 servlet的引入和实例化
servlet引擎会可靠的引入和实例化servlet,当servlet引擎被启动时servlet就被引入和实例化了,
或者当一个servlet被请求时被引擎引入和实例化。
servlet引擎启动时,需要装载的类通过java的装载类进行装载,被装载的类可以在本地文件系
统、远程文件系统或网络服务中。在装载完后,引擎就实例化它们。
2.3.2 初始化
在servlet对象实例化后,引擎必须在这个servlet接受客户段请求之前初始化,在初始化中
servlet可以读取固定的配置信息,一些昂贵的资源如数据库连接和一次性激活的资源,引擎通
过调用servlet接口的init方法初始化。每个serlet对象都实现了Servlet接口和ServletConfig接口,
ServletConfig接口允许servlet接受web应用配置档中配置的参数,还向servlet中传入了一个描述
servlelt运行环境的类(ServletContext)
2.3.2.1 在初始化时发生错误
在初始化过程中,servlet实例能抛出UnavailableException 或ServletException异常。在这样的
情况下servlet不能被放入服务中,必须被引擎释放,destroy方法没有被调用。在初始化失败后
引擎可以在UnavailableException异常规定的最短无效时间后实例化新的一个实例,再初始化。
2.3.3 request
当servlet初始化完成后,引擎可以使用它去处理客户端的请求了。请求被封装在Servletrequest
类型的对象中,响应信息被封装在ServletResponse类型的对象中,这两个对象以参数的形式传
给Servlet接口中的service方法。
2.3.3.1 多线程问题
servlet引擎可以发送并发的请求给servlet的service方法,servlet开发者必须提供足够的线程来
运行service方法。
对开发者来说一个可以选择的方法是实现SingleThreadModel接口,以确保在同一时刻只有一个
请求在service方法中。一个引擎要确保请求能够在servlet中持续化,或维持在一个servlet实例
池中,如果servlet是web应用服务的一部分,引擎可以在一个虚拟机中拥有一个servlet实例化的
池。
对于没有实现SingleThreadModel接口的servlet,如果service方法(或 doGet,doPost)被声明
为synchronized,引擎将不能用实例池的途径,而必须持续化请求,强力建议开发者不能声明
synchronize service方法,这样会严重影响系统的性能。
2.3.3.2 request中的异常
在处理请求时servlet可以抛出ServletException或UnavailableException异常,一个
ServletException异常会在处理一个请求出现错误时抛出,引擎将清除这个异常。当servlet一时
或永久地不能获得一个请求时就会抛出UnavailableException异常,如果是一个永久性异常时引擎
将调用它的destroy方法从服务器中消除servlet实例,如果是暂时性异常时引擎在异常期间不发
送请求给servlet。如果返回SERVICE_UNAVAILABLE(503)响应,在这期间引擎将不接受任何请
求,直到header中出现Retry-After。引擎可以不区分永久性还是暂时性的异常把所有的
UnavailableException作为永久性处理。
2.3.3.3 线程安全
执行request和response对象不能保证是线程安全的,意思是说他们只能在请求的线程中使用,
不能被其它线程中的对象使用。
2.3.4 结尾
servlet实例可能被引擎保存几毫秒或和引擎一样的生命时间或在这两者之间。当引擎决定结束
一个servlet时,调用它的destroy方法,在destroy中释放任何长久固定的资源。
在引擎调用desroy方法之前,必须保证运行在service方法中的线程都完成处理,或者超过了服
务定义的执行时间。
一旦servlet实例的destroy方法被调用,引擎不在发送任何请求给这个实例。如果引擎再次使用
这个servlet就必须再建一个这个servlet的实例。
在destroy方法执行完成后,引擎将释放这个servlet实例,于是就符合垃圾回收机制的条件了。
第三章3.1 介绍ServletContext接口
ServletContext接口定义了servlet运行环境的信息。引擎提供商有义务在servlet引擎中提供一个
实现了ServletContext接口的对象。通过这个对象servlet能够获得log事件,资源的URL,设置或
存储servlet之间通信的变量。ServletContext在web服务中确定了一个所有请求开始的路径,是
ServletContext的上下文路径。
3.2 ServletContext 接口的作用范围
每个web应用配置到容器中都会产生一个实现了ServvletContext接口的实例。如果是分布式
的,将会在每个java虚拟机上产生一个ServletContext实例。容器中默认固有的web应用(不是
发布上来的web应用)有一个默认的ServletContext,在分布式中这个默认的ServletContext只存
在于一个虚拟机中,是不可分配的。
3.3 初始化参数
ServletContext接口的getInitParameter,getInitParameterNames方法接受部署描述文件中的初始
化参数,这些参数可以是的安装信息,或网站管理员的mail或名字或对系统的评论。
3.4 上下文属性
servlet可以通过一个名称把对象邦定到servletContext中,帮定到ServletContext中的对象都能被
同一个web服务中的其它对象引用。ServletContext中的属性方法有:
setAttribute
getAttribute
getAttributeNames
removeAttribute
3.4.1 在分布式系统中 上下文的属性
上下文属性是在本地的虚拟机中保存的,这防止了ServletContext属性存在于分布式的内存中。
当信息需要在一个分布式环境中共享的时候,信息应该被放在session中,或存在数据库中,或
存在一个实体bean中。
3.5 资源
ServletContext接口提供了获取web服务中的静态资源的方法:
getResource
getResourceAsStream
这些方法以一个“/”作为上下文的根目录,后跟着资源路径的路径为参数。这些资源可以在本地
服务系统中也可以在另个web应用中,或在一个远程的文件系统中。
这些方法不能用于去获得一个动态的资源,如要调用一个jsp页面,getResource("/index.jsp")将
返回index.jsp的原代码,不能web显示index.jsp。
要获得资源列表可以用getResourcePaths(String path)方法
3.6 多主机 和 Servlet 上下文
web服务中可能在一个IP上有多个逻辑主机的情况。在这种情况下每个逻辑主机必须有自己单
独的servlet上下文,或者设置多个servlet 上下文,但在逻辑主机中不能共享这些servlet 上下
文,一个主机只能单独使用一个。
3.7
引擎提供类重新装载机制是必须的,必须确认应用中所有的类和接口都可以在单类装载器中
装载;在session绑定监听事件中引擎会终止正在装在的类。以前版本的装载器,引擎创建一
个新的装载器装载一个servlet或class和类装载器装载其他的servlet或类截然不同;这可能装
载一个未知的类或对象,产生不可预知的行为。这是新的类装载器中是应该注意预防的问
题。
3.7.1 临时工作目录
Servlet 上下文需要一个临时存储的目录。servlet引擎必须为每个servlet 上下文提供一个私有临
时目录,通过javax.servlet.context.tempdir的context属性使目录有效。与该属性关联的对象必
须是java.io.File类型。
在许多servlet引擎实现中提供请求可以识别的通用的机制。
当servlet引擎重起始不必维护临时目录中的内容,但要确保临时目录中的该上下文内容对于运
行在该servlet引擎中的其它web应用中的servlet 上下文是不可见的。