【问题标题】:How does the FacesServlet know which facelet to render based on the URL?FacesServlet 如何知道根据 URL 渲染哪个 facelet?
【发布时间】:2013-03-29 16:09:03
【问题描述】:

我一直在检查,但找不到关于 FacesServlet 如何将 URL 解析为 Web 应用程序文件结构中的真实文件的解释。在 servlet 的上下文中,我的理解是 URL 只是您希望客户端使用的虚构名称。然后,在 web.xml 中,您将特定的 servlet 映射到 URL 模式,但是 servlet 的真实名称/位置对外界是隐藏的……这通常是针对 servlet 的。

特别是对于 JSF 2,我们处理 FacesServlet,这引出了我的第一个问题:FacesServlet 是我需要在我的应用程序中提供映射详细信息的唯一 servlet(也是我需要的唯一 servlet,期间)? 答案似乎是“是”,但如果在某些情况下并非如此,请举个例子。

通过阅读有关 SO 的其他问题,我了解到并非所有请求都需要通过 FacesServlet,因此基本上请求分为 A)对不应该由 FacesServlet 处理的静态内容的请求,以及 B)对需要由 FacesServlet 处理的动态内容。 那么,静态内容是如何获得的呢?只是通过传入的请求,其中的 URL 与 FacesServlet 的 URL 模式不匹配,但匹配应用程序文件结构中的真实文件位置?

最后,我的主要问题是:当一个请求与 FacesServlet 的 URL 模式匹配时,FacesServlet 如何知道要呈现哪个视图文件 (.xhtml)?使用我需要遵循的 JSF 2 才能使其工作?如果不是,那么我不明白,因为就像我在上面提到的“通用”servlet 的情况下,URL 可以包含一个与真实文件名无关的名称,只要它映射到web.xml 文件中的正确 servlet。我觉得我在这里遗漏了一些明显(和重要)的东西。我唯一能想到的是 URL 应该匹配一个真实的文件位置,或者有另一个映射表或将 URL 与视图文件相关联的东西。

对了,我看了this question,有相关但没有任何答案。

谢谢!

【问题讨论】:

    标签: jakarta-ee servlets jsf-2 url-routing facesservlet


    【解决方案1】:

    servlet specification 第 10.5 节概述了提供静态内容的最简单方法:

    Web 应用程序以结构化的目录层次结构存在。这件事的根源 层次结构用作作为应用程序一部分的文件的文档根。为了 例如,对于在 Web 容器中具有上下文路径 /catalog 的 Web 应用程序, Web 应用程序层次结构或 JAR 文件中的 index.html 文件 在 WEB-INF/lib 中,包括 META-INF/resources 下的 index.html 可以提供目录以满足来自 /catalog/index.html 的请求。如果 index.html 存在于根上下文和 META-INF/resources 中 应用程序的 WEB-INF/lib 目录中的 JAR 文件的目录,然后该文件 必须使用在根上下文中可用的。 URL 匹配规则 上下文路径在第 12 章“将请求映射到 Servlet”中列出。

    应用程序层次结构中存在一个名为“WEB-INF”的特殊目录。这 目录包含与应用程序相关但不在文档中的所有内容 应用程序的根。大多数 WEB-INF 节点不是公共文档的一部分 应用程序树。除了静态资源和打包在 META 中的 JSP- 位于 WEB-INF/lib 目录中的 JAR 文件的 INF/resources,没有其他 WEB-INF 目录中包含的文件可以由 容器。

    也就是说,要提供静态内容,将内容保存在 Web 应用程序的相应目录中就足够了。

    Servlet 映射是对这个“隐式”servlet 的补充。因此,大多数 JSF 应用程序只声明 FacesServlet。 IIRC,在最近的 JSF 实现中,如果省略了它的声明,servlet 甚至会声明它自己,所以你甚至不必显式声明它。

    FacesServlet 如何定位要使用的视图的定义在JSF specification 中定义,特别是第 7.6.2 节:

    术语视图标识符和 viewId 在下面可互换使用,表示生成视图的 Web 应用程序资源的上下文相对路径,例如 JSP 页面或 Facelets 页面。在 JSP 情况下,这是表示视图的 jsp 页面的上下文相对路径,例如 /foo.jsp。在 Facelets 案例中,这是表示视图的 XHTML 页面的上下文相对路径,例如 /foo.xhtml。

    JSF 实现必须提供默认 ViewHandler 实现,以及提供 ViewDeclarationLanguage 的默认 ViewDeclarationLanguageFactory 实现 旨在支持呈现包含 JSF 组件的 JSP 页面和包含 JSF 组件的 Facelets 页面的实现。

    默认实现在以下 7.6.2.1 节中指定。我饶了你的完整报价。要点是,如果 Faces Servlet 使用前缀映射(例如 /faces/**)进行映射,则 viewId 是 URL 中前缀之后的部分,如果 Faces Servlet 使用后缀映射进行映射(例如 *.jsf) ,viewId 是 URL 中上下文路径之后的部分,替换了文件扩展名。例如,如果 servlet 映射到 *.jsf,则对 URL http://host/context/admin/userlist.jsf 的请求将从 Web 应用程序目录中的文件 admin/userlist.xhtml 中读取视图定义。

    【讨论】:

    • 感谢规格链接。因此,如果我理解正确,JSF 中有一个隐式约定,即 URL 的 viewId 部分必须与资源的“真实”相对路径匹配,否则将找不到任何东西。这是正确的吗?这是有道理的,因为否则我不知道 FacesServlet 怎么知道要返回哪个 facelet。
    • 是的,没错。当然,您可以自定义该约定,甚至可以从完全不同的源加载视图定义(JSF 的内部工作是完全可自定义的),但通常,只需使用该约定。
    • 太棒了。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    相关资源
    最近更新 更多