`
bsr1983
  • 浏览: 1101119 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Servlet3.1标准学习笔记二

 
阅读更多
18.HttpServletRequest接口提供了getCookies方法来获得请求中的cookie的一个数组。这些cookie是从客户端发送到服务器端的客户端发出的每个请求上的数据。
如果请求已经通过一个安全协议发送过,如HTTPS,必须通过ServletRequest接口的isSecure方法公开该信息。Web容器必须公开下列属性给servlet程序员:
密码套件               javax.servlet.request.cipher_suite                 String
算法的位大小        javax.servlet.request.key_size                        Integer
SSL会话id             javax.servlet.request.ssl_session_id               String
如果有一个与请求相关的SSL证书,它必须由servlet容器以java.security.cert.X509Certificate类型的对象数组暴露给servlet程序员并可通过一个javax.servlet.request.X509Certificate类型的ServletRequest属性访问。
19.客户端可以选择希望Web服务器用什么语言来响应。该信息可以和使用Accept-Language头与HTTP/1.1规范中描述的其他机制的客户端通信。
(1)getLocale    返回客户端请求要接受内容的首选语言环境。
(2)getLocales   返回一个Locale对象的枚举,从首选语言环境开始顺序递减,这些语言环境是可被客户接受的语言环境。
如果客户端没有指定首选语言环境,getLocale方法返回的语言环境必须是servlet容器默认的语言环境,而getLocales方法必须返回只包含一个默认语言环境的Local元素的枚举。
20.许多浏览器不随着Content-Type头一起发送字符编码限定符,而是根据读取HTTP请求确定字符编码。如果客户端请求没有指定请求默认的字符编码,容器用来创建请求读取器和解析POST数据的编码必须是“ISO-8859-1”。然而,为了向开发人员说明客户端没有请求默认的字符编码,在这种情况下,客户端发送字符编码失败,容器从getCharacterEncoding 方法返回null.
如果客户端没有设置字符编码,并使用不同的编码来编码请求数据,而不是使用上面描述的默认的字符编码,那么可能会发生数据损坏。Servlet接口添加了一个新的方法,setCharacterEncoding(String enc)。开发人员可以通过调用该方法来覆盖由容器提供的字符编码。必须在解析任何post数据或从请求读取任何输入之前调用此方法。此方法一旦调用,将不会影响已经读取的数据的编码。
21.每个request对象只在servlet的service方法的作用域内,或过滤器的doFilter方法的作用域内有效,除非该组件启用了异步处理并且调用了request对象的startAsync方法。在发生异步处理的情况下,request对象一直有效,知道调用AsyncContext的complete方法。容器通常会重复利用request对象,以避免创建request对象的性能开销。开发人员必须注意的是,不建议在上述范围之外保持startAsync方法还没有被调用的请求对象的引用,因为这样可能产生不确定的结果。
在请求升级的情况下,如上描述依然成立。
22.ServletContext(Servlet上下文)接口定义了servlet运行在的Web应用的视图。容器供应商负责提供Servlet容器的ServletContext接口的实现。Servlet可以使用ServletContext对象记录事件,获取URL引用的资源,存钱当前上下文的其他Servlet可以访问的属性。
ServletContext是Web服务器中已知路径的根。例如,Servlet上下文可以从http://www.mycorp.com/catalog找出,/catalog请求路径称为上下文路径,所有以它开头的请求都会被路由到与ServletContext相关联的Web应用。
部署在容器中的每一个Web应用都有一个ServletContext接口的实例与之关联。在容器分布在多态虚拟机的情况下,每个Web应用在每个JVM中都将有一个ServletContext实例。
如下ServletContext接口方法允许Servlet访问由应用开发人员在Web应用中的部署描述符中指定的上下文初始化参数:
(1)getInitParameter
(2)getInitParameterNames
应用开发人员使用初始化参数来表达配置信息。
如下的方法只能在应用实例化的过程中通过一个ServletContextListener实现的contextInitialized方法或者一个ServletContainerInitializer实现的onStartup方法调用。除了添加Servlet和Filter,也可以查找关联到Servlet或Filter的一个Registraction对象实例,或者到Servlet或者Filter的所有Registration对象的map。
往ServletContext添加指定class名称的监听器。ServletContext将使用由与应用关联的classloader装载加载该给定名称的class,且它们必须实现一个或多个以下接口:
(1)javax.servlet.ServletContextAttributeListener
(2)javax.servlet.ServletRequestListener
(3)javax.servlet.ServletRequestAttributeListener
(4)javax.servlet.http.HttpSessionListener
(5)javax.servlet.http.HttpSessionAttributeListener
(6)javax.servlet.http.HttpSessionIdListener
如果ServletContext传到了ServletContainerInitializer的onStartup方法,则给定名字的类可以实现除上面列出的接口之外的javax.servlet.ServletContextListener。作为该方法调用的一部分,容器必须装载指定类名的class,以确保其实现了所需的接口之一。如果给定名字的类实现了一个监听器接口,则其调用顺序和声明顺序是一样的。换句话说,如果它实现了javax.servlet.ServletRequestListener或javax.servlet.http.HttpSessionListener,那么新的监听器将被添加到该接口的有序监听器列表的末尾。
23.上下文属性
Servlet可以使用指定的名字将对象属性绑定到上下文。同一个Web应用内的其他任何Servlet可以使绑定到上下文的任意属性。
在JVM中创建的上下文属性是本地的,这可以防止从一个分布式容器的共享内存存储中获取ServletContext属性,当需要在运行在分布式环境的Servlet之间共享信息时,该信息应该被放到session或存储到数据库,或者设置到企业级JavaBean组件。
24.资源
ServletContext接口提供了直接访问Web应用中静态内容层次机构的文件的方法,包括HTML,GIF和JPEG文件
(1)getResource
(2)getResourceAsStream
getResource和getResourceAsStream方法需要一个以“/”开头的String字符串作为参数,给定的资源路径是相对于上下文的根,或者相对于web应用的WEB-INF/lib目录下的JAR文件中的META-INF/resources目录。这两个方法首先根据请求的资源查找web应用上下文的根,然后查找所有WEB-INF/lib目录下的JAR文件。查找WEB-INF/lib目录中JAR文件的顺序是不确定的。这种层次结构的文件可以存在于服务器的文件系统,Web应用的归档文件,远程服务器,或者其他位置。
这两个方法不能获取动态内容。
25.Servlet上下文不会在虚拟主机之间共享。ServletContext接口的getVirtualServerName方法允许访问ServletContext部署在的逻辑主机的配置名字。该方法必须对所有部署在逻辑主机上的所有servlet context返回同一个名字。且该方法返回的名字必须是明确的、每个逻辑主机稳定的、和适合用于关联服务器配置信息和逻辑主机。
26.每一个servlet上下文都需要一个临时的存储目录。Servlet容器必须为每一个servlet上下文提供一个私有的临时目录,并将通过javax.servlet.context.tempdir上下文属性使其可用,关联该属性的对象必须是java.io.File类型。该要求公认为在多个servlet引擎实现中提供一个通用的便利。当servlet容器重启时,它不需要去保持临时目录中的内容,但必须确保一个servelt上下文的临时目录中的内容对运行在同一个servlet容器的其他Web应用的上下文不可见。
27.响应对象封装所有从服务器返回给客户端的信息,在HTTP协议中,从服务器返回客户端的信息是通过HTTP头信息或请求的信息体传输的。
ServletResponse接口的如下方法运行servlet访问和设置缓冲信息:
(1)getBufferSize 返回使用的底层缓冲区大小。如果没有使用缓冲,该方法必须返回一个int值0.
(2)setBufferSize  Servlet可以请求setBufferSize方法设置一个最佳的缓冲大小。
(3)isCommitted 返回一个表示是否有任何响应字节已经返回到客户端的boolean值。
(4) reset 当响应没有提交时,该方法情况缓冲区的数据。头信息,状态码和在调用reset之前servlet调用getWriter或getOutputStream设置的状态也必须被清空。
(5) resetBuffer 如果响应没有被提交,该方法将清空缓存区的内容,但不清空请求头和状态码。
(6) flushBuffer 强制刷出缓冲区的内容到客户端
Servlet可以使用如下HttpServletResponse接口中的方法设置HTTP响应头:
(1)setHeader 设置一个给定名字和值的header。之前的header将被新的header替换。
(2)addHeader方法使用给定的名字添加一个header值到set。
28.非阻塞IO
非阻塞IO仅对在Servlet和Filter中的异步请求处理和升级处理有效。否则,当调用ServletInputStream.setReadListener或ServletOutputStream.setWriteListener方法时将抛出IllegalStateException。
29.HttpServletResponse提供了如下简便方法:
(1)sendRedirect 将设置适当的header和内容体将客户端重定向到另一个地址。使用相对URL路径调用该方法是合法的,但是底层的容器必须将传回到客户端的相对地址转换为全路径URL。
(2)sendError 方法将设置适当的header和内容体用于返回给客户端返回错误消息。可以为sendError方法提供一个可选的String参数用于指定错误的内容体。
30.Servlet应设置response的locale和字符集。使用ServletResponse.setLocal方法设置local。该方法可以重复调用;但相应被提交后调用该方法不会产生任何作用。如果在页面被提交之前Servlet没有设置locale,容器的默认locale将用来确定相应的locale,但是没有指定与客户端通信的规范,例如使用HTTP情况下的Context-Language header。
setCharacterEncoding,setContentType和setLocale方法可以被重复的调用来改变字符编码。
在ServletResponse接口的getWriter方法被调用或响应被提交之前,如果servlet没有指定字符编码,默认使用ISO-8859-1。
当响应被关闭时,容器必须立即刷出响应缓冲区中的所有剩余的内容到客户端。
以下事件表明servlet满足了请求且响应对象即将关闭:
(1)servlet的service方法终止。
(2)响应的setContentLength或setContentLengthLong方法制定了大于零的内容量,且已经写入到响应。
(3)sendError方法已调用
(4)sendRedirect方法已调用。
(5)AsyncContext的complete方法已调用。
每个响应对象是只有当在servlet的service方法的范围内或在filter的doFilter方法范围内是有效的,除非该组件关联的请求对象已经开启异步处理。如果相关的请求已经启动异步处理,那么知道AsyncContext的complete方法被调用,请求对象一直有效。为了避免响应对象创建的性能开发,容器通常回收响应对象。在相关的请求的startAsync还没有调用时,开发人员必须意识到保持到响应对象引用,超出之上描述的范围可能导致不确定的行为。
31.过滤器是一种代码重用的技术,它可以改变HTTP请求的内容,响应,及header信息。过滤器通常不产生响应或像servlet那样对请求作出响应,而是修改或调整到资源的请求,修改或调整来自资源的响应。
供开发人员使用的过滤器功能有如下几种类型:
(1)在执行请求之前访问资源
(2)在执行请求之前处理资源的请求
(3)用请求对象的自定义版本包装请求,对请求的header和数据进行修改
(4)用响应对象的自定义版本包装响应,对响应的header和数据进行修改。
(5)拦截资源调用之后的调用
(6)按指定顺序执行的零个、一个或多个拦截器作用于Servlet,一组Servlet或静态内容
应用开发人员通过实现javax.servlet.Filter接口并提供一个公共的空参构造器来创建过滤器。该类及构建Web应用的静态资源和Servlet打包在Web应用归档文件中。Filter在部署描述符中通过<filter>元素声明。一个过滤器或一组过滤器可以通过在部署描述符中定义<filter-mapping>来为调用配置。可以使用servlet的逻辑视图名把过滤器映射到一个特定的servlet,或者使用URL模式把一组Servlet和静态资源内容映射到过滤器。
在部署描述符中声明的每个<filter>在每个JVM的容器中仅实例化一个实例。容器提供了声明在过滤器的部署描述符的过滤器config(FilterConfig),对Web应用的ServletContext的引用,和一组初始化参数。
过滤器的核心概念是包装请求或响应,以便它可以覆盖行为执行过滤任务。在这个模型中,开发人员不仅可以覆盖请求和响应对象上已有的方法,也能提供新的API以适用于对过滤器链中剩下的过滤器或目标web资源做特殊的过滤任务。
32.可以使用部署描述符中的<init-params>元素把一组初始化参数关联到过滤器。这些参数的名字和值在过滤器运行期间可以使用过滤器的FilterConfig对象的getInitParameter和getInitParameterNames方法得到。另外,FilterConfig提供访问Web应用的ServletContext用于加载资源,记录日志,在ServletContext的属性列表存储状态。链中最后的过滤器和目标servlet或资源必须执行在同一个调用线程。
过滤器可以通过@WebFilter注解定义或者在部署描述符中使用<filter>元素定义。在这个元素中,可声明如下内容:
(1)filter-name:用于映射过滤器到servlet或URL
(2)filter-class:由容器用于标示过滤器类型
(3)init-params:过滤器的初始化参数
容器必须为部署描述符中定义的每个过滤器声明实例化一个Java类实例。因此,如果开发人员对一个过滤器类声明了两次,则容器将实例化两个相同的过滤器类的实例。
一旦在部署描述符中声明了过滤器,配置人员使用<filter-mapping>定义Web应用中的servlet和静态资源到过滤器的应用。过滤器可以使用<servlet-name>元素关联到一个Servlet。过滤器可以使用<url-pattern>风格的过滤器映射关联到一组servlet和静态内容。
当使用<url-pattern>风格配置<filter-mapping>元素,容器必须使用路径映射规则(path mapping rule)决定<url-pattern>是否匹配请求URI。
容器使用的用于构建应用到一个特定请求URI的过滤器链的顺序如下所示:
(1)首先,<url-pattern>按照在部署描述符中的出现顺序匹配过滤器映射。
(2)接下来,<servlet-name>按照在部署描述符中的出现顺序匹配过滤器映射。
如果过滤器映射同时包含了<servlet-name>和<url-pattern>,容器必须展开过滤器映射为多个过滤器映射(每一个<servlet-name>和<url-pattern>一个),保持<servlet-name>和<url-pattern>元素顺序。
33.通过在部署描述符中使用心得<dispatcher>元素,开发人员可以为filter-mapping指定是否想要过滤器应用到请求,当:
(1)请求直接来自客户端
可以由一个带有REQUEST值的<dispatcher>元素,或者没有任何<dispatcher>元素来表示。
(2)使用表示匹配<url-pattern>或<servlet-name>的web组件的请求分配器的forward()调用情况下处理请求。
可以由一个带有FORWARD值的<dispatcher>元素表示。
(3)使用表示匹配<url-pattern>或<servlet-name>的Web组件的请求分派器的include()调用情况下处理请求。
可以由一个带有INCLUDE值的<dispatcher>元素表示。
(4)使用第106页“错误处理”指定的错误页面机制处理匹配<url-pattern>的错误资源的请求。
可以由一个带有ERROR值的<dispatcher>元素表示。
(5)使用第10页指定的“异步处理”中的异步上下文分派机制对web组件使用dispatche调用处理请求。
可以由一个带有ASYNC值的<dispatcher>元素表示。
(6)或之上1,2,3,4,5的任何组合。
34.HTTP被设计为一种无状态协议。为了构建有效的Web应用,必须与来自一个特定的客户端的请求彼此相关关联。
(1)Cookies
通过HTTP cookie的会话跟踪是最常用的会话跟踪机制,且所有servlet容器都应该支持。
容器向客户端发送一个cookie,客户端后续到服务器的请求都将返回该cookie,明确地将请求与会话关联。会话跟踪cookie的标准名字必须是JSESSIONID,所有3.0兼容的容器必须支持。容器也允许通过容器指定的配置自定义会话跟踪cookie的名字。
(2)SSL会话
安全套接字层,在HTTPS使用的加密技术,有一种内置机制允许多个来自客户端的请求被明确识别为同一会话。Servlet容器可以很容易地使用该数据来定义会话。
(3)URL重写
URL重写是会话跟踪的最低标准。当客户端不接受cookie时,服务器可使用URL重写作为会话跟踪的基础。URL重写设计添加数据、会话ID、容器解析URL路径从而请求与会话相关联、
会话ID必须被编码为URL字符串中的一个路径参数。参数的名称必须是jessionid.
URL重写在日志、书签、refer header、缓存的HTML、URL工具条中暴露会话标识。在支持cookie或SSL会话的情况下,不应该使用URL重写作为会话跟踪机制。
与每个会话相关联的是一个包含唯一标识符的字符串,也被称为会话ID,会话ID的值能通过调用javax.servlet.http.HttpSession.getId()获取,且能在创建后通过调用javax.servlet.http.HttpServletRequest.changeSessionId()改变。
HttpSession对象必须被限定在应用(或servlet上下文)级别。底层的机制,如使用cookie建立会话,不同的上下文可以是相同,但所引用的对象,包括该对象中的属性,决不能在容器上下文之间共享。
35.servlet可以按名称绑定对象属性到HttpSession实现,任何绑定到会话的对象可用于任意其他的Servlet,其属于同一个ServletContext且处理属于相同会话中的请求。
一些对象可能需要在它们被放进会话或从会话中移除时得到通知。这些信息可以从HttpSessionBingingListener接口实现的对象中获取。这个接口定义了以下方法,用于标识一个对象被绑定到会话或从会话解除绑定时。
(1)valueBound
(2)valueUnbound
Servlet容器定义了默认的会话超时时间,且可以通过HttpSession接口的getMaxInactiveInterval方法获取,也可以通过setMaxInactiveInterval方法设置超时时间。
HttpSession接口的getLastAccessedTime方法允许servlet确定在当前请求之前的会话的最后访问时间。
写分布式应用的开发人员应该意识到容器可能运行在多个Java虚拟机中,开发人员不能依赖静态变量存储应用状态。应该用企业Bean或数据库存储这种状态。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics