zoukankan      html  css  js  c++  java
  • 20200311 9. 分派请求

    9. 分派请求

    构建 Web 应用时,把请求转发给另一个 servlet 处理、或在 response 中包含另一个 servlet 的输出通常是很有
    用的。 RequestDispatcher 接口提供了一种机制来实现这种功能。

    当请求启用异步处理时, AsyncContext 允许用户将这个请求转发到 servlet 容器。

    9.1 获得一个 RequestDispatcher

    实现了 RequestDispatcher 接口的对象,可以从 ServletContext 中的下面方法得到:

    • getRequestDispatcher
    • getNamedDispatcher

    getRequestDispatcher 方法需要一个 String 类型的参数描述在 ServletContext 作用域内的路径。这个路径必须是相对于 ServletContext 的根路径,或以 / 开头,或者为空。该方法根据这个路径使用 servlet 路径匹配规则(见第 12 章,请求映射到 servlet)来查找 servlet,把它包装成 RequestDispatcher 对象并返回。如果基于给定的路径没有找到相应的 servlet,那么返回这个路径内容提供的 RequestDispatcher

    getNamedDispatcher 方法使用一个 ServletContext 知道的 servlet 名称作为参数。如果找到一个 servlet,则把它包装成 RequestDispatcher 对象,并返回该对象。如果没有与给定名字相关的 servlet,该方法必须返回 null

    为了让 RequestDispatcher 对象使用相对于当前请求路径的相对路径(不是相对于 ServletContext 根路径)获得一个 servlet,在 ServletRequest 接口中提供了 getRequestDispatcher 方法。

    此方法的行为与 ServletContext 中同名的方法相似。 Servlet 容器根据 request 对象中的信息把给定的相对路
    径转换成当前 servlet 的完整路径。例如,在以 / 作为上下文根路径和请求路径/garden/tools.html 中,通过
    ServletRequest.getRequestDispatcher("header.html") 获 得 的 请 求 调 度 器 和 通 过 调 用
    ServletContext.getRequestDispatcher("/garden/header.html")获得的完全一样。

    9.1.1 请求调度器路径中的查询字符串

    ServletContextServletRequest 中创建 RequestDispatcher 对象的方法使用的路径信息中允许附加可选的查询字符串信息。比如,开发人员可以通过下面的代码来获得一个 RequestDispatcher

    String path = “/raisins.jsp?orderno=5”;
    RequestDispatcher rd = context.getRequestDispatcher(path);
    rd.include(request, response);
    

    查询字符串中指定的用来创建 RequestDispatcher 的参数优先于传递给它包含的 servlet 中的其他同名参数。

    RequestDispatcher 相关的参数作用域仅适用于包含(include)或转发(forward)调用期间。

    9.2 请求调度器的使用

    要使用请求调度器, servlet 可调用 RequestDispatcher 接口的 includeforward 方法。这些方法的参数既可以是 javax.servlet.Servlet 接口的 service 方法传来的 request 和 response 对象实例,也可以是本规范的 2.3 版 本中介绍的 request 和 response 包装器类的子类对象实例。对于后者,包装器实例必须包装容器传递到 service 方法中的 request 和 response 对象。

    容器提供者应该保证分发到目标 servlet 的请求作为原始请求发生在的同一个 JVM 的同一个线程中。

    9.3 Include 方法

    RequestDispatcher 接口的 include 方法可能随时被调用。 include 方法的目标 servlet 能够访问 request 对象的各个方法( all aspects),但是使用 response 对象的方法会受到更多限制。

    它只能把信息写到 response 对象的 ServletOutputStreamWriter 中,或提交在最后写保留在 response 缓冲区中的内容,或通过显式地调用 ServletResponse 接口的 flushBuffer 方法。它不能设置响应头部信息或调用任何影响响应头部信息的方法, HttpServletRequest.getSession()HttpServletRequest.getSession(boolean)方法除 外 。 任 何 试 图 设 置 头 部 信 息 必 须 被 忽 略 , 任 何 调 用HttpServletRequest.getSession()HttpServletRequest.getSession(boolean)方法将需要添加一个 Cookie 响应头部信息,如果响应已经提交,必须抛出一个 IllegalStateException 异常。

    如果默认的 servlet 是 RequestDispatch.include()的目标 servlet,而且请求的资源不存在,那么默认的 servlet 必须抛出 FileNotFoundException 异常。如果这个异常没有被捕获和处理,以及响应还未提交,则响应状态码必须被设置为 500

    9.3.1 内置请求参数

    除了可以用 getNamedDispatcher 方法获得 servlet 外,已经被另一个 servlet 使用 RequestDispatcherinclude 方法调用过的 servlet,有权访问被调用过的 servlet 的路径。

    以下的 request 属性必须被设置:

    • javax.servlet.include.request_uri
    • javax.servlet.include.context_path
    • javax.servlet.include.servlet_path
    • javax.servlet.include.path_info
    • javax.servlet.include.query_string

    这些属性可以通过包含的 servlet 的 request 对象的 getAttribute 方法访问,它们的值必须分别与被包含 servlet 的请求 RUI、上下文路径、 servlet 路径、路径信息、查询字符串相等。如果随后的请求包含这些属性,那么这些属性会被后面包含的属性值替换。

    如果包含的 servlet 通过 getNamedDispatcher 方法获得,那么这些属性不能被设置。

    9.4 Forward 方法

    RequestDispatcher 接口的 forward 方法,只有在没有输出提交到向客户端时,通过正在被调用的 servlet 调用。如果 response 缓冲区中存在尚未提交的输出数据,这些数据内容必须在目标 servlet 的 service 方法调用前清除。如果 response 已经提交,必须抛出一个 IllegalStateException 异常。

    request 对象暴露给目标 servlet 的路径元素(path elements)必须反映获得 RequestDispatcher 使用的路径。唯一例外的是,如果 RequestDispatcher 是通过 getNamedDispatcher 方法获得。这种情况下, request 对象的路径元素必须反映这些原始请求。

    RequestDispatcher 接口的 forward 方法无异常返回之前,响应的内容必须被发送和提交,且由 Servlet 容器关闭,除非请求处于异步模式。如果 RequestDispatcher.forward()的目标发生错误,异常信息会传回所有调用它经过的过滤器和 servlet,且最终传回给容器。

    9.4.1 查询字符串

    在转发或包含请求时请求调度机制负责聚集( aggregating)查询字符串参数。

    9.4.2 转发的请求参数

    除了可以用 getNamedDispatcher 方法获得 servlet 外, 已经被另一个 servlet 使用 RequestDispatcherforward 方法调用过的 servlet,有权访问被调用过的 servlet 的路径。

    以下的 request 属性必须设置:

    • javax.servlet.forward.request_uri
    • javax.servlet.forward.context_path
    • javax.servlet.forward.servlet_path
    • javax.servlet.forward.path_info
    • javax.servlet.forward.query_string

    这些属性的值必须分别与 HttpServletRequestgetRequestURI,、 getContextPathgetServletPathgetPathInfogetQueryString 方法的返回值相等,这些方法在从客户端接收到的 request 对象上调用,值传递给调用链中的第一个 servlet 对象。(在 request 对象上调用从客户端接收请求的调用链中的第一个 servlet 对象)

    这些属性通过转发 servlet 的 request 对象的 getAttribut 方法访问。请注意,即使在多个转发和相继的包含( subsequent includes)被调用的情况下,这些属性必须始终反映原始请求中的信息。

    如果转发的 servlet 使用 getNamedDispatcher 方法获得,这些属性必须不能被设置。

    9.5 错误处理

    如果请求分发的目标 servlet 抛出运行时异常或受检查类型异常 ServletExceptionIOException,异常应该传播到调用的 servlet。所有其它的异常都应该被包装成ServletExceptions,异常的根本原因设置成原来的异常,因为它不应该被传播。

    9.6 获得一个异步上下文对象

    实现了 AsyncContext 接口的对象可从 ServletRequest 的一个 startAsync 方法中获得,一旦有了 AsyncContext 对象,你就能够使用它的 complete() 方法来完成请求处理,或使用下面描述的转发方法。

    9.7 Dispatch 方法

    可以使用 AsyncContext 中下面的方法来转发请求:

    • dispatch(path)

      这个 dispatch 方法的 String 参数描述了一个在 ServletContext 作用域中的路径。这个路径必须是相对于
      ServletContext 的根路径并以 / 开头。

    • dispatch(servletContext, path)

      这个 dispatch 方法的 String 参数描述了一个在 ServletContext 指定作用域中的路径。这个路径必须是相对于 ServletContext 的根路径并以 开头。

    • dispatch()

      这个方法没有参数,它使用原来的 URI 路径。如果 AsyncContext 已经通过 startAsync(ServletRequest, ServletResponse) 初始化,且传递过来的 request 是 HttpServletRequest 的实例,那么这个请求分发到
      HttpServletRequest.getRequestURI()返回的 URI。否则当最后转发时当由容器转发到 request 的 URI。

      AsyncContext 接口中的 dispatch 方法可被等待异步事件发生的应用程序调用。如果 AsyncContext 已经调用了 complete() 方法,必须抛出 IllegalStateException 异常。所有不同的 dispatch 方法会立即返回并且不会提交 response。

      request 对象暴露给目标 servlet 的路径元素( path elements)必须反映 AsyncContext.dispatch 中指定的路径。

    9.7.1 查询字符串

    请求调度机制是在调度请求时负责聚焦( aggregating)查询字符串。

    9.7.2 调度请求参数

    使用 AsyncContextdispatch 方法调用过的 servlet 能够访问原始请求的路径。

    下面的 request 属性必须设置:

    • javax.servlet.async.request_uri
    • javax.servlet.async.context_path
    • javax.servlet.async.servlet_path
    • javax.servlet.async.path_info
    • javax.servlet.async.query_string

    这些属性的值必须分别与 HttpServletRequestgetRequestURIgetContextPathgetServletPathgetPathInfogetQueryString 方法的返回值相等,这些方法在从客户端接收到的 request 对象上调用,值传递给调用链中的第一个 servlet 对象。

    这些属性通过转发 servlet 的 request 对象的 getAttribut 方法访问。请注意,即使在多个转发和相继的包含( subsequent includes)被调用的情况下,这些属性必须始终反映原始请求中的信息。

  • 相关阅读:
    Admin注册和路由分发详解
    自定义Xadmin
    苑昊老师的博客
    pip 国内源 配置
    Django模型层(2)
    Django 中间件
    Django form表单
    整理的最全 python常见面试题(基本必考)
    AJAX
    Cookie、Session和自定义分页
  • 原文地址:https://www.cnblogs.com/huangwenjie/p/12462571.html
Copyright © 2011-2022 走看看