分类:
2008-09-08 18:23:42
第一章:
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 上下文是不可见的。
4 requeset
request对象包含了客户端的所有请求信息。在HTTP中,客户端发送到服务端的信息都包含在请求的HTTP 头和消息体中
4.1 HTTP 的参数
客户端发送给servlet引擎的参数是包含在请求中的,引擎从客户端请求的URI字符串中或POST数据中解析出请求的参数。参数以name-value的形式存储的。任何一个name可以对应多个value。在ServletRequest接口的方法中:
getParameter
getParameterNames
getParameterValues
getParameterValues方法返回关联到一个name上的一个String对象的数组。getParameter返回name对应的values数组中的第一个value。URI和POST体中的参数都会放入请求参数的set对象中。URI中的参数会在POST体之前被引入,如URI中的参数“a=hello”post体中的参数是a=goodbye&a=world,则参数set中的内容是a=(hello,goodbye,world).以HTTP GET请求的参数是不隐蔽的,参数必须通过getRequestURI或getPathInfo方法获得参数字串。
4.1.1 参数什么时候有效
在post form中的数据参数被放入参数set之前的情况是这样的:
1)请求是一个HTTP或一个HTTPS
2)HTTP方法是POST
3)内容的类型是application/x-www-form-urlencoded
4)初始化过的servlet从request对象中调用getParameter方法(或getParameterNames,getParameterValues)。
Post form 中的数据符合条件的就放入参数set中,不符合的就放入request对象的输入流中。
4.2 属性
request的属性是一个对象,引擎可以把API不能表达的信息放入属性中,一个servlet也可以设置一个属性信息用于servlet之间的通信。request对象中的属性方法有:
getAttribute
getAttributeNames
setAttribute
一个属性名称只能关联一个value。属性名以“java.”或“javax.”为前缀的是规范保留的,类似的“sun.”“com.sun”是sun公司的保留字,这些保留的前缀是不能使用的。name建议使用统一的包命名规范名称。
4.3 头
servlet通过HttpServletRequest接口的方法获得HTTP的包头信息,这些方法是:
getHeader
getHeaders
getHeaderNames
getHeader 方法返回头的名称。一个名称可以关联多个头信息,如果在这种情况下,getHeader方法返回第一个头信息。
getHeaders返回与一个名称关联的所有头信息存放在Enumeration对象中。HttpServletRequest提供了一些提取头信息的类型转换方法,如:
getIntHeader 把头信息中的数据转换成int型,如果转换失败会报NumberFormatException错误。
getDateHeader 把头信息中日期的数据转换成date型,如果转换失败会报IllealArgumentException错误
4.4 请求路径
context路径:这路径是和ServletContext对象关联的,在web服务中默认的上下文路径是空的字符串,如果上下文路径不是web服务的根目录,则路径以‘/’字符开始,但不能以‘/’结束。
Servlet 路径:与该请求匹配的servlet的路径。该路径以‘/’字符开头,或以‘/*’开头但后面为空字串。
路径信息:是请求路径的一部分,但不是context路径的一部分,也不是Servlet路径的一部分,它既不为null也不是以‘/’开头的字符串。
上一路径在HttpServletRequest接口中对应的方法是:
getContextPath
getServletPath
getPathInfo
requestURI = contextPath + servletPath + pathInfo
上下文配置的例子:
Conteext Path /catalog
Servlet Mapping Pattern:/lawn/*
Servlet:LawnServlet
Servlet Mapping Pattern:/garden/*
Servlet:GardenServlet
Servlet Mapping Pattern:*.jsp
Servlet:JSPServlet
观察下面的路径
Request path path Elements
/catalog/lawn/index.htm ContextPath:/catalog
ServletPath:/lawn
PathInfo:/index.html
/catalog/garden/implements/
ContextPath:/catalog
ServletPath:/garden
PathInfo:/implements/
/catalog/help/feedback.jsp
ContextPath:/catalog
ServletPath:/help/feedback.jsp
PathInfo:null
[1]