轻量级Java EE企业应用开发实战
上QQ阅读APP看书,第一时间看更新

3.4 请求

请求对象封装了客户端请求的所有信息。在HTTP协议中,这些信息包含在从客户端发送到服务器请求的HTTP头部和消息体中。

3.4.1 HTTP协议参数

Servlet的请求参数以字符串的形式作为请求的一部分从客户端发送到Servlet容器。当请求是一个HttpServletRequest对象且符合“参数可用时”描述的条件时,容器从URI查询字符串和POST数据中填充参数。参数以一系列的名-值对(name-value)的形式保存。任何给定的参数的名称可存在多个参数值。ServletRequest接口的以下方法可访问这些参数:

  • getParameter
  • getParameterNames
  • getParameterValues
  • getParameterMap

getParameterValues方法返回一个String对象的数组,包含了与参数名称相关的所有参数值。

getParameter方法的返回值必须是getParameterValues方法返回的String对象数组中的第一个值。

getParameterMap方法返回请求参数的一个java.util.Map对象,其中以参数名称作为Map键,参数值作为Map值。

查询字符串和POST请求的数据被汇总到请求参数集合中。查询字符串数据放在POST数据之前。例如,请求由查询字符串a=hello和POST数据a=goodbye&a=world组成,得到的参数集合顺序将是a=(hello, goodbye, world)。

这些API不会暴露GET请求(HTTP 1.1所定义的)的路径参数。它们必须从getRequestURI方法或getPathInfo方法返回的字符串值中解析。

post表单数据填充到参数集(Parameter Set)前必须满足以下条件:

  • 该请求是一个HTTP或HTTPS请求。
  • HTTP方法是POST。
  • 内容类型是application/x-www-form-urlencoded。
  • 该Servlet已经对请求对象的任意getParameter方法进行了初始调用。

如果不满足这些条件,而且参数集中不包括post表单数据,那么Servlet必须可以通过请求对象的输入流得到post数据。如果满足这些条件,那么从请求对象的输入流中直接读取post数据将不再有效。

3.4.2 属性

属性是与请求相关联的对象。属性可以由容器设置来表达信息,否则无法通过API表示,或者由Servlet设置将信息传达给另一个Servlet(通过RequestDispatcher)。属性通过ServletRequest接口中的以下方法来访问:

  • getAttribute
  • getAttributeNames
  • setAttribute

一个属性名称只能关联一个属性值。

3.4.3 请求头

通过下面的HttpServletRequest接口方法,Servlet可以访问HTTP请求的头信息:

  • getHeader
  • getHeaders
  • getHeaderNames

getHeader方法返回给定头名称的头。多个头可以具有相同的名称,例如HTTP请求中的Cache-Control头。如果多个头的名称相同,getHeader方法就返回请求中的第一个头。getHeaders方法允许访问所有与特定头名称相关的头值,返回一个String对象的Enumeration(枚举)。

头可包含String形式的Int或Date数据。HttpServletRequest接口提供如下方法访问这些类型的头数据:

  • getIntHeader
  • getDateHeader

如果getIntHeader方法不能转换为Int的头值,就抛出NumberFormatException异常。如果getDateHeader方法不能把头转换成一个Date对象,就抛出IllegalArgumentException异常。

3.4.4 请求路径元素

引导Servlet服务请求的请求路径由许多重要部分组成:

    URI = Context Path + Servlet Path + PathInfo

其中:

  • Context Path:与ServletContext相关联的路径前缀是这个Servlet的一部分。如果这个上下文是基于Web服务器的URL命名空间的“默认”上下文,那么这个路径将是一个空字符串。否则,如果上下文不是基于服务器的命名空间,那么这个路径以“/”字符开始,但不以“/”字符结束。
  • Servlet Path:路径部分直接与激活请求的映射对应。这个路径以“/”字符开头,如果请求与“/*”或“”模式匹配,在这种情况下,它是一个空字符串。
  • PathInfo:请求路径的一部分,不属于Context Path或Servlet Path。如果没有额外的路径,它要么是null,要么是以“/”开头的字符串。使用HttpServletRequest接口中的以下方法来访问这些信息:

 getContextPath

 getServletPath

 getPathInfo

表3-1展示了请求路径元素的使用例子。

表3-1 请求路径元素的使用例子

3.4.5 路径转换方法

在Servlet API中有两个方便的方法,允许开发者获得与某个特定的路径等价的文件系统路径。这两个方法是:

  • ServletContext.getRealPath
  • HttpServletRequest.getPathTranslated

getRealPath方法需要一个String参数,并返回一个String形式的路径,这个路径对应一个在本地文件系统上的文件。getPathTranslated方法推断出请求的pathInfo的实际路径。

这些方法在Servlet容器无法确定一个有效的文件路径的情况下返回null,比如Web应用程序不能访问远程文件系统上的本地文件。JAR文件中META-INF/resources目录下的资源只有当调用getRealPath()方法时才认为容器已经从包含它的JAR文件中解压,在这种情况下必须返回解压缩后的位置。

3.4.6 请求数据编码

目前,很多HTTP请求并不一定会在Content-Type头上设置字符编码限定符。如果客户端请求没有指定请求默认的字符编码,那么容器用来创建请求读取器和解析POST数据的编码必须是ISO-8859-1。

如果客户端没有设置字符编码,并使用不同的编码来编码请求数据,而不是使用上面描述的默认的字符编码,那么可能会发生问题。为了弥补这种情况,开发人员可以通过下面几种方法来覆盖由容器提供的字符编码:

  • *ServletContext上提供了setRequestCharacterEncoding(String enc)。
  • web.xml中提供了元素。
  • ServletRequest接口上提供了setCharacterEncoding(String enc)。

必须在解析任何post数据或从请求读取任何输入之前调用上述方法。上述方法一旦调用,将不会影响已经读取的数据的编码。