第四章
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
4.5 路径转换
在API中有两个简单的方法允许开发者获得文件系统的路径:
ServletContext.getRealPath
HttpServletRequet.getPathTranslated
getRealPath(String aPath)方法返回本地文件系统的绝对路径。getPathTranslated方法计算出请
求pathInfo中的绝对路径。
以上的两个方法,servlet引擎不能辨认文件的路径是否有效,当web应用调用一个不确定远程
文件系统,或数据库路径中的文件时,会返回null
4.6 Cookies
HttpServletRequest接口中提供了getCookies方法返回请求中的cookies数组,在每次客户端请求
时cookies数据就从客户端发送给服务。客户端返还的部分cookie信息是cookie的name和cookie
的value。当cookie被送入浏览器时,cookie的其它信息就可以设置了。
4.7 SSL 属性
如果一个请求被转给一个安全的协议,如HTTPS,这些信息必须暴露给ServletRequest接口的
isSecure方法。web引擎必须把下面的信息暴露给servlet开发者:
Attribute Attribute Name javaType
Cipher suite javax.servlet.request.cipher_suite String
bit size of the algo-rithm javax.servlet.request.key_size Integer
如果一个SSL证书伴随着一个请求,servlet引擎必须把它作为一个数组对象暴露给servlet开发
者,该数组中有
java.security.cert.X509Certificate对象和放在ServletRequest属性中的javax.servlet.request.
X509Certificate对象。
数组排列的顺序是升序,在链中的证书的顺序就是客户端设置的顺序。
4.8 国际化
ServletRequest接口的方法中提供了的方法:
getLocale
getLocales
getLocale方法将返回客户端将从中获得内容的首选的locale。要想知道更多的关于Accept-
Language header 怎么解释客户端首选的语言的,请看14.4章
getLocales方法返回一个Locale objects的Enumeration,从首选的locale开始递减。
如果客户端没有制定首选的locale,servlet引擎一定要提供一个默认的locale供getLocale方法返
回,getLocales方法必须包含一个默认的locale的locale element
4.9 Request 数据的编码
有许多web浏览器不能发送一个编码的头内容,所以把编码留给解读HTTP请求的Read去做。对
于默认的请求编码,引擎通常创建一个reader用“ISO-8859-1”去解析POST的数据,如果客户端
没有指明编码,或者客户端发送失败,getCharacterEncoding方法就返回null。
如果客户端没有设置编码,而请求需被另外一种编码,可用ServletRequest接口中的
setCharacterEncoding(String enc) 方法。必须在解析post数据或读取请求流之前调用这些方
法。
4.10 Request对象的生命周期
每个request对象仅在servlet的service方法或filter中的doFilter方法中有效,引擎重用request对
象是为了降低创建request对象的性能消耗。
开发者必须清楚request对象在给定的范围外的一些不确定的行为。
第五章
response对象封装着服务端送给客户端的信息,从服务端传回的信息可以包含在请求的头和消息体重。
5.1 缓存
servlet引擎支持应答缓存,典型的servlet会默认的执行缓存,servlet可以指定缓存参数。
设置缓存信息的方法在ServletResponse接口中的方法有:
getBufferSize
setBufferSize
isCommitted
Reset
resetBuffer
flushBuffer
这些方法只有在servlet调用ServletOutputStream 或Writer之前有效。
getBufferSize返回缓存的大小,如果没有缓存,该方法返回0。
setBufferSize可以设置缓存的大小,但不是必须的。servlet会根据请求放置适当的缓存大小。这方
法必须在servlet调用ServletOutputStream 或Writer方法之前被调用。如果在之后调用就会抛出
IllegalStateException错误。
isCommitted返回一个boolen值,标志是否有任何一个字节的数据被返回给客户端了。flushBuffer
方法强制把缓存中的信息写到客户端。
当response没有提交缓存内容时调用reset方法就会清除缓存中的信息,包括头信息和状态码。
resetBuffer方法会清除缓存中的信息,但不会清除头和状态码。在commit之后调用reset或
resetBuffer都会抛出IllegalStateException错误,缓存中的内容不受影响。
使用缓存时,当缓存满时response就必须立刻刷新把缓存中的内容发送给客户端;只要第一个字节
到了客户端,commit的状态就为true。
5.2 Headers
servlet能够通过HttpServletResponse的一些方法设置HTTP响应的头信息,这些方法有:
setHeader
addHeader
setHeader方法会把给定的一个name-values放到头信息中,头信息中只能有一个name-values,后面
setHeader会覆盖前面setHeader方法中的内容,一个name可以有多个value。
addHeader方法可以增加一个value到已有的name上,如果name不同就会新建一个name-values
头可以包含一些信息,如日期或数字对象。
以下的一些方法用适当的数据类型设置头信息:
setIntHeader
setDateHeader
addIntHeader
addDateHeader
在响应被发送到客户端之前,头信息是必须被设置的,如果没有设置头信息,servlet引擎将不会发送该
请求到客户端。HTTP1.1规范没有规定必须设置响应的头信息。当程序员没有设置响应体的Content-
Type时,servlet引擎也不需要设置一个默认的类型。
5.3 其他一些方法
HttpServletResonse接口中还有其他的一些方法:
sendRedirect
sendError
sendRedirect方法将设置合适的头和体信息,用于重定向客户端到另一个URL。如果sendRedirect参数
是个相对路径,则在底层servlet引擎中会把这相对路径转换成绝对路径返回给客户端的。
如果相对路径不能被引擎转换成绝对路径就会抛出IllegalArgumentException错误。
sendError方法会把一条错误信息作为头和体信息发送给客户端。
如果在调用sendRedirect或sendError之前设置了头和体信息,再调用sendRedirect或sendError时,之前
的头和体中的数据信息都将没用,不会被发送到客户端。如果使用了缓存,在调用sendRedirect或
sendError时,之前的信息都将被清除。如果在commit之后调用sendRedirect或sendError就会抛出
IllegalStateException错误。
5.4 国际化
当客户端用一特殊的语言(或客户端设置了语言)发出请求时,servlet会设置相应的响应语言信息,
ServletResponse接口中设置响应语言的方法是setLocale。这个方法会设置一个合适的Content-
Language到头信息中。最好是开发者在调用getWriter方法之前调用setLocale方法,确保返回的
PrintWriter已经被设置好了语言信息。如果在调用setLocale之后又调用了setContentType,setLocale中
的内容将被setContentType中的字符集覆盖。
response默认的编码方式是“ISO-8859-1”。
5.5 response对象的关闭
当response被关闭时,引擎必须刷新该response缓存中的所有内容到客户端。关闭的顺序是:
1)关闭servlet的service方法
2)response 中setContentLength方法设置的指定数量的信息被写入response
3)调用sendError方法
4)调用sendRedirect方法
5.6 response对象的生命周期
每个response对象仅在servlet的serrvice方法或filter的doFilter的方法中有效。引擎重复使用reponse对
象,是为了降低创建response对象的开销。开发者必须注意response对象在指定范围外可能出现的一些
意外的行为。