Other Web Frameworks

本章详细介绍了 Spring 与第三方 Web 框架的集成。 Spring Framework 的核心价值主张之一就是支持_choice_。一般来说,Spring 不会强制你使用或购买任何特定的架构、技术或方法(尽管它肯定会建议使用一些替代其他一些)。在 Web 领域,这种选择和选择与开发人员及其开发团队最相关的架构、技术或方法的自由尤其明显,Spring 在该领域提供了自己的 Web 框架(Spring MVCSpring WebFlux),同时还支持与许多流行的第三方 Web 框架集成。

Common Configuration

在深入探讨各个支持的 Web 框架的具体集成之前,让我们先了解一下不特定于任何 Web 框架的常见的 Spring 配置。(本节同样适用于 Spring 自己 Web 框架的变体。)

Spring 的轻量级应用模型提倡的一个概念(因缺乏更好的词而用)是一个分层架构。请记住,在一个“经典的”分层架构中,Web 层只是众多层中的一层。它充当进入服务器端应用的入口点之一,并将任务委托给服务层中定义的服务对象(门面),来满足特定于业务(并且与表示技术无关)的用例。在 Spring 中,这些服务对象、其他特定于业务的对象、数据访问对象等都存在于一个不同的“业务上下文”中,该上下文不包含任何 Web 或表示层对象(表示对象,例如 Spring MVC 控制器,通常配置在不同的“表示上下文”中)。本节详细介绍了如何配置 Spring 容器(一个 WebApplicationContext),该容器包含您应用中的所有“业务 bean”。

进入具体问题,您需要做的就是声明一个https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/context/ContextLoaderListener.html[ContextLoaderListener]在 Web 应用程序的标准 Jakarta EE servlet web.xml 文件中,并添加一个 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 定义创建一个https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/context/WebApplicationContext.html[WebApplicationContext]对象,并将其存储在 Web 应用程序的 ServletContext 中。

所有 Java Web 框架都构建在 Servlet API 之上,所以您可以使用以下代码片段,获得 ContextLoaderListener 创建的“业务上下文”ApplicationContext 的访问权限。

以下示例展示如何获取 WebApplicationContext

WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);

{"spring-framework-api"/web/context/support/WebApplicationContextUtils.html[WebApplicationContextUtils] 类是为方便所设计的,因此您不必记住 [ServletContext] 属性的名称。它的 [getWebApplicationContext()] 方法将在 [WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE] 键下找不到对象时返回 [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 Resolver

SpringBeanFacesELResolver 是一个兼容 JSF 的 ELResolver 实现,它与 JSF 和 JSP 使用的标准统一 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>

Using FacesContextUtils

在将您的属性映射到 [faces-config.xml] 中的 bean 时,自定义 [ELResolver] 可以很好地工作,但是,有时您可能需要明确获取 bean。FacesContextUtils 类可以轻松地做到这一点。它类似于 [WebApplicationContextUtils],不同之处在于它接受一个 [FacesContext] 参数,而不是 [ServletContext] 参数。

以下示例显示了如何使用 FacesContextUtils

ApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());

Apache Struts

Struts由 Craig McClanahan 发明,是一个由 Apache Software Foundation 托管的开源项目。Struts 1.x 极大地简化了 JSP/Servlet 编程范例,赢得了许多使用专有框架的开发人员的青睐。它简化了编程模型,具有开源属性,并且拥有一个庞大的社区,这让该项目得以成长并受到 Java Web 开发人员的欢迎。

作为原版 Struts 1.x 的继任者,查看 Struts 2.x 或更新版本以及 Struts 提供的 Spring Plugin,以实现内置的 Spring 集成。

Apache Tapestry

Tapestry是“面向组件的框架,用于在 Java 中创建动态、健壮、高度可扩展的 web 应用程序”。

虽然 Spring 有自己的 powerful web layer,但通过结合 Tapestry(用于 Web 用户界面)和 Spring 容器(用于较低层级)来构建企业 Java 应用程序,可具有许多独一无二的优势。

如需了解更多信息,请参阅 Tapestry 的专用 integration module for Spring

Further Resources

以下链接指向本章中描述的各种 Web 框架的更多资源。