http://www.oracle.com/technetwork/cn/topics/entarch/spring-2-weblogic-server-9-integrat-091510-zhs.html

Spring 2.0.1 与 BEA WebLogic Server 9.2 的集成

作者:Andy Piper、Eric Hsiao、Rod Johnson 和 Chris Wall
04/23/2007

编辑注:Spring 2.0.2 工具包于本文完成后已经发布了,现在可供下载。

摘要

一年多以前,我们讲述过 Spring 1.2.x 与 WebLogic Server 9.2 的集成。其后,我们又验证了 Spring 和 BEA WebLogic Server 的更新的版本,一直到 WebLogic Server 9.2 和 Spring 2.0 的组合。表现出在功能性、可用性和性能上的重大飞跃,因此我们决定对文章进行更新以反映这一变化。

BEA WebLogic Server 9.2 是 Sun Microsystems 的 Java EE 1.4 平台的领先实现。然而,WebLogic Server 的核心价值主张则体现在 Java EE 规范没有覆盖的领域 — 增强的管理、易用性、高可用性、可伸缩性、可靠性和性能。实际上,WebLogic Server 的价值不依赖于任何特定的编程模型,所以它也自然适用于新出现的非 Java EE 的 Java 编程模型。近年来出现的最令人激动的事物莫过于基于控制反转 (IoC) 的模型,Spring Framework 就是它 事实上的 实现。本文介绍了 Spring 2.0 Framework、WebLogic Server 以及这两者的集成的新特性。我们会看到,整体大于部分之和。

文章结构

文章的前两节概述 Spring 和 WebLogic Server 以及它们各自的特性。如果您熟悉 Spring Framework,那么可以跳过第一节。如果您熟悉 WebLogic Server,那么可以跳过第二节。本文主要目的是介绍这两种技术的集成,所以本文后续的部分都是讲述这一主题的。首先,我们分析 MedRec — WebLogic Server 上的一个示例程序 — 分别以它的原始的 Java EE 形式和使用 Spring Framework 重构后的形式。之后,是关于特定的集成点的一些细节。在 WebLogic Server 上开发 Spring 应用程序,那么,几乎可以肯定,这些细节会对您有所帮助。如果您只是想有个大致的概念,可以先阅读标题,内容留待以后再看。最后,我们展望了一些正在考虑中的未来开发工作。

Spring 简介

在本节中,我们将简要地概述 Spring Framework 的特性,包括 2.0 版以来的一些新特性。

Spring 是基于 Rod Johnson 在 Expert One-on-One J2EE Design and Development(Wrox,2002)公布的代码的一个分层的Java/Java EE 应用程序框架。Spring 的存在是因为我们相信 Java EE 应该更容易使用,并且有可能创造更简单的 Java EE 开发方法而不会牺牲平台性能。

Spring 支持灵活的 Java EE 开发,允许使用传统 Java 对象(一般称为 POJO)开发 Java EE 应用程序。

改进的 Spring 开发体验

Spring 在其核心部分提供了一个易于配置、XML 驱动的控制反转 (IoC) 容器。IoC 基于所谓的“好莱坞”原则:“不要打电话过来,请等通知。” 在该模式中,通过容器而不是直接编程将 Java 对象间的关系 注入 应用程序中。有两种注入方式 — 构造函数注入和 setter 注入,具体取决于容器是通过其构造函数还是 mutator 方法将信息注入已创建的 Java 对象。

在 Spring 中,注入的属性 — 或到其他 bean 的引用 — 是通过一个 XML 文件进行配置的,这使得配置轻而易举。它耦合了另外一个 AOP 框架,允许非侵入性增加诸如事务处理和安全等属性,这意味着开发人员可以专注于创建业务解决方案,而不必忙于复杂的 Java EE 开发或配置。由于容器是非侵入性的,所以您不必担心业务代码会被特定于供应商(此处也包括 Spring)的构件所污染。

Spring 应用程序组件

如上所述,Spring 提供了一个轻型容器,用于提供集中式、自动化的配置并连接应用程序对象。该容器是 非侵入性的,能够以一致、透明的方式通过 IoC 将一组松耦合的组件 (POJO) 组装成复杂的系统。 因为该容器允许首先独立地开发和测试各软件组件,然后在任意环境(Java SE 或 Java EE)中进行扩展部署,所以它具有灵活性和高利用率,并提高了应用程序的可测试性和可伸缩性 此外,Spring 提供了许多其他对开发人员友好的特性,下面我们一一列举:

  • 用于事务管理的通用抽象层:支持可插入的事务管理器,使事务划分更轻松,同时无需处理底层的问题。该层中还包括 JTA 策略和一个 JDBC DataSource。相比普通的 JTA 或 EJB CMT,Spring 的事务支持不依赖于 Java EE 环境。考虑到是一个十分灵活的非侵入性解决方案,事务语义通过 AOP 应用于 POJO,通过 XML 或 Java SE 5 注释进行配置。

  • JDBC 抽象层:提供了一个有意义的异常层次结构(不再从 SQLException 抽取供应商代码),简化了错误处理,极大地减少了代码编写量。无需为了再次使用 JDBC 编写另外的 finally 代码块。面向 JDBC 的异常遵循 Spring 的一般 DAO 异常层次结构。

  • 与业界领先的对象关系映射解决方案的集成:在资源拥有者、DAO 实现支持和事务策略方面。 对大量 IoC 便利特性的一流支持,解决了许多典型的 O-R 映射集成问题。所有这些都遵循 Spring 的一般事务和 DAO 异常层次结构。而且,Spring 2.0 提供了与 Java 持久性 API (JPA) 的完全集成。

  • AOP 功能:完全集成到 Spring 配置管理中。您可以对 Spring 所管理的任何对象启用 AOP,增加了声明性事务管理等方面。 借助于 Spring,您能够拥有没有 EJB 的声明性事务管理 — 甚至也可以没有 JTA。

  • 灵活的 MVC Web 应用程序框架:构建在核心的 Sping 功能之上。该框架是通过策略接口高度可配置的,并且适用于多种视图技术,如 JSP、Velocity、Tiles、iText 和 POI。注意,Spring 中间层可以轻松地与基于任何其他 Web MVC 框架(如 Struts、WebWork 或 Tapestry)的 Web 层组合。

  • 用户可扩展的配置层:允许用户在 vanilla Spring 配置中加入自己定制的 XML 标记。整个 Spring 2.0 核心库已经广泛地使用此功能,以提供增强的语法和通用 Spring 特性的可用性。

  • 异步编程抽象:包括与 JMS 提供者的进行框架无关的事务集成的消息驱动的 POJO (MDP);与异步调度机制的集成,如 commonj、Java SE 并行程序和 Quartz;本地事件支持。

所有的 Spring 功能都可以在任何 Java EE 服务器上使用,大部分功能可以在非托管环境中使用。Spring 的一个重心是支持可重用业务和不依赖于特定的 Java EE 服务的数据访问对象。这些对象可以不费事地跨 Java EE 环境(Web 或 EJB)、独立应用程序和测试环境进行重用。

Spring 的分层体系结构提供了大量灵活性。 其所有功能都构建在较低的层次上。例如,您可以在不使用 MVC 框架或没有 AOP 支持的情况下使用 JavaBeans 配置管理。但是,如果您要使用 Web MVC 框架或 AOP 支持,您会发现它们构建在配置框架之上,所以您可以马上应用有关它的知识。

BEA WebLogic Server 9.2 简介

在本节,我们将简要概述 BEA WebLogic Server 的特性,重点强调其提供的底层基础架构,而不是编程模型。

WebLogic Server 是可伸缩的企业级 Java EE 应用服务器。WebLogic Server 基础架构支持各类分布式应用程序的部署,是构建各种应用程序的理想基础。

Sun Microsystem 公司的 Java EE 1.4 规范在 WebLogic Server 上的实现提供了一组标准的 API,用以创建能够访问多种服务(如数据库、消息传递服务和外部企业系统连接)的分布式 Java 应用程序。终端用户客户程序使用 Web 浏览器客户端或 Java 客户端访问这些应用程序。由于 Java EE 是如此有名,这里我们就不进一步讨论了。参见关于编程模型的 WebLogic Server 文档,可以获得更多信息。

除了实现 Java EE 之外,WebLogic Server 还使企业能够在一个健壮的、安全的、高可用的、可伸缩的环境中部署任务关键型应用程序。这些特性允许企业配置 WebLogic Server 实例集群以分布负载,并在发生硬件或其他故障时提供额外的容量。新的诊断工具允许系统管理员监视和调优已部署的应用程序和 WebLogic Server 环境本身的性能。您还可以对 WebLogic Server 进行配置以自动监视和调整应用程序吞吐量,无需人工干预。广泛的安全特性保护了对服务的访问,保证了企业数据安全,并阻止了恶意攻击。

WebLogic Server 增强的服务质量

与许多其他 BEA 产品一样,WebLogic Server 如同冰山,浮在水面上的只是很少的一部分而已。具体来说,WebLogic Server 提供了许多特性和工具来支持高可用、可伸缩的应用程序部署:

  • WebLogic Server 集群通过将工作负载分布到多个 WebLogic Server 实例之间,为您的应用程序提供可伸缩性和可靠性。基于要处理的工作量,传入的请求可以路由到集群中的一个 WebLogic Server 实例。如果出现硬件或其他故障,会话状态对其他可恢复故障节点工作的集群节点可用。此外,可以实现集群,使服务驻留在这样的单台计算机上:如果出现故障,该计算机可以选择将服务迁移到集群中的另一个节点上。

  • 除了在一个集群内跨服务器复制 HTTP 会话状态之外,WebLogic Server 还能够跨多个集群复制 HTTP 会话状态,从而在多个地理区域、电网和 Internet 服务提供商中扩展可用性和容错能力。

  • Work Manager 基于您定义的规则划分工作优先级,并监视实际的运行时性能统计信息。然后利用这些信息优化应用程序的性能。Work Manager 可以全局应用于一个 WebLogic Server 域或者一个特定的应用程序组件。

  • 过载保护使 WebLogic Server 能够检测和避免过载情况,并从中得以恢复正常。

  • 网络通道基于流量类型将网络流量分散到各个通道中,有利于网络资源的有效使用。

  • WebLogic Server 持久存储 是一个性能卓越的内置存储器解决方案,针对需要持久存储的 WebLogic Server 子系统和服务。例如,它可以存储持久的 JMS 消息,或者临时存储使用存储-转发特性发送的消息。持久存储支持到基于文件的存储器或到支持 JDBC 的数据库的持久性。

  • 存储-转发服务使 WebLogic Server 可以在跨 WebLogic Server 实例分布的应用程序之间可靠地传递消息。如果发送消息时由于网络或系统故障造成消息目标不可用,那么一个本地服务器实例将保存消息,并且当远程目标可用时转发。

  • 企业级就绪部署工具使应用程序简化了从开发阶段到生产环境的部署和移植。

  • 生产环境重新部署使企业能够在不中断旧版程序工作进程的情况下部署新版本。

现在,让我们来看看这两个系统之间的协作。

在 Java EE 和 Spring 中开发应用程序

为了比较和对照 Java EE 和 Spring 开发方法的差别,我们使用 Spring 2.0 Framework 重新编写了 MedRec 示例程序,充分利用了 Spring 2.0 的许多创新特性。在下一节,我们将简要介绍 MedRec 的总体体系结构,然后依次了解它的 Java EE 形式和 Spring 形式。

Medical Records 应用程序

Avitek Medical Records(或 MedRec)是一个 WebLogic Server 示例程序套件,简明演示了 Java EE 平台的各个方面。MedRec 旨在作为各层次 Java EE 开发人员的一个培训工具。它显示了每个 Java EE 组件的使用方法,阐明了适于组件交互和客户端开发的设计模式。MedRec 还阐释了使用 WebLogic Server 开发和部署应用程序的最佳实践。

MedRec 背后的真实概念是一个框架,其中患者、医生、管理人员使用各种不同的客户端管理患者数据。对于患者,MedRec 提供基于 Web 的应用程序,供他们查看自己的医疗记录和维护档案文件。MedRec 为管理人员提供基于 Web 的应用程序,用于管理入院登记、医疗记录上载和常规应用程序监视。MedRec 还提供与独立医疗机构接合的资源。为了演示这个通信系统,MedRec 包括一个医生应用程序,用于向 MedRec 系统请求和提供数据。

Java EE 版的 MedRec 体系结构概述

Java EE 和 WebLogic Server 版的 MedRec 的设计和实现采用传统的三层体系结构模型,分为相互独立的客户端、服务器和数据存储三个部分:

  • 表示层:该层负责所有用户交互;有时也称作客户端层。

  • 服务层:该层是封装了应用程序业务逻辑的中间层。服务层处理来自异构客户端的请求,同时与各种后端系统进行交互,包括数据存储。该层有时也称作服务器层。

  • 企业信息系统 (EIS) 层:该层表示那些提供和/或存储原有应用程序和数据库之类数据的系统。EIS 层有时也称作数据存储。

我们为 MedRec 的患者和管理部门程序开发了 Web 应用程序 (webapp) 以公开针对各自用户的服务。webapp 遵循模型-视图-控制器模式,Java Server Pages 将视图呈现给用户,模型封装要呈现给用户和从用户处捕获的数据,而控制器机制则管理除与服务层交互之外的组件交互。MedRec 采用 Jakarta Struts 实现该模式。

服务层为发出请求的客户端提供服务,并管理与后端应用程序和资源的交互。 MedRec 的服务层采用会话外观模式封装业务逻辑和业务数据。会话外观通过提供一个到分布式服务的接口,简化了应用程序的复杂性。在 MedRec 中,会话外观的首要责任是提供数据吞吐量。在 MedRec 的 Java EE 和 WebLogic Server 版本中,会话外观被开发为无状态的会话企业 JavaBeans,而数据则由实体企业 JavaBeans 管理。

为了与外部实体接合,MedRec 通过 Web 服务公开应用程序功能,从而允许在不同系统之间使用一系列开放标准进行动态交互。通过 Web 服务公开服务,MedRec 可以为独立的各方提供数据或接收来自各方的数据,这样就实现了集中式医疗记录管理的主要目标。

图 1 阐释了 Java EE 和 WebLogic 版 MedRec 的高级体系结构图。


图 1:J2EE 版 MedRec 的体系结构图

使用 Spring 重新表示 MedRec

为了使 Spring 能够利用 WebLogic Server 的企业特性,对 MedRec 的体系结构进行了重新设计,用相应的 Spring 组件替换了核心的 Java EE 组件。我们用基于 Spring 的 MedRec 版本 (MedRec-Spring) 复制了与原版 MedRec 相同的功能。

控制反转
MedRec-Spring 最显著的变化是引入了 Spring IoC。IoC 方法功能强大,通过一个容器将相关性注入到配置好的组件中而应用。 IoC 将应用程序代码与其配置相分离。例如,对象与其相关性无关,因此可以专注于其职责。在 MedRec-Spring 案例中,诸如数据源、JMS 服务、MBean 连接和对等服务等企业资源在运行时被提供给 MedRec-Spring 的对象。另外,通过迁移资源配置和在已编译代码外进行引用,应用程序从特定于开发的资源向中间的生产资源和环境的转移更加易于管理。

我们发现,要正确使用 IoC,应用程序代码需要遵循更严格的 Java 编程规则 — 特别是在编写接口的代码时。接口比其他东西更能促进更好的协作,因为可以减轻依赖性,而且实现的变化被隔离开来。 从 IoC 的角度看,接口支持相关性注入的可插入本性。为了利用 IoC,我们对 MedRec-Spring 进行了重构,这样就可以基于接口对业务对象进行编码。

POJO
在 MedRec-Spring 中,传统 Java 对象 (POJO) 代替了无状态会话 EJB。无状态会话 EJB 的强大在于它们的远程控制和事务管理功能。 因为 MedRec-Spring 通过 Spring 的 HTTP Invoker 体系结构公开了服务 bean,所以它能够满足远程控制的要求。 事务管理是由 Spring 的事务抽象层提供的。MedRec-Spring 的事务管理精确地镜像了 MedRec 的事务管理,因为 Spring 事务管理器配置为将责任委托给 WebLogic Server 的 JTA 事务管理器。

消息处理
MedRec-Spring 包含原始 MedRec 的大多数消息处理功能。我们采用 Spring 的 JMS 程序包简化了一些一般性任务,如连接工厂和目标查找。Spring 提供了一个代表消息目标的对象,而不是通过程序获取队列句柄。与所有 Spring bean 一样,这些对象表示(JNDI 名称、连接工厂关联等)是在已编译代码的外部配置的。 我们还在三个领域使用了 Spring 2.0 的消息驱动的 POJO (MDP) 作为 JMS 消息的目标:

  • 处理邮件消息(向患者发送批准邮件或拒绝邮件)
  • 处理注册消息(处理新患者注册)
  • 处理医疗记录上载(从 XML 文件向 RDBMS 上载医疗记录)

AOP
MedRec-Spring 使用 Spring AOP 主要有两个目的:

  • 声明性事务管理
  • DAO 实现后处理 (JPA) 的返回值

JPA
MedRec-Spring 现在使用 JPA 访问和写入患者记录。有关更多详细信息,请参见“结合使用 JAVA 持久性 API 和 SPRING 2.0”。

应用程序管理
MedRec-Spring 包含应用程序管理特性。这些特性与 WebLogic Server 的域配置以及运行时域交互。MedRec-Spring 必须按照 WebLogic Server 的 MBean Server 形式,Spring 提供了连接管理,简化了 MBean Server 的可访问性。

Web 服务
最后,MedRec-Spring 使用 Web 服务导出它的服务。 Spring 提供一个 JAX-RPC 工厂用于生成 Web 服务的代理。与其他 Spring bean 类似,工厂 bean 也是在已编译的代码外部配置的,使得应用程序更加灵活。

图 2 显示基于 Spring 的 MedRec 版本的高级体系结构图。


图 2:基于 Spring 的 MedRec 版本的高级体系结构图

WebLogic Server 上的 Spring 最佳实践

比较了 Java EE 和 Spring 环境上的 MedRec 体系结构之后,现在我们来介绍在实现 MedRec-Spring 应用程序过程中发现的一些宝贵经验:

  • 使用延迟初始化。为了实现 IoC 容器,Spring 加载一个 应用程序上下文 文件,创建并缓存每个已配置的 bean 实例。Spring bean 引用的每个资源都必须可以实例化或查找,了解这一点很重要。例如,Spring 的 JMX 支持提供到 WebLogic Server 的 MBean 服务器的连接。部署期间,并非所有 MBean 服务器都是激活的,因此在部署资源时,用户应该一启动即使用 Spring 延迟初始化和查找服务。

  • 基于功能分离出 Spring 配置。 这允许应用程序组件仅加载那些与自身工作职责相关的上下文。该实践还允许测试人员用一个特定于测试环境的上下文替换一个应用程序上下文(例如,数据源配置),从而改变其行为。

  • 通过 JndiObjectFactoryBean 封装 JDBC 数据源连接池 。则那些要求数据库交互的 bean 可以引用该 bean,以利用 WebLogic Server 的数据源连接池功能。

  • 将 Spring 的 org.springframework.ejb.support 用于会话和消息驱动的企业 JavaBeans 。Spring 的 org.springframework.ejb.support 提供企业 JavaBeans (EJB) 可以扩展的抽象类。这些抽象的 EJB 类通过包含 EJB 生命周期方法的标准实现来辅助开发。更重要的是,这些类提供了加载 Spring 应用程序上下文的机制,包括跨多个 EJB 和客户端共享上下文,因此在 EJB 初始化时减少了重复和开销。

  • 利用热部署和 WebLogic Server 的拆分开发目录环境。 这极大地提升了集成测试期间的 Spring 开发体验。热部署允许应用程序重新加载,而无需重新启动服务器。拆分开发目录环境减少了不必要的文件复制,加快了开发和部署。拆分开发目录 Ant 任务帮助您快速地重新编译和重新部署应用程序,无需先生成一个可部署的存档文件或展开的存档目录。

  • 将 Spring 库打包为应用程序库、可选的扩展或服务器扩展。这允许几个 Spring 应用程序共享 Spring Framework,减少了应用程序所占空间。不仅减少了内存占用,而且还提高了部署次数。

Spring on WebLogic Server 工具包

为帮助您从部署在 WebLogic Server 上的 Spring 应用程序得到最大收获,我们已经发布了一个经过认证的 BEA 发行版,包括 Spring 2.0、MedRec on Spring 应用程序和其他一些不错的工具。可以从 BEA 的发行版 Web 站点上免费下载此工具包。

Spring 2.0.1 与 BEA WebLogic Server 9.2 的集成
页面: 1, 2, 3, 4

企业 Spring

Spring Framework 的非侵入性 IoC 开发模型不但依赖于 Java EE 应用服务器可用的特性集,而在旨在补充该特性集。事实上,在要求很高的生产环境中,底层应用服务器基础架构提供的服务质量对 Spring 应用程序的持续可靠性、可用性和性能非常重要。WebLogic Server 9.2 提供了企业级特性,能够从各方面增强您的 Spring 应用程序。在本节中,我们将详述这些特性以及如何在 Spring 应用程序中利用它们。

集群管理和部署

一个 WebLogic Server 集群包括多个 WebLogic Server 服务器实例,这些服务器实例同时运行并一起工作,从而提高了可伸缩性和可靠性。对客户端来说,集群就像单个 WebLogic Server 实例一样。构成集群的服务器实例既可运行在同一台计算机上,也可位于不同的计算机上。可以通过在现有的计算机上向集群添加额外的服务器实例,或者向集群添加计算机以托管增加的服务器实例,来提高集群的容量。WebLogic Server 集群为 Spring 应用程序提供了一个企业级部署平台,WebLogic Server 提供的丰富性和易用性是其他支持相似特性的技术所不具备的。有关 WebLogic Server 集群的配置和管理的完整讨论,请参见“Understanding Cluster Configuration”。

通常,Spring 应用程序被打包成 webapp 形式,在这种情况下,您无需为了利用 WebLogic Server 集群而更改自己的应用程序。只需将应用程序部署到集群中的服务器,即可体验增强的可伸缩性和可用性带来的好处。

Spring 会话复制

Spring Web 应用程序通常将信息存储在 HTTP 会话中,如订单 ID 和用户信息。为了支持一个集群内的 servlet 和 JSP 的自动复制和故障切换,WebLogic Server 支持集中用于保持 TTP 会话状态的机制。只需为用户应用程序提供一个适当的 weblogic.xml 部署描述符,它们就能够被 Spring Web 应用程序非侵入性地使用。获取 WebLogic Server 9.0 的提供的有关如何配置各种类型的会话持久性的更多信息。

集群化的 Spring 远程控制

Spring 提供强大的远程控制支持,允许您仍然利用一致的基于 POJO 的编程模型轻松地导出和使用远程服务。通过一个接合到适当 Spring bean 的 RMI 接口,Vanilla Spring 支持代理 POJO 调用。然而,这种支持仅限于 JRMP(Sun 的 RMI 实现),或者通过 JndiRmiProxyFactoryBean 使用特定的远程接口。借助于 Spring 1.2.5 on WebLogic Server 9.0 认证,我们已经扩展了 JndiRmiProxyFactoryBean 和相关的服务导出程序 — 这样它就能支持任何 J2EE RMI 实现的 POJO 代理,包括 RMI-IIOP 和 T3。这方面的支持还包括一个 WebLogic RMI 部署描述符,它支持代理 RMI 接口上的集群化,因此 POJO 调用可以在一个 WebLogic Server 集群内进行负载均衡。客户端上这种支持的配置与此相似 ( applicationContext.xml):

<bean id="proProxy"
class="org.springframework.remoting.rmi.JndiRmiProxyFactoryBean">
<property name="jndiName" value="t3://${serverName}:${rmiPort}/order"/>
</property>
<property name="jndiEnvironment">
<props>
<prop key="java.naming.factory.url.pkgs">
weblogic.jndi.factories
</prop>
</props>
</property>
<property name="serviceInterface"
value="org.springframework.samples.jpetstore.domain.logic.OrderService"/>
</bean>

服务导出程序如下(同样来自 applicationContext.xml):

<bean id="order-pro"   class="org.springframework.remoting.rmi.JndiRmiServiceExporter">
<property name="service" ref="petStore"/>
<property name="serviceInterface"
value="org.springframework.samples.jpetstore.domain.logic.OrderService"/>
<property name="jndiName" value="order"/>
</bean>

集群化的描述符自动包含在其中,仅要求适当的集群配置以及在所有集群成员上部署 Spring 应用程序。获得有关故障切换支持的更多信息。

对 Spring 组件的控制台支持

Spring on WebLogic Server 工具包是一个 WebLogic Server 控制台扩展,它显示了应用程序中定义的 Spring bean、属性和操作。它构建在 WebLogic 控制台扩展门户框架之上,该框架可以转换 WebLogic Administration 控制台的外观、功能和布局,而无需修改服务器或控制台代码。将控制台扩展复制到 yourdomain/console-ext 目录后即进行了部署,随后服务器重新启动。有关部署控制台扩展的更多详细信息,请参考 Spring on WebLogic Server 工具包。

控制台扩展为不是 MBean 的 Spring bean 自动创建 (JMX) 管理接口(对于多数 Spring bean,通常就是这样),通过在 applicationContext.xml 中配置一个 MBeanExporter 并指定经汇编程序公开的 bean 来完成。该特性是 Spring 和 WebLogic Server 无缝地、非侵入性协作的一个极好的例证。 为了使 Spring 应用程序支持 JMX,只需更改应用程序上下文部署描述符。为了使控制台支持 Spring,只需要将两个 jar 部署到现有域即可。

为了在 WebLogic Server 的 Administration 控制台启用 Spring Console 扩展,需要两个 jar 文件;它们作为 Spring WebLogic 程序包的一部分提供。具体来说,这两个所需的 jar 文件称为 spring-ext-server.jarspring-ext-client.jarspring-ext-server.jar 需要复制到 yourdomain/console-ext 目录。相关的 spring-ext-client.jar 文件需要和 Web 应用程序一道部署。(如果是 .WAR 文件,则将 spring-ext-client.jar 放入 Web 应用程序的 WEB-INF/lib 目录。)

有了这两个文件后,剩下的工作就是在 Spring XML 配置文件中定义几个 bean。第一个绝对要定义的 Spring bean 是 com.interface21.wl9.jmx.mediator.Mediator bean。这个 bean(顾名思义)介于用户应用程序、WebLogic Server 的 MBeanServer 和管理控制台三者之间。它的定义如以下示例所示,是个非常简单的 bean:

<!-- WLS console adapter bean -->
<bean id="consoleAdapter" class="com.interface21.wl9.jmx.mediator.Mediator"/>

这个 bean 必须被“插入”(或说相关性注入)第二个 bean 中,即 MBeanExporter,它也是绝对必须进行配置的。 MBeanExporter 类交付的成果就是只需将 Spring 应用程序上下文中已定义的任意数量的不同 bean 导出到 BEA WebLogic MBeanServer(或者任何配置好的 MBeanServer)。注意,MBeanServer 导出的那些 bean 无需为 JMX 进行编码。Spring JMX 基础架构代码负责生成 ModelMBean 来描述通过 JMX 为了进行管理而导出的 bean。下面是一个典型的上下文配置文件的 MBeanExporter bean 定义:

<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="assembler" ref="assembler"/>
<property name="server" ref="server"/>
<property name="beans">
<map>
<!-- these are the beans that are to be exported... -->
<entry key="my_app_name:type=MaintenanceControl"
value-ref="maintenanceInterceptor"/>
<entry key="my_app_name:type=ExceptionMonitor"
value-ref="exceptionHandler"/>
<entry key="my_app_name:type=RequestStatistics"
value-ref="requestStatisticsFilter"/>
</map>
</property>
<property name="registrationBehaviorName"
value="REGISTRATION_REPLACE_EXISTING"/>
<property name="autodetect" value="true"/>
<property name="listeners">
<list>
<!-- notice how we 'plug-in' the Mediator bean
that was defined previously... -->
<ref bean="consoleAdapter"/>
</list>
</property>
</bean>

注意上面的 bean 定义,另一个 bean(“assembler”)被注入到 MBeanExporter 的“assembler”属性中。下面是该 bean 的定义:

<bean id="assembler" class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
<property name="interfaceMappings">
<props>
<prop key="my_app_name:type=MaintenanceControl">fully.qualified.management.interface.name</prop>
<prop key="my_app_name:type=ExceptionMonitor">fully.qualified.management.interface.name</prop>
<prop key="my_app_name:type=RequestStatistics">fully.qualified.management.interface.name</prop>
</props>
</property>
</bean>

描述 Spring JMX 提供的所有内容不在本文的讨论范围内。此处只需说明一点就够了,那就是上面定义的 InterfaceBasedMBeanInfoAssembler bean 是一个可能的策略,用以控制用户 bean 的哪些方法和属性实际地公开出来供管理之用,就像 JMX 操作和属性那样。 InterfaceBasedMBeanInfoAssembler 使用(任意地)接口决定导出哪些方法和属性。有关更多信息,请参阅本文末尾的“参考资料”一节。

MBeanExporter 的 bean 定义上的第二个著名属性是 server 属性。 这是向 MBeanExporter 注入一个 WebLogic Server 的 MBeanServer 实例的地方。MBeanExporter 将所有已配置的 bean 导出到这一特定的服务器。该 bean 的定义如下所示:

<!-- WebLogic 9 MBeanServer -->
<jndi:jndi-lookup id="server" jndi-name="java:comp/env/jmx/runtime"/>

server bean 的这个定义中,实际上 MBeanServer 实例源自 JNDI(使用为 jndiName 属性指定的值在上下文中查找)。对于 MBeanExporter,MBeanServer 源自 JNDI 的事实没有意义;这个将相关性注入需要相关性的对象透明源引是相关性注入方法的一大附加值(上面所见的易于使用和配置的 JndiObjectFactoryBean 证明 Spring 的注入支持是非常高级的)。

最后,最有趣的是 MBeanExporter 配置的一部分是 beans 属性。 beans 属性是 (JMX) ObjectName 到 bean 的简单映射,这些 bean 将导出到先前注入的 MBeanServer 实例以便管理。选择 ObjectName 的策略(在这种策略下,您的 bean 实际上会导出到 MBeanServer)是完全可配置的。在本例中,所用的默认策略是只需使用 beans 映射的键作为 ObjectName。(有关各种 ObjectName 策略的全面纲要,请参见随 Spring 一起提供的 JavaDoc。)

Web 服务支持

Spring 的远程控制功能的另一个方面是它对 RPC 风格的 Web 服务的支持。WebLogic Server 提供了基于 Ant 的工具,可以根据 Web 服务的描述生成 JAX-RPC 存根。Web 服务客户端使用这些生成的存根获取一个表示服务器端操作的远程接口。Spring 通过提供一个 JaxRpcPortProxyFactoryBean 简化了这个过程。

我们发现,在 WebLogic Server 环境中正确地配置 JaxRpcPortProxyFactoryBean 有些棘手,所以为了节约您的时间,我们给出下面这个代码片段,演示如何为一个包含复杂类型的文档字面包装的 Web 服务配置代理生成。

多数属性是自解释的。有几个属性比较有名:

  • serviceInterface 是 Spring setter 注入的副产品。这个类将表示 Web 服务操作。

  • customProperties 属性支持定制的 WebLogic Server Web 服务存根属性。

  • jaxRpcService 值设置为 WebLogic Server 的生成的 JAX-RPC 实现服务。JAX-RPC 服务负责验证 Web 服务和加载复杂类型映射。为了实现后者,WebLogic Server 的 JAX-RPC 实现服务必须配置为一个 Spring bean。这可以确保 JAX-RPC 服务构造函数的运行,而且类型映射文件也在此加载。

JaxRpcPortProxyFactoryBean 上将 lookupServiceOnStartup 设置为 false,即可在启动时关闭 JAX-RPC 服务查找。当首次访问时,将会进行查找。这对于与可靠的 WebLogic Server 请求/响应 Web 服务通信是必需的,而此处的客户端也必须是一个 Web 服务。在这些情况下,始发客户端通常是与 Web 服务客户端一起部署的。 因为应用程序部署完成前不会激活 Web 服务,所以客户端 Web 服务对于 Spring 上下文加载是不可用的。如下代码摘自一个 applicationContext-ws.xml 上下文配置文件:

<!-- reliable asynchronous Web service for sending new medical records to medrec -->
<bean id="reliableClientWebServicesPortType"
class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean"
lazy-init="true">
<property name="wsdlDocumentUrl"
value="http://${WS_HOST}:${WS_PORT}/ws_phys/PhysicianWebServices?WSDL"/>
<property name="portName" value="PhysicianWebServicesPort"/>
<property name="jaxRpcService">
<ref bean="generatedReliableService"/>
</property>
<property name="serviceInterface"
value="com.bea.physician.webservices.client.PhysicianWebServicesPortType"/>
<property name="username" value="medrec_webservice_user"/>
<property name="password" value="weblogic"/>
<property name="customProperties">
<props>
<prop key="weblogic.wsee.complex">true</prop>
</props>
</property>
</bean>
<!-- allows the jaxRpcService class to execute its constructor which loads in type mappings -->
<bean id="generatedReliableService"
class="com.bea.physician.webservices.client.PhysicianWebServices_Impl">
</bean>

有关更多信息,请参见 WebLogic Server 的 Overview Web Services Invocation 和 Remoting and Web Services Using Spring。

安全性

WebLogic Server 安全系统支持并扩展了 Java EE 的安全性,同时提供了一组丰富的安全提供程序,可以对其进行定制以处理不同的安全性数据库或安全性策略。除了使用标准的 Java EE 安全性之外,应用程序编程人员还可以使用很多专有扩展,这些扩展使应用程序可以与安全系统紧密集成。 WebLogic Server 附带了几个安全提供程序,例如,可以选择包含大部分流行 LDAP 服务器的身份验证数据库、Active Directory、本地 Windows 和内置的身份验证解决方案。可以使用定制的提供程序对内置的提供程序进行扩充,从而几乎可以与任意身份验证数据库、授权机制和凭证映射服务相集成。由于部署为 webapp 的 Spring 应用程序使用的是 Java EE 安全性,因此无需修改应用程序即可获得 WebLogic Server 的安全性优点。

经验丰富的 Spring 用户还会熟悉 Acegi — Spring 自身的安全框架。目前,可以在应用程序中使用 Acegi、WebLogic Server 安全性或同时使用二者,因为它们是相互独立的。 稍后我们将讲述与此相关的更多信息。

分布式事务

Spring 提供事务管理的基础架构。除了对各家数据库供应商的支持之外,Spring 还通过一家 Java EE 供应商的 JTA 实现支持分布式事务。通过 WebLogicJtaTransactionManager,可以将 Spring 的 JTA 管理器配置为与 WebLogic Server 的 JTA 实现一起工作。

WebLogicJtaTransactionManager 直接向 WebLogic Server 的 Java Transaction API 委托责任。通过 JNDI,客户端和 bean 提供程序可以使用 WebLogic Server JTA TransactionManager 接口,这一交互由 Spring 管理。事务管理器也支持事务的作用域;事务能够作用于集群和域的内部或二者之间。

WebLogicJtaTransactionManager 最强大的特性是管理分布式事务的能力和用于企业应用程序的两阶段委托协议。使用 WebLogicJtaTransactionManager,应用程序能够利用 WebLogic Administration Console 来进行事务监控。 WebLogicJtaTransactionManager 还支持按数据库隔离级别,允许复杂的事务处理配置。下面的代码节选自 applicationContext-service.xml

<bean id="serviceFacade" class="com.bea.medrec.web.service.ServiceFacadeImpl">
<!-- .... -->
</bean>
<!-- spring's transaction manager delegates to WebLogic Server's transaction manager -->
<bean id="transactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager"> <property name="transactionManagerName" value="javax.transaction.TransactionManager"/>
</bean>
<aop:config>
<aop:advisor advice-ref="txAdvice"
pointcut="execution(* com.bea.medrec.web.service.ServiceFacade.*(..))"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="activate*" propagation="REQUIRED"/>
<tx:method name="deny*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="process*" propagation="REQUIRED"/>
<tx:method name="get*" propagation="REQUIRED" read-only="true"/>
<tx:method name="search*" propagation="REQUIRED" read-only="true"/>
<tx:method name="saveRecord" propagation="REQUIRED"/>
<!-- ... -->
</tx:attributes>
</tx:advice>

有关更多信息,请参见 Overview of Transactions in WebLogic Server Applications 和“在 Spring 中实现事务挂起”。

消息驱动的 POJO

消息驱动的 POJO (MDP) 替代了 Java EE 的消息驱动的 Bean (MDB)。与 POJO 类似,它们的优势也是不要求任何特定于平台的 API 扩展或结构。它们只需要标准的 JMS API 实现:

public class RegistrationMessageListener implements MessageListener {
public void onMessage(Message message) {
// Fetch Registration information from ObjectMessage.
// Process new reg by invoking service (DI)
// ...    }
}

与 Spring 的大多数成员一样,MDP 容器的配置当然也很简单。下面的代码节选自 applicationContext-jms.xml

<!-- JMS ConnectionFactory and Queue -->
<jndi:jndi-lookup id="jmsConnectionFactory" jndi-name="com.bea.medrec.messaging.MedRecQueueConnectionFactory"/>
<jndi:jndi-lookup id="registrationQueue" jndi-name="com.bea.medrec.messaging.RegistrationQueue"/>
<!-- MDP -->
<bean id="registrationMessageListener" class="com.bea.medrec.service.messaging.RegistrationMessageListener">
<!-- ... properties... -->
</bean>
<!-- MDP container -->
<bean id="registrationMessageListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="concurrentConsumers" value="5"/>
<property name="destination" ref="registrationQueue"/>
<property name="messageListener" ref="registrationMessageListener"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>

有关在 WebLogic Server 上如何实现 MDP 的更详细的讨论,请参见这里。

JPA 和 AOP 配置

我们已经定义了一个 Web 服务层,它允许我们在 RMI、Spring HTTP 调用程序、Hessian/Burlap 和 JAXPRC 之间轻松切换 Web 服务实现。调用远程服务时,如果想要使用一种可序列化的机制传递对象,那么这些对象本身必须可序列化。遗憾的是,OpenJPA 的 Find 结果是一个私有的列表实现,不支持 Serializable,所以我们需要将这些列表与一些更合适的列表绑定,如 Java SE 集合库的 ArrayListLinkedList。我们可以使用 spring aop 来帮助我们实现,而不必修改应用程序源代码:

@Aspect
public class ReturningValuePostProcessorAspect {
@Pointcut("execution(java.util.List com.bea.medrec.dao.PatientDao.*(..))")
public void postProcessPatientDao() {
}
@Pointcut("execution(java.util.List com.bea.medrec.dao.RecordDao.*(..))")
public void postProcessRecordDao() {
}
@Pointcut("execution(java.util.List com.bea.medrec.dao.UserDao.*(..))")
public void postProcessUserDao() {
}
}

以下是相关联的 ReturningValuePostProcessor 类。

@Aspect
public class ReturningValuePostProcessor {
public ReturningValuePostProcessor() {
}
@Around("com.bea.medrec.dao.jpa.ReturningValuePostProcessorAspect.postProcessPatientDao()")
public Object postProcessPatientDao(ProceedingJoinPoint pjp) throws Throwable {
return doPostProcess(pjp);
}
@Around("com.bea.medrec.dao.jpa.ReturningValuePostProcessorAspect.postProcessRecordDao()")
public Object postProcessRecordDao(ProceedingJoinPoint pjp) throws Throwable {
return doPostProcess(pjp);
}
@Around("com.bea.medrec.dao.jpa.ReturningValuePostProcessorAspect.postProcessUserDao()")
public Object postProcessUserDao(ProceedingJoinPoint pjp) throws Throwable {
return doPostProcess(pjp);
}
private Object doPostProcess(ProceedingJoinPoint pjp) throws Throwable {
Object retVal = pjp.proceed();
if (retVal == null) {
return null;
}
if (!(retVal instanceof List)) {
return retVal;
} else {
//noinspection unchecked
return new ArrayList((List) retVal);
}
}
}

下面的代码节选自 applicationContext-jpa.xml

<bean id="patientDao" class="com.bea.medrec.dao.jpa.PatientDaoImpl"/>
<bean id="recordDao" class="com.bea.medrec.dao.jpa.RecordDaoImpl"/>
<!-- ... -->
<bean id="returningValuePostProcessor" class="com.bea.medrec.dao.jpa.ReturningValuePostProcessor"/>
<aop:aspectj-autoproxy/>

Java 管理扩展

Java 管理扩展 (JMX) 是用于监视和管理 Java 应用程序的规范。它允许一般的管理系统监视应用程序,当应用程序需要注意时发出通知,并修改应用程序状态以补救问题。Spring 提供广泛的 JMX 支持,包括通过 Spring 的 MBeanServerConnectionFactoryBean 公开 WebLogic Server 的 MBeanServer 的能力。 MBeanServerConnectionFactoryBean 是一个方便的工厂,附带一个 MBeanServerConnection。 在应用程序部署期间,建立连接并进行缓存,供以后引用 bean 进行操作。

可以将 MBeanServerConnectionFactoryBean 配置为返回 WebLogic Server 的 Runtime MBean Server,公开特定的 WebLogic Server 实例的监视、运行时控制和活动配置。这包括访问 WebLogic Server Diagnostics Framework。 此外,Runtime MBean 为当前服务器提供 runtime MBean 和活动配置 MBean 的访问。

还可以配置 MBeanServerConnectionFactoryBean 以获得到 WebLogic Server 的Domain Runtime MBean Server 的连接。Domain Runtime MBean Server 提供域范围内服务的访问,如应用程序部署、JMS 服务器和 JDBC 数据源。它还是访问域中所有服务器的所有 runtime MBean 和活动配置 MBean 的层次结构的单点。这个 MBean Server 也是访问被管理服务器上的 MBean 的单点。

此外,可以配置 MBeanServerConnectionFactoryBean 以获取与 WebLogic Server 的 Edit MBean Server 的连接。Edit MBean Server 提供管理当前 WebLogic Server 域配置的入口点。

注意,在部署期间,WebLogic Server 的 Domain Runtime MBean Server 不是活动的。所以,bean 需要使用 Spring 的延迟初始化进行配置,它会在调用 bean 时获取该 bean。

下面是使用 WebLogic 的 MBean Server 配置 Spring 的 MBeanServerConnectionFactoryBean 连接的一个例子:

<!-- expose WebLogic Server's runtime mbeanserver connection -->
<bean id="runtimeMbeanServerConnection"
class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean">
<property name="serviceUrl"      value="service:jmx:t3://${WS_HOST}:${WS_PORT}/jndi/weblogic.management.mbeanservers.runtime"/>
<property name="environment">
<props>
<prop key="java.naming.security.principal">
${WS_USERNAME}</prop>
<prop key="java.naming.security.credentials">
${WS_PASSWORD}</prop>
<prop key="jmx.remote.protocol.provider.pkgs">
weblogic.management.remote</prop>
</props>
</property>
</bean>

有关更多信息,请参见 Understanding WebLogic Server MBeans 和 Spring 的 JMX Support。

支持

从 WebLogic Server 9.0 和 Spring 1.2.5 开始,BEA 就为 Spring Framework on WebLogic Server 提供了支持和认证。这种支持不仅是测试 WebLogic Server 上的 Spring 库的健全性,还致力于 BEA 和 Interface 21(Spring Framework 的创建者和维护者)之间的积极努力和协作。我们不但测试了上面所讲的 Spring 2.0 的所有特性和配置,一些新特性还直接作为 BEA 和 Interface 21 的协作成果引入 Spring 2.0。

下载

Spring Open Source Framework Support 2.0 下载包括 Spring 2.0(已在 WebLogic Server 9.2 上经过认证)和 Spring-JMX 控制台扩展以及利用 Spring 2.0 Framework 重新编写的 WebLogic Medical Records 示例程序。

未来的工作

今后,我们计划提供 WebLogic Server 和 Spring Framework 之间更深层次的集成。尽管我们有了一些想法,但其中最令人感兴趣的是:

  • Spring 部署单元: Spring 应用程序通常被部署为 webapp,但今后为 Spring 应用程序提供专用部署单元是可能的。

  • Spring 安全性和 WebLogic Server 安全性集成: Spring 安全性是 Spring 的安全框架,我们计划将它与 WebLogic Server 的企业级安全框架集成。

总结

我们用了一些时间讨论了 Spring、WebLogic Server 以及这两种技术的集成。如我们所展示的那样,WebLogic Server 提高了应用程序的服务质量,Spring 则提高了开发人员的生产力。这两种技术都是高度非侵入性的,允许您专注于应用程序的业务功能的开发,而不是纠缠于特定于技术的 API 的错综复杂性。

Spring 2.0.1 与 BEA WebLogic Server 9.2 的集成相关推荐

  1. BEA WebLogic Server 10 查看和配置日志

    查看和配置日志 WebLogic Server 内的每个子系统都可生成日志消息来传达其状态.例如,当启动 WebLogic Server 实例时,安全子系统会输出消息以报告其初始化状态.为了记录其子系 ...

  2. BEA WebLogic 和 INTERWOVEN TEAMSITE的集成

    Interwoven TeamSite是基于web的最佳培训内容管理系统.BEA WebLogic是一个经过认证的具有执行内容传输任务的应用服务器(这是BEA WebLogic多种特征之一).两个执行 ...

  3. BEA WebLogic平台下J2EE调优攻略--转载

    BEA WebLogic平台下J2EE调优攻略   2008-06-25 作者:周海根 出处:网络   前 言 随着近来J2EE软件广泛地应用于各行各业,系统调优也越来越引起软件开发者和应用服务器提供 ...

  4. BEA WebLogic Platform 8.1 Single Sign-On Enablement:概述

    BEA WebLogic Platform 8.1 Single Sign-On Enablement:概述 时间:2004-03-10 作者: 浏览次数: 4162 本文关键字:SSO,  单点登录 ...

  5. 有关Spring 3.0的发布

    今天SpringSource大张旗鼓的宣布Spring 3.0的降临,一时间占据了各大外媒的醒目位置(不过说实话,时机还是不太好,和Visual Studio 2010 Beta 2撞一天了,在头条位 ...

  6. WebLogic Server的Identity Assertion--转载

    在一些典型的公司Web应用程序安全部署中,访问受保护应用程序的用户通过企业身份/访问管理产品,如Netegrity 的 SiteMinder,IBM 的WebSEAL 和Oblix 的 Oblix C ...

  7. 前沿资讯|Spring Native 0.11.2、Spring Authorization Server 0.2.2 发布

    近日,Spring官方又更新了两个前沿内容,分别是Spring Native 0.11.2 和Spring Authorization Server 0.2.2 .下面一起来看看分别都更新了些什么. ...

  8. 【零基础小白的华丽蜕变】Oracle WebLogic Server 14c(14.1.1.0)下载及安装

    [catalog]   1. WebLogic 下载及安装   2. 访问 WebLogic 控制台   [每日一面]web服务器和应用服务器的区别 1.WebLogic 下载及安装 WebLogic ...

  9. 预警| WebLogic Server再曝高危0 day漏洞

    6月11日,阿里云安全团队发现WebLogic CVE-2019-2725补丁绕过的0day漏洞,并第一时间上报Oracle官方, 6月12日获得Oracle官方确认.由于Oracle尚未发布官方补丁 ...

最新文章

  1. Linux性能调优用这个“必杀技”,稳了!
  2. R语言可视化散点图(scatter plot)图中的标签和数据点互相堆叠丑死了,ggrepel包来帮忙:文本标签(label)相互排斥,远离数据点,远离绘图区域的边缘。
  3. vs2010启动调试、停止调试非常慢
  4. float元素一定要闭合
  5. lk中内联调用的dsb()
  6. java怎么让表格的字段相乘,excel表格怎么让数据相乘-如何在excel表格中设置乘法公式...
  7. qt高亮快捷键_QtCreator中常用快捷键总结
  8. easyUI 展开DataGrid里面的行显示详细信息
  9. 二分法求数组最大最小_JavaScript之如何求数组的最大值和最小值
  10. Stanford CS230深度学习(五)CNN和ResNet
  11. 自定义按键_NS推送10.0.0版本更新 新增按键自定义和数据转移功能
  12. 23 岁创业,28 岁成为福布斯亚洲青年领袖,这个“刷脸的男人”有点牛
  13. quartus仿真30:D触发器构成的可重复序列111探测器
  14. asr1009查看接口光衰_python脚本检查H3C交换机光衰
  15. Unix/Linux环境C编程入门教程(24) MySQL 5.7.4 for Red Hat Enterprise 7(RHEL7)的安装
  16. java多线程写数据到数据库6_java多线程向数据库写入数据
  17. 百度地图API地理位置和坐标转换 城市坐标
  18. mysql2005安装asp_Sql server 2005安装时ASP.Net版本注册要求警告的解决方法
  19. 计算机软件免税,软件产品的增值税优惠有哪些?
  20. 如何像“二次元萌妹”小冰一样写诗创作和即兴编曲?

热门文章

  1. SwiftUI之深入解析如何创建列表展示视图和列表如何导航跳转新页面
  2. iOS逆向之Protocol Witness Table的汇编实现原理
  3. iOS之身份证号码全校验与校验位自动补全
  4. python入门常用代码
  5. 394. Decode String
  6. Python中利用Matplotlib绘制多图并合并展示
  7. 大数据WE阶段(十七)文件上传
  8. 【机器视觉】 fuzzy_measure_pos算子
  9. 【C++】Visual Studio教程(三) - 项目和解决方案
  10. 【Linux】一步一步学Linux——fc命令(224)