第2章 The servlet Interface
所有Servlet实现同一接口:Servlet,它有两个直接的子类:GenericServlet和HttpServlet.
2.1 Request Handle method
基本的Servlet使用service()方法处理请求,因为可能有多个客户的请求在service()中工作,所以开发者必须要考虑到并发的情况。
SRV.2.1.1 HTTP Specific Request Handling Methods
HttpServlet定义了以下7个方法:
-
doGet for handling HTTP GET requests
-
doPost for handling HTTP POST requests
-
doPut for handling HTTP PUT requests
-
doDelete for handling HTTP DELETE requests
-
doHead for handling HTTP HEAD requests
-
doOptions for handling HTTP OPTIONS requests
-
doTrace for handling HTTP TRACE requests
SRV.2.1.2 Additional Methods
关于Http的几个附加命令HEAD,DELETE,PUT,OPTIONS,TRACE。
SRV.2.1.3 Conditional GET Support
这个”Conditional GET“指的是这样的请求:只有所请求的资源在一个特定时间之后被修改过,才被发送给客户端。
HttpServlet里的getLastModified()方法提供了这方面的支持。
SRV.2.2 Number of Instances
在2.4之前的版本中,Servlet有两种方式:
第一种方式是对于一个Servlet,只有一个实例,这个实例可以同时服务多个用户,这是默认的。
另一种方式是一个Servlet的实例只能服务一个客户,这样就需要一个Servlet的Pool,当多个用户连接时,需要建立多个Servlet实例。这种方式需要Servlet实现SingleThreadModel接口。
以上两种方式的比较:第一种方式需要考虑同步问题(因为一个Servlet的实例服务多个用户,Servlet中的数据成员需要同步),第二种方式不需要考虑同步问题。
SRV.2.3 Servlet Life Cycle
1.载入:
应用服务器可能在启动时载入Servlet或者在第一个请求到来时延迟加载,载入的方式也是使用类装载器,和普通的Java Object没有什么区别。
2.初始化:
初始化时可能遇到错误,这时会抛出ServletException或者UnaviliableException异常
3.多线程:
需要注意的一点是,最好不要对service()方法进行synchronize修饰。这样的话就不能使用线程池,而必须对request序列化
4.处理请求时的错误处理:
如果在这时发生异常,可以发送UnavailableException或者ServletException,如果发送了
ServletException,服务器必须要想办法清除request。如果发送了UnavailableException,有两种选择,如果是永
久的的无效,需要调用destroy(),并摧毁Servlet,如果这时客户端访问此Servlet,它将会收到404错误。如果是临时的无效,容器需
要拒绝任何到此Servlet的请求,并且返回503错误
5.线程安全的话题
request和response这两个对象不是线程安全的,所以不要在service()方法外面使用它们,它们的引用不应该传给另一个线程中的对象,如果一定要访问它们,必须对使用这两个对象的代码进行同步。
6.服务的结束
Servlet容器并不需要一直保持一个Servlet处于运行状态,在释放一个servlet时,会调用destroy方法,当调用destroy方法之前,容器会一直等到所有的线程都完成了在service()方法中的工作。
第3章 Servlet Context
SRV.3.1 Introduction to the ServletContext Interface
Servlet Context,从Servlet的角度来看,可以理解为它所属Web应用程序,ServletContext是一个接口,Servlet容器的提供商必须要实现这个接口。
ServletContext能做什么呢?它可以把事件记录到日志中,获得资源的URL,还可以利用ServletContext存放一些所有Servlet都能共享的数据。
ServletContext有一个路径,例如http://www.mycorp.com/catalog,这里的cataqlog就是ServletContext的路径,所有的对catalog的请求都会关联到这个ServletContext.
SRV.3.2 Scope of a ServletContext Interface
在Servlet容器中,每个ServletContext通常只有一个实例。当Web容器是分布式的部署在多台机器上时,那一个ServletContext在每个JVM上都有一个实例。
在Servlet容器中,但没有部署的Servlet也是允许的,这种Servlet属于一个缺省的ServletContext,这种缺省的ServletContext不能被分布到多个JVM上。
SRV.3.3 Initialization Parameters
在ServletContext接口中,有两个方法可以用来获得初始化参数:
• getInitParameter
• getInitParameterNames
SRV.3.4 Context Attributes
在ServletContext中,有4个方法可以用来设置和管理ServletContext的属性:
• setAttribute
• getAttribute
• getAttributeNames
• removeAttribute
SRV.3.4.1 Context Attributes in a Distributed Container
ServletContext中的属性只在本地的JVM中有效,不能被分布式环境中运行于其它JVM中的Servlet访问,如果需要在分布式环境中共享数据,可以把数据存放在Session,数据库或EJB中。
SRV.3.5 Resources
资源指的是在Web应用程序中的一些静态的内容,如静态HTML页面,图片等等。ServletContext提供了两个方法来访问这些资源:
• getResource
• getResourceAsStream
这两个方法都接受一个String型参数,它指定了一个以"/"开头的相对于这个ServletContext的资源路径。资源可以放在同一服务器上,或者不同服务器上,或者在一个Web应用程序的WAR包中。
需要注意的是,这两个方法不能用来获取动态内容,如果我们用这两个方法去取一个JSP页面,返回的将是JSP页面的源代码。
getResourcePaths(String path)方法可以用来获取一个资源列表。
SRV.3.6 Multiple Hosts and Servlet Contexts
Web服务器可能支持多个域名分享一个IP地址,这种配置叫做“虚拟主机”。在这种情况下,每个虚拟主机必须要有自己的ServletContext,而不能共享一个ServletContext。
SRV.3.7 Reloading Considerations
所有的Servlet和它们引用的类必须都处于一个类装载器范围内。
SRV.3.7.1 Temporary Working Directories
每一个ServletContext都需要一个临时目录,并且通过
javax.servlet.context.tempdir属性指定。Servlet容器不需要管理这个临时路径的内容,但是要确保一个
ServletContext的临时目录对其他的ServletContext是不可见的。