请求对象封装了客户请求的所有信息。在HTTP协议中,这个信息从客户端转发到HTTP数据头和请求的消息体的服务中。
3.1 HTTP协议参数
Servlet的请求参数由客户端以字符串形式发送给一个Servlet容器,作为其请求的一部分。当一个请求是HttpServletRequest对象时,并遇见了“When parameters are aviliable”此章节中的条件时,容器从URI查询字符串和POST数据中填入参数。
参数是以一组name-value队方式存储。一个给定的参数名可以对应多个参数值。ServletRequest接口的下述方法可以访问这些参数。
getParameter
getParameterNames
getParameterValues
getParameterMap
getParameterValues方法返回了一个字符对象数组,包含了一个参数名的所有参数值。从getParameter方法返回的值必须是由getParameterValues方法返回的String对象数组的第一个值。getParameterMap方法返回的是请求参数的Map类型,其中以name为键,以参数值为map值。
来自查询字符串和post体中数据,被存入请求参数集合中。在post体的数据之前,查询字符串数据就提供了。例如,如果一个请求由一个查询字符串“a=hello”和post主体数据“a=goodbye&a=world”构成,得到的结果参数集合将以a=(hello,goodbye,world)顺序排列。
Path参数(一个GET请求的一部分,在HTTP1.1中定义的),不会被这些API暴露。它们必须调用getRequestURI方法或者getPathInfo方法中返回的String值来解析。
3.1.1 When Parameters Are Available(什么时候参数可用)
下面是post格式的数据植入parameter集合必须满足的条件:
1 请求时一个HTTP或者HTTPS请求
2 HTTP方法是POST
3 上下文类型是application/X-WWW-form-urlencoded
4 servlet已经完成了request对象的getParameter方法中的一个的初始调用。
如果条件不满足并且POST格式的数据不再parameter集合中,post数据任必须通过请求对象的输入流使得servlet可以访问。如果条件满足,post格式的数据不再直接从请求对象的输入流中的直接读取。
3.2 File upload(文件上传)
如果一个请求是multipart/form-data类型,并且这个servlet处理的请求使用了注解@MultipartConfig,HttpServletRequest可以通过以下方法访问不同部分请求的不同部分。
public Collection<Part> getParts()
public Part getPart(String name)
每个部分提供了对数据头,与之相关的上下文类型的访问,并且通过getInputStream方法访问内容、
对于form-data部分作为Content-Disposition,虽然没有一个文件名,这个不部分的字符串值通过HttpServletRequest的getParameter/getParameterValues方法也可以访问,使用了那部分的名字。
3.3 Attributes 属性
属性是与请求关联的对象。属性可能会被设置,通过容器表达信息,否则不能借助API表达,或许可能被设置,通过一个servlet与另一个servlet进行通信(借助RequestDispatcher)。访问属性可以通过ServletRequest接口的以下方法:
getAttribute
getAttibuteNames
setAttribute
只有一个属性值可能与一个属性名关联。
以前缀java.和javax.开始的属性名已经被这个servlet规范预定了。类似地,以sun.和com.sun.为前缀的属性名也已经被Sun.Microsystems预定了。建议在属性集合中的属性名与存储领域命名的规定相一致。
3.4 Headers(消息头)
一个servlet可以访问一个HTTP请求的消息头,通过以下方法:
getHeader
getHeaders
getHeaderNames
getHeader返回给定消息头名字的一个消息头。相同名字可以有多个消息头,在一个HTTP请求中,比如Cache-Control消息头。如果一个名字对应多个消息头,getHeader方法返回请求中的第一个消息头。getHeaders方法返回一个消息头名对应的所有的可以访问的消息头值,其类型是String对象的Enumeration。
消息头可能包含int或者Date数据的String类型。HttpServletRequest接口提供了访问这些类型数据的方法:
getIntHeader
getDateHeader
如果getIntHeader方法不能将header值转为int,将跑出一个NumberFormateException异常。如果getDateHeader方法不能讲header值转为Date,将抛出一个IllegalArgumentException异常。
3.5 Request Path Elements(请求路径参数)
引导一个servlet 业务请求的请求路径由许多重要部分组成。下面的元素可以从请求URI路径中获取并在请求对象中也会暴露。
Context Path :与ServletContext关联的路径前缀是这个servlet的一部分。如果这个上下文是默认的上下文,以Web服务器ULR命名空间为基础,这个路径将是一个空字符串。否则,如果这个上下文不是在服务器命名空间的根部,路径以“/”字符开始但不以“/”结束。
Servlet Path : 这个路径部分直接对应映射;来激活这个请求。这个路径以"/"开始,除了这种情况,请求以'/*或者“”来匹配,这个时候路径是一个空字符串。
PathInfo : 这个请求路径不是上下文路径的一部分,也不是Servlet路径的一部分。如果没有额外的路径,其值为null,或者是以‘/’开头的空字符串。
HttpServletRequest接口提供了访问这个信息的接口:
getContextPath
getServletPath
getPathInfo
这点值得注意,请求URI和路径部分之间除了URI编码不同之外,下面的表达式总是正确的:
requestURI = contextPath + servletPath + pathInfo
给出了几个例子来强调上面提到的几点:
TABLE 3-1 Example Context Set Up
Context Path /catalog
Servlet Mapping Pattern: /lawn/*
Servlet: LawnServlet
Servlet Mapping Pattern: /garden/*
Servlet: GardenServlet
Servlet Mapping Pattern: *.jsp
Servlet: JSPServlet
观察下面例子的表现:
TABLE 3-2 Observed Path Element Behavior
Request Path Path Elements
/catalog/lawn/index.html 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
3.6 Path Translation Method (路径转换方法)
API提供了两种方法来获取系统文件路径,其等价于一个独特的路径。
ServletContext.getRealPath
HttpServletRequestRequest.getPathTranslated
getRealPath方法传递一个String参数并返回一个本地文件系统相对应路径的文件的String表达式。getPathTranslated方法返回这个请求的pathInfo的真正路径。
在这些情况下Servlet容器用这些方法确定一个有效文件路径,比如当web应用程序从一个激活的远程文件系统,不能从本地访问的运行,或者在一个数据库中,这些方法将返回null。
在JAR文件的META-INF/resources目录下的资源必须考虑当调用getRealPath方法时从他们包含的JAR文件中打开这些资源,在这种情况下必须返回打开的位置。
3.7 Cookie(小甜饼)
3.8 SSL Attributes(SSL属性)
3.9 Internationalization(国际化)
客户端可能可选德指明一个web服务器期望给出什么响应的语言。这个信息可以使用Accept-Language消息头还有HTTP/1.1规范的其他机制来完成。ServletRequest接口提供了如下方法来确定发送者更喜欢的位置。
getLocale
getLocales
getLocale方法将返回客户端想接受的内容的期望的环境。
getLocales方法将返回指明Locale对象的一个Enumeration,在递减的顺序中启动期望的环境,这些locales对于客户端都是可接受的。
如果客户端没有指定环境,getLocale方法返回servlet容器默认的locale。getLocales方法必须包含默认环境的单一Locale元素的一个enmueration。
3.10 请求数据编码
当前,许多浏览器不使用Content-type消息头发送一个字符编码限定符,剩下决定字符编码来读取HTTP请求。容器用来创建请求读写器和解析POST数据的默认请求字符编码必须是“ISO-8859-1”,如果客户端请求没有指定默认编码的话。然而,客户端发送一个字符编码失败,容器调用getCharacterEncoding方法返回null。
如果客户端没有指定字符编码并且请求数据采用了不同的字符编码而不是默认的,将会产生乱码。为补救这种情况,ServletRequest接口添加了一个新的方法setCharacterEncoding(String enc)方法。开发者可以重新设定字符编码。必须在解析任何post数据或者从请求中读取输入之前调用上述方法。一旦数据读取方法调用再调用字符编码方法将是无效的。
3.11 Lifetime of the Request Object(请求对象的生命周期)
每个请求对象只有在一个servlet的service方法的范围内有效,或者在一个过滤器的doFilter方法的范围内有效,除非能够异步处理并且请求对象调用startAsync方法。异步处理的时候,请求对象保持有效直到AsyncContext调用了complete方法。容器一般循环利用请求对象,便面创建的请求对象达到最大值。注意在上述描述范围之外调用startAsync方法保持请求对象的引用时不推荐的,因为这样可能有不确定的结果。