其他 Web 框架
本章详细介绍了 Spring 与第三方 Web 框架的集成。
Spring 框架的核心价值主张之一是实现选择。通常来说,Spring 不强制你使用或接受任何特定的架构、技术或方法(尽管它肯定会推荐一些)。这种选择最适合开发人员及其开发团队的架构、技术或方法的自由,在 Web 领域表现得最为明显,Spring 提供了自己的 Web 框架(Spring MVC 和 Spring WebFlux),同时还支持与一些流行的第三方 Web 框架集成。
通用配置
在深入研究每个受支持的 Web 框架的集成细节之前,让我们首先看一下不特定于任何一个 Web 框架的通用 Spring 配置。(本节同样适用于 Spring 自己的 Web 框架变体。)
Spring 轻量级应用程序模型所倡导的(由于缺乏更好的词语)概念之一是分层架构。请记住,在“经典”分层架构中,Web 层只是众多层中的一层。它充当服务器端应用程序的入口点之一,并将业务委托给服务层中定义的(门面)服务对象,以满足业务特定(与表示技术无关)的用例。在 Spring 中,这些服务对象、任何其他业务特定对象、数据访问对象以及其他对象存在于一个独特的“业务上下文”中,该上下文不包含任何 Web 或表示层对象(表示对象,例如 Spring MVC 控制器,通常在独特的“表示上下文”中配置)。本节详细介绍了如何配置一个包含应用程序中所有“业务 bean”的 Spring 容器(一个 WebApplicationContext)。
具体来说,您只需在 Web 应用程序的标准 Jakarta EE Servlet web.xml 文件中声明一个 ContextLoaderListener,并添加一个 contextConfigLocation <context-param/> 部分(在同一个文件中),该部分定义要加载的 Spring XML 配置文件集。
考虑以下 <listener/> 配置
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
进一步考虑以下 <context-param/> 配置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
如果您不指定 contextConfigLocation 上下文参数,ContextLoaderListener 将查找名为 /WEB-INF/applicationContext.xml 的文件进行加载。一旦上下文文件加载完毕,Spring 将根据 bean 定义创建一个 WebApplicationContext 对象,并将其存储在 Web 应用程序的 ServletContext 中。
所有 Java Web 框架都构建在 Servlet API 之上,因此您可以使用以下代码片段来访问由 ContextLoaderListener 创建的这个“业务上下文” ApplicationContext。
以下示例展示了如何获取 WebApplicationContext
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
WebApplicationContextUtils 类是为了方便而设计的,因此您无需记住 ServletContext 属性的名称。如果 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE 键下不存在对象,其 getWebApplicationContext() 方法将返回 null。为了避免应用程序中出现 NullPointerExceptions,最好使用 getRequiredWebApplicationContext() 方法。当 ApplicationContext 缺失时,此方法会抛出异常。
一旦您获得了 WebApplicationContext 的引用,就可以通过其名称或类型检索 bean。大多数开发人员通过名称检索 bean,然后将其转换为其实现接口之一。
幸运的是,本节中的大多数框架都有更简单的查找 bean 的方法。它们不仅使从 Spring 容器获取 bean 变得容易,而且还允许您在控制器上使用依赖注入。每个 Web 框架部分都有关于其特定集成策略的更多详细信息。
JSF
JavaServer Faces (JSF) 是 JCP 的标准组件化、事件驱动的 Web 用户界面框架。它是 Jakarta EE 伞形项目的一个官方组成部分,也可以单独使用,例如通过在 Tomcat 中嵌入 Mojarra 或 MyFaces。
请注意,JSF 的最新版本与应用服务器中的 CDI 基础设施紧密相关,一些新的 JSF 功能仅在这种环境下才能工作。Spring 的 JSF 支持已不再积极发展,主要用于在现代化旧版 JSF 应用程序时的迁移目的。
Spring 的 JSF 集成的关键要素是 JSF ELResolver 机制。
Spring Bean 解析器
SpringBeanFacesELResolver 是一个 JSF 兼容的 ELResolver 实现,它与 JSF 和 JSP 中使用的标准 Unified EL 集成。它首先委托给 Spring 的“业务上下文” WebApplicationContext,然后委托给底层 JSF 实现的默认解析器。
在配置方面,您可以在 JSF 的 faces-context.xml 文件中定义 SpringBeanFacesELResolver,示例如下:
<faces-config>
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
...
</application>
</faces-config>
使用 FacesContextUtils
自定义 ELResolver 在将属性映射到 faces-config.xml 中的 bean 时效果很好,但有时您可能需要显式获取一个 bean。FacesContextUtils 类使这变得容易。它类似于 WebApplicationContextUtils,只是它接受一个 FacesContext 参数而不是 ServletContext 参数。
以下示例展示了如何使用 FacesContextUtils
ApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
Apache Tapestry
Tapestry 是一个“组件导向的框架,用于在 Java 中创建动态、健壮、高度可扩展的 Web 应用程序。”
虽然 Spring 有自己的强大的 Web 层,但将 Tapestry 用于 Web 用户界面和 Spring 容器用于下层结合构建企业 Java 应用程序具有许多独特的优势。
有关更多信息,请参阅 Tapestry 专用的Spring 集成模块。