• Servlet规范之The Request


    The Request

    文章是对 JSR-000340 JavaTM Servlet 3.1 Final Release的Java™ Servlet规范的翻译,尚未校准


    请求对象封装了来自客户端请求的所有信息。在HTTP协议中,这些信息在HTTP头和请求的信息体中从客户端传输到服务器。

    HTTP协议参数

    Servlet的请求参数是由客户端发送至Servlet容器的字符串,作为其请求的一部分。当请求是一个HttpServletRequest对象,并且符合第24页 "When Parameters Are Available"中规定的条件时,容器会从URI查询字符串和POST-ed数据中填充参数。

    参数被存储为一组name-value对。对于任何给定的参数名称,可以存在多个参数值。ServletRequest接口的下列方法可用于访问参数。

    • getParameter
    • getParameterNames
    • getParameterValues
    • getParameterMap

    getParameterValues方法返回一个字符串对象数组,其中包含与参数名称相关的所有参数值。从getParameter方法返回的值必须是getParameterValues返回的String对象阵列中的第一个值。getParameterMap方法返回请求的参数的java.util.Map,它包含作为键的名称和作为映射值的参数值。

    来自查询字符串和帖子正文的数据被汇总到请求参数集。查询字符串的数据会在帖子正文的数据之前呈现。例如,如果一个请求的查询字符串为a=hello,帖子正文为a=goodbye&a=world,那么产生的参数集将被排序为a=(hello, goodbye, world)

    作为GET请求的一部分的路径参数(如HTTP 1.1所定义的)不被这些API所公开。它们必须从getRequestURI方法或getPathInfo方法返回的String值中解析出来。

    When Parameters Are Available

    以下是必须满足的条件,然后才会将表单数据填充到参数集中。

    1. 该请求是一个HTTP或HTTPS请求。
    2. HTTP方法是POST。
    3. 内容类型是 application/x-www-form-urlencoded
    4. servlet对请求对象的 getParameter系列方法进行了初始调用。

    如果不满足这些条件,并且post form数据不包括在参数集中,那么post数据仍然必须通过请求对象的输入流提供给servlet。如果条件得到满足,POST数据将不再可用于直接从请求对象的输入流中读取。

    文件上传

    Servlet容器允许在数据以multipart/form-data形式发送时上传文件。

    如果满足以下任何一个条件,Servlet容器就会提供multipart/form-data处理。

    • 处理请求的servlet被注释为@MultipartConfig,定义在第8-70页的第8.1.5节"@MultipartConfig"。
    • 部署描述符包含处理请求的Servlet的multipart-config元素。

    如何提供multipart/form-data类型的请求中的数据,取决于servlet容器是否提供multipart/form-data处理:

    • 如果servlet容器提供了multipart/form-data处理,数据将通过HttpServletRequest中的下列方法提供:

      • public Collection getParts()
      • public Part getPart(String name)

      每个part都可通过Part.getInputStream方法访问头部,相关的内容类型和内容。

      对于以表单数据的Content-Disposition的部分,即使没有文件名,该部分的字符串值也将通过HttpServletRequest上的getParametergetParameterValues方法得到该部分的名称。

    • 如果servlet容器不提供 multi-part/form-data处理,数据将通过HttpServletReuqest.getInputStream来获得。

    Attributes

    属性是与一个请求相关的对象。属性可以由容器设置,以表达无法通过API表达的信息,也可以由Servlet设置,以向另一个Servlet传递信息(通过RequestDispatcher)。属性可以通过ServletRequest接口的下列方法来访问:

    • getAttribute
    • getAttributeNames
    • setAttribute

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

    java. javax.开头的属性名被保留给本规范定义。同样,以sun.com.sun.oraclecom.oracle开头的属性名也被保留给Oracle公司定义。建议放在属性集中的所有属性都按照《Java编程语言规范》建议的反向域名惯例来命名包。

    Headers

    一个servlet可以通过HttpServletRequest接口的以下方法访问HTTP请求的头信息:

    • getHeader
    • getHeaders
    • getHeaderNames

    getHeader方法返回一个给定的头的名称。在一个HTTP请求中可以有多个同名的头,例如Cache-Control头。如果有多个同名的头信息,getHeader方法会返回请求中的第一个头信息。getHeaders方法允许访问所有与特定头名称相关的头值,返回一个Enumeration的字符串对象。

    头信息可以包含 intDate数据的String表示。HttpServletRequest接口的下列方便方法提供了对这些格式之一的头数据的访问:

    • getIntHeader
    • getDateHeader

    如果getIntHeader方法不能将头的值翻译成int,就会抛出NumberFormatException。如果getDateHeader方法不能将标题翻译成Date对象,就会抛出IllegalArgumentException

    Request Path 元素

    服务请求的servlet的请求路径由许多重要部分组成。以下元素从请求URI路径中获得,并通过请求对象暴露:

    • Context Path: 与ServletContext相关的路径前缀,该Servlet是其中的一部分。如果这个上下文是基于Web服务器的URL名称空间的 "default"上下文,这个路径将是一个空字符串。否则,如果该上下文没有基于服务器名称空间的根目录,那么该路径以一个/字符开始,但不以一个/字符结束。
    • Servlet Path: 直接对应于激活该请求的映射的路径部分。这个路径以/字符开始,除非请求与/*或" "模式匹配,在这种情况下,它是一个空字符串。
    • PathInfo: 请求路径中不属于Context Path或Servlet Path的部分。如果没有额外的路径,它就是空的,或者是一个带/的字符串。

    使用HttpServletRequest接口中的下面方法来访问这些信息:

    • getContextPath
    • getServletPath
    • getPathInfo

    需要注意的是,除了请求URI和路径部分的URL编码不同,下面的等式总是正确的:

    requestURI = contextPath + servletPath + pathInfo

    举几个例子来说明上述观点,请考虑以下几点:

    TABLE 3-1 Example Context Set Up

    ContextPath/catalog
    ServletMappingPattern: /lawn/*
    Servlet: LawnServlet
    ServletMappingPattern: /garden/*
    Servlet: GardenServlet
    ServletMappingPattern: *.jsp
    Servlet: JSPServlet

    The following behavior is observed:

    TABLE 3-2 Observed Path Element Behavior

    Request PathPath Elements
    /catalog/lawn/index.htmlContextPath: /catalog
    ServletPath: /lawn
    PathInfo: /index.html
    /catalog/garden/implements/ContextPath: /catalog
    ServletPath: /garden
    PathInfo: /implements/
    /catalog/help/feedback.jspContextPath: /catalog
    ServletPath: /help/feedback.jsp
    PathInfo: null

    路径转换方法

    在API中有两个方便的方法,允许开发者获得相当于特定路径的文件系统路径。这些方法是:

    • ServletContext.getRealPath
    • HttpServletRequest.getPathTranslated

    getRealPath方法接受一个String参数,并返回一个路径所对应的本地文件系统中的文件的String表示。getPathTranslated方法计算请求的pathInfo的真实路径。

    在Servlet容器无法为这些方法确定有效的文件路径的情况下,例如,当Web应用程序从归档文件、在本地无法访问的远程文件系统或在数据库中执行时,这些方法必须返回空。JAR文件的META-INF/resources目录下的资源,只有在调用getRealPath()时,容器已经将其从包含的JAR文件中解压,才必须考虑,在这种情况下,必须返回解压的位置。

    Non Blocking IO

    Web容器中的非阻塞请求处理有助于改善不断增长的对改进Web容器可扩展性的需求,增加Web容器可同时处理的连接数。Servlet容器中的非阻塞IO允许开发者在数据可用时读取数据,或在可能时写入数据。非阻塞IO只适用于Servlet和过滤器中的异步请求处理(如第2-10页第2.3.3.3节 "异步处理 "中的定义),以及升级处理(如第2-20页第2.3.3.5节 "升级处理 "中的定义)。否则,当调用ServletInputStream.setReadListenerServletOutputStream.setWriteListener时,必须抛出一个IllegalStateException

    The ReadListener provides the following callback methods for non blocking IO

    ReadListener为非阻塞性IO提供以下回调方法:

    • ReadListener
      • onDataAvailable(). 当可以从传入的请求流中读取数据时,onDataAvailable方法会被调用到 ReadListener上。容器将在数据可被读取时第一次调用该方法。容器随后将调用onDataAvailable方法,当且仅当ServletInputStream上的isReady方法(如下所述)返回false
      • onAllDataRead(). 当你完成了对注册了监听器的ServletRequest的所有数据的读取时,onAllDataRead方法被调用。
      • onError(Throwable t). 如果在处理请求时有任何错误或异常,onError方法会被调用。

    Servlet容器必须以线程安全的方式访问ReadListener中的方法。

    除了上面定义的 ReadListener之外,在ServletInputStream类中还增加了以下方法:

    • ServletInputStream
      • boolean isFinished(). 当所有与 ServletInputStream相关的请求数据被读取时,isFinished方法返回true。否则它将返回false
      • boolean isReady(). isReady方法返回true,如果数据可以无阻塞地被读取。如果没有数据可以在不阻塞的情况下被读取,则返回 “false”。如果isReady返回false,调用read方法是非法的,必须抛出一个IllegalStateException
      • void setReadListener(ReadListener listener). 设置上面定义的ReadListener,使其被调用,以非阻塞的方式读取数据。一旦监听器与给定的ServletInputStream相关联,容器就会在数据可以读取、所有数据都已读取或处理请求时出现错误时调用ReadListener的方法。注册一个ReadListener将启动非阻塞的IO。此时切换到传统的阻塞式IO是非法的,必须抛出一个IllegalStateException。在当前请求的范围内对setReadListener的后续调用是非法的,必须抛出IllegalStateException

    Cookies

    HttpServletRequest接口提供了getCookies方法来获取请求中存在的cookies数组。这些cookie是在客户端发出的每个请求中从客户端发送到服务器的数据。通常情况下,客户端作为cookie的一部分发回的唯一信息是cookie名称和cookie值。当cookie被发送到浏览器时可以设置的其他cookie属性,如评论,通常不被返回。该规范还允许cookies为HttpOnlycookies。HttpOnlycookie向客户端表明,它们不应该被暴露给客户端脚本代码(除非客户端知道要寻找这个属性,否则它不会被过滤掉)。使用HttpOnly cookies有助于减轻某些类型的跨站脚本攻击。

    SSL Attributes

    如果一个请求是通过安全协议(如HTTPS)传输的,这一信息必须通过ServletRequest接口的isSecure方法公开。Web容器必须向Servlet程序员公开以下属性:

    TABLE 3-3 Protocol Attributes

    AttributeAttribute NameJava Type
    cipher suitejavax.servlet.request.cipher_suiteString
    bit size of the algorithmjavax.servlet.request.key_sizeInteger
    SSL session idjavax.servlet.request.ssl_session_idString

    如果有一个与请求相关的SSL证书,它必须由servlet容器暴露给servlet程序员,作为java.security.cert.X509Certificate类型的对象数组,并通过javax.servlet.request.X509CertificateServletRequest属性访问。

    这个数组的顺序被定义为按照信任度的升序排列。链中的第一个证书是由客户设置的,下一个是用来验证第一个的,以此类推。

    国际化

    客户端可以选择向网络服务器表明他们希望响应的语言。这个信息可以从客户端使用Accept-Language标头和HTTP/1.1规范中描述的其他机制来传达。ServletRequest接口中提供了以下方法来确定发送者的首选语言。

    • getLocale
    • getLocales

    getLocale方法将返回客户想要接受的内容的首选地区。参见RFC 2616 (HTTP/1.1)第14.4节,了解更多关于如何解释Accept-Language头以确定客户端的首选语言。

    getLocales方法将返回一个Locale对象的枚举,按照从首选语言开始的递减顺序,指出客户可以接受的语言。

    如果客户没有指定首选的locale,getLocale方法返回的locale必须是servlet容器的默认locale,getLocales方法必须包含默认locale的一个Locale元素的枚举。

    请求数据的编码

    目前,许多浏览器并不随Content-Type头发送 char编码修饰符,这就使读取HTTP请求的字符编码的确定成为可能。如果客户端请求没有指定编码,容器用来创建请求阅读器和解析POST数据的默认编码必须是 “ISO-8859-1”。然而,为了向开发者表明,在这种情况下,客户端未能发送字符编码,容器会从getCharacterEncoding方法中返回null

    如果客户端没有设置字符编码,而请求数据的编码与上述的默认编码不同,就会发生中断。为了补救这种情况,一个新的方法setCharacterEncoding(String enc)已经被添加到ServletRequest接口中。开发者可以通过调用这个方法来覆盖由容器提供的字符编码。它必须在解析任何职位数据或从请求中读取任何输入之前被调用。一旦数据被读取,调用此方法将不会影响编码。

    请求对象的生命周期

    每个请求对象只在servlet的service方法的范围内有效,或者在过滤器的doFilter方法的范围内有效,除非组件的异步处理被启用,并且startAsync方法被调用到请求对象上。在异步处理发生的情况下,请求对象仍然有效,直到completeAsyncContext上被调用。容器通常会回收请求对象,以避免创建请求对象的性能开销。开发者必须意识到,不建议在上述范围之外维护对startAsync未被调用的请求对象的引用,因为这可能会产生不确定的结果。

    在升级的情况下,上述情况仍然适用。

  • 相关阅读:
    Python基础——类和对象
    PHP去除字符串前或后的字符或空格
    【测试工具】Fiddler
    Flume的安装部署及常见问题解决
    js--定时器--匀速动画,缓动动画
    网络安全(黑客)自学
    cookies和session模拟学生用户登录
    通信设备为什么需要接地阻?
    SCI常见词汇表达
    Qt之进程通信-QProcess(含源码+注释)
  • 原文地址:https://blog.csdn.net/weixin_43820556/article/details/127970419