实现企业集成模式 第0部分
在我关于Spring Integration的演讲之后,我收到了很多关于澄清和示例的问题。为了满足需求,我将开始一个小系列,介绍如何使用Spring Integration实现不同的集成模式。这第一篇文章将侧重于基础知识。它将向您展示如何启动和运行,并带您了解其中一个示例。
如果您以前从未听说过Spring Integration,那么阅读Mark Fisher撰写的介绍性博客或浏览项目网站,熟悉它可能是一个好主意。总的来说
让我先声明一下:……
在我关于Spring Integration的演讲之后,我收到了很多关于澄清和示例的问题。为了满足需求,我将开始一个小系列,介绍如何使用Spring Integration实现不同的集成模式。这第一篇文章将侧重于基础知识。它将向您展示如何启动和运行,并带您了解其中一个示例。
如果您以前从未听说过Spring Integration,那么阅读Mark Fisher撰写的介绍性博客或浏览项目网站,熟悉它可能是一个好主意。总的来说
让我先声明一下:……
亲爱的Spring社区,
我们很高兴地宣布 Spring Web Flow 2 正式上市。 下载 | 文档
Spring Web Flow 是 Spring Portfolio 中专注于提供构建和运行富 Web 应用程序的基础设施的项目。作为 Spring 项目,Web Flow 基于 Spring Web MVC 框架提供:
Web Flow 2 发行版的模块及其与 Spring Framework 的关系如下所示:
Spring Web MVC 框架是 Spring Framework 发行版的模块,它使用经过验证的模型视图控制器(MVC)范例为使用 Spring 开发 Web 应用程序提供了基础。Web Flow 发行版的每个模块都建立在这个基础上。
Web Flow 模块是 MVC 的扩展,允许您使用 特定领域语言 定义控制器。这种语言旨在模拟需要多次服务器请求才能完成的用户交互,或者可以从不同上下文调用。
Spring JavaScript 是一个 JavaScript 抽象框架,可以轻松编写非侵入性 JavaScript,以逐步增强网页的行为。该框架包含一个公共 JavaScript API 以及一个基于 Dojo Toolkit 的实现。Spring.js 旨在简化常见企业场景中 Dojo 的使用,同时保留其在高级用例中的全部功能。
Spring JavaScript 可以与任何服务器端框架协同工作。Web Flow 2 发行版包括 Spring JavaScript 和 Spring Web MVC 之间方便的集成,用于处理 Ajax 请求。
Spring Faces 模块包含 Spring 对 JavaServerFaces 的支持。这种支持允许您在熟悉的 Spring MVC 和 Web Flow Controller 环境中使用 JSF 作为视图技术。通过这种架构方法,您可以结合 JSF UI 组件模型的优势和 Web MVC 架构的优势。Spring Faces 还包含一个基于 Spring JavaScript 的轻量级组件库,用于以渐进的方式声明式地启用 Ajax 和客户端验证行为。
除了引入新的 Spring Faces 和 Spring Javascript 模块外,Web Flow 2 发行版还解决了两个主要主题:集成和简洁性。
在所有模块中,Web Flow 2 发行版都增加了许多有趣的集成,让您可以丰富您的 Web 应用程序。这些集成支持:
Web Flow 2 中的 flow 定义语言得到了极大的简化,同时整体功能也更加强大。这些简化包括:
InfoQ 有一个 讨论帖 总结了对 SpringSource 应用平台发布公告的反应。Michael Burke 在该帖中提出了一个 很棒的问题,可以这样转述:“抛开围绕 OSGi 的炒作,如果我将目前打包为 EAR 的应用程序移植到 OSGi bundles,我能期望看到什么好处?”
我开始在 InfoQ 帖子中回答这个问题,但我的答案对于评论来说太长了,所以我将在这里解决。
这个问题问得很好。基于 OSGi 的应用程序与传统的基于 JEE EAR 的应用程序之间的主要区别在于模块化得到了改进。所以问题变成了,这种改进的模块化是否给我带来了任何好处,如果带来了,它们是什么?《设计规则,模块化的力量》一书对这个问题进行了非常详尽的论述。它提供了很好的背景知识,但我感觉 Michael 可能正在寻找一些比那本书中更不理论化的东西……
SpringSource Application Platform 的主要优势之一是其按需供应依赖项的能力。这有两个好处:它确保平台内存占用尽可能小,并且允许应用程序在不将所有依赖项封装在单一部署单元(例如 WAR 文件)中的情况下进行部署。要利用这些功能,您需要了解平台的供应存储库,而这篇博文将提供这些信息。
如您所见,有三个主要目录:bundles、installed 和 libraries。installed 用于平台内部使用,所以我们将重点关注 bundles 和 libraries 目录。每个目录包含多个子目录,用于分隔不同类型的依赖项。当平台启动已部署的应用程序时,其...
在 JavaOne 会议期间,在线上和线下,关于 SpringSource Application Platform 的讨论非常多。WebSphere 事务架构师 Ian Robinson 的一个最有见地的 评论 之一是:
这一切会影响 WebSphere 吗?嗯,Spring 核心框架本身没有任何变化。无论 SpringSource Application Platform 的未来如何,Spring 核心框架项目仍然可以与 WebSphere 互补。就像炸鱼薯条一样。Ian 说得完全正确。SpringSource Application Platform 是 Spring 部署的另一个选择。没有什么改变...
SpringSource Application Platform 由 OSGi 捆绑包构建而成,并支持同样由 OSGi 捆绑包构建的应用程序。平台支持 OSGi 的标准功能,但也支持一些额外的清单头部。许多人曾问:“为什么 SpringSource 要添加专有头部?”以及“新头部有什么含义?”,因此本文解释了背景动机以及 Import-Library 和 Import-Bundle 的含义。
因此,熟悉 OSGi 的开发者可以将平台用作标准的 OSGi 容器,并受益于平台的功能,例如:
好吧,过程中的一些步骤相对容易,特别是如果遵循了良好的软件工程实践并且代码已被组织成服务、域和基础设施组件。这些组件可以转换为捆绑包,它们之间的依赖关系可以使用 META-INF/MANIFEST.MF 中的标准 OSGi Import-Package 和 Export-Package 头部来表达。
一个更困难的步骤是表达对 Spring 和 Hibernate 等企业框架的依赖。使用标准的 OSGi Import-Package 和 Require-Bundle 头部来表达这些依赖关系是完全可能的,如果您想创建将在其他 OSGi 容器中运行的 OSGi 捆绑包,那么您应该这样做,但这种方法有一些隐藏的成本。
首先,开发人员必须精确地确定构成给定框架的包。仅仅导入应用程序代码使用的包是不够的,因为许多企业框架在应用程序加载时会在应用程序的字节码中注入进一步的依赖关系。开发人员必须通过试错来发现需要导入哪些额外的实现包,以确保编织后的应用程序能够正确运行。
然后是迁移到框架的新版本的工作,其中构成框架的包的精确集已发生更改。编织所需的附加包通常不是由公共契约定义的,因此可能会发生更改。
此外,生成的包导入未能正确捕获设计意图,这使得将来维护或扩展应用程序更加困难。
我们真的不想给用户带来这些负担,因此我们创建了一些额外的 SpringSource Application Platform 特定清单头部,Import-Library 和 Import-Bundle,作为表达对企业框架依赖关系的便捷方式。正如您将在下面看到的,这些头部只是“语法糖”,它们本身就是标准的 OSGi 包导入。
Import-Library: <librarySymbolicName>;version=<versionRange>其中 <librarySymbolicName> 是库的“符号名称”,<versionRange> 是使用 OSGi 版本范围表示法可接受的库版本范围。库定义指定了库的符号名称和版本,这两个共同唯一地标识了平台上的库。
如果您不熟悉 OSGi 版本范围表示法,最常用的形式是最小版本范围,例如 2
,表示“版本 2 或更高版本”,以及“半开”范围,例如 [2.2.1,2.2.2)
,表示 2.2.1(含)和 2.2.2(不含)之间的任何版本。如果省略 version=<versionRange>,并省略分号分隔符,则默认范围包含所有版本。
对于每个库导入,平台会选择具有给定符号名称和给定版本范围内的最高版本库。然后,平台会将库导入替换为一组包导入,这些包导入匹配该库捆绑包导出的所有包。平台会检测到捆绑包导入两个或多个导出公共包的库的情况,会发出适当的日志消息,并阻止导入捆绑包的安装。
因此,例如,以下头部导入了介于 2.5.4(含)和 2.5.5(不含)之间的某个版本的 Spring Framework 库。
Import-Library: org.springframework.spring;version="[2.5.4,2.5.5)"
:=表示一个“指令”,它会修改清单头部的语义,而分隔符
=表示一个“匹配属性”,如 version。
Import-Library: <librarySymbolicName>;version=<versionRange>;resolution:=optional
如果未指定 resolution,或者指定为 mandatory,则包含导入库头部的捆绑包将无法安装,如果不存在具有给定符号名称且版本在给定范围内的库。但是,如果指定了 resolution:=optional,则在没有合适的库可用时,将忽略该库导入。
因此,例如,以下头部从 2.5 版本开始导入某个版本的 Spring Framework 库,但如果不存在合适的库,则会被忽略。
Import-Library: org.springframework.spring;version="2.5";resolution:=optional
Import-Library: org.foo.p;version="[1,2)",org.bar.q;version="[2,3)"
正如您所期望的,对于每个导入的捆绑包,平台会选择具有给定符号名称和给定版本范围内的最高版本捆绑包。然后,平台会将捆绑包导入替换为一组包导入,这些包导入匹配该捆绑包导出的包。
因此,例如,以下头部导入了 Hibernate 对象关系映射 捆绑包。
Import-Bundle: com.springsource.org.hibernate;version="[3.2.6,3.2.7)"
嗯,我们希望 Require-Bundle 保留其标准语义,包括将拆分的包组合在一起的能力。但我们希望 Import-Library 和 Import-Bundle 具有与 Import-Package 相同的底层语义,从而避免拆分包的复杂性。
我们还预计,随着平台随时间的推移而发展,我们将需要向 Import-Library 和 Import-Bundle 添加进一步的指令,这些指令不适合添加到 Require-Bundle。
对于希望利用平台头部但需要生成可在其他 OSGi 容器上运行的捆绑包的用户,我们计划开发一个工具来替换 Import-Library 和 Import-Bundle...
自上周三发布 SpringSource 应用平台以来,众多开发人员下载了 1.0.0 测试版并开始试用该平台。结果,人们开始询问:“如何在平台上部署我的应用程序?我有哪些部署和打包选项?”此外,开发人员迫切希望看到可用的示例。作为回应,S2AP 团队将在未来几周发布几个示例应用程序,演示这些功能以及更多内容,但在您拿到这些示例之前,我想先给您一个高层次的…
亲爱的 Spring 社区:
我很高兴地宣布 Spring Web Services 1.5.1 已经发布!
这是 Spring-WS 1.5 系列的第一个错误修复和增强版本。它修复了自 1.5.0 以来报告的所有错误,并引入了框架中的各种增强功能
等等。请参阅更新日志了解详情。
请注意,由于向后兼容性问题,CastorMarshaller 现在需要 Castor 1.2 或更高版本。
干杯,
Arjen Poutsma
Spring Web Services 负责人
很多人一直在问 SpringSource Application Platform 究竟能为 Spring 应用程序做什么,使其在 OSGi 上运行良好,这超出了 OSGi 和 Spring Dynamic Modules 开箱即用的功能。Adrian 昨天的帖子重点介绍了一些一般性问题,现在我们来看一些细节。
在 OSGi 上运行 Spring 应用程序面临的三个最具挑战性的方面是
其余但不太有趣的方面包括:JSP 支持、TLD 扫描、注解匹配和资源查找。总而言之,有一些相当多的问题需要解决才能使应用程序平稳部署。
加载时编织是支持的一项最棘手的功能。在基本层面上,它需要挂钩到 Equinox 的 ClassLoader,以便在 defineClass 调用期间可以附加和使用标准的 ClassFileTransformers。在此基础上,许多 LTW 的用法需要访问一个一次性的 ClassLoader,该 ClassLoader 可用于检查类型以决定在编织期间需要做什么,而不会影响实际的 ClassLoader。
这个基本级别的支持实际上是相当容易实现的。困难之处在于,当编织由一个 bundle 中的类驱动,但另一个 bundle 中的类需要被编织时。这在企业应用程序中很常见,其中一个 bundle 包含领域实体,另一个 bundle 包含使用 JPA EntityManager 的类型。Platform 通过确保应用程序中的所有 bundle 都可以使用适当的 ClassFileTransformers 进行编织来处理这种复杂性。
当您开始将编织传播到其他 bundle 时,您确实需要知道何时停止。如果您只是将编织应用于所有 bundle,那么应用程序将会相互干扰。Platform 通过显式地限定编织范围,使其仅应用于应用程序中的模块,从而防止这种情况发生。
LTW 的另一个问题是它会使刷新复杂化。当一个 bundle 被刷新时,OSGi 将刷新所有依赖于它的 bundle。这意味着,在我上面给出的例子中,刷新领域 bundle 会导致 EntityManager bundle 被刷新。然而,刷新 EntityManager **不会**刷新领域 bundle,这意味着编织可能不同步。Platform 通过将刷新传播到受编织影响的其他 bundle 来处理此问题。
对于类路径扫描,主要问题是 Equinox 不暴露标准的 jar: 和 file: 资源。Platform 在中间放置了一个适配器,以便库可以看到它们期望的资源协议。这有一个很好的副作用,就是使**大量**第三方库能够工作——这不仅仅是类路径扫描的修复。
许多第三方库使用线程上下文 ClassLoader 来访问应用程序类型和资源。OSGi 中的每个 bundle 都有自己的 ClassLoader,因此,在任何时候只能公开一个 bundle 作为线程上下文 ClassLoader。这意味着,如果第三方库需要查看分布在多个 bundle 中的类型,它将无法按预期工作。
Platform 通过创建一个 ClassLoader 来解决这个问题,该 ClassLoader 导入您应用程序中每个模块的所有导出的包。然后,此 ClassLoader 作为线程上下文 ClassLoader 公开,使第三方库能够看到您应用程序中的所有导出类型。
这只是 Platform 所解决问题的一小部分,但希望它能让您对 Platform 对 Spring Framework 用户意味着什么有所了解。