AOM 2.0的特性系列之六:与 Spring/EJB3的无缝集成
2008-03-03 由 Kevin 发表   评论(4条)   有9204人浏览

1. 前言

本教程介绍 AOM 2.0是怎样与 Spring、EJB3无缝集成的,在阅读本文之前,我建议你首先阅读前几篇文章:

AOM 2.0的特性系列之一:约定优于配置

AOM 2.0的特性系列之二:国际化

AOM 2.0的特性系列之三:输入校验

AOM 2.0的特性系列之四:模型事件

AOM 2.0的特性系列之五:LiteBean

2. 我们需要 Spring 和 EJB3

一个 Web应用并不仅仅只是UI展现层那么简单,我们还要考虑数据持久化、事物完整性保障等等。我们即希望 AOM 能够提供完整解决方案,又不需要它重新发明轮子,因为后台的业务编程模型已经有了优秀的并且经过业界验证的解决方案,如 Spring、EJB 3等。其中,又以 Spring 在业界的使用更为广泛,因此,本文主要介绍 AOM 是怎样和 Spring 紧密集成的,并顺带着介绍一下 EJB 3的支持。

3. Spring is here

我们说:AOM与Spring是无缝集成的。各位同学一看到“无缝集成”这几个字,想必嘴角一撇,心想:典型的广告用语。那么,AOM在与 Spring 集成这方面上,到底做了哪些工作?简单介绍,三个特性而已:

  • 所有在 Spring 中定义的 Bean,都能够被当成 AOM 中的 LiteBean 直接使用。

    你可以理解成:假设你在 Spring 中定义了一个 MySpringBean,那么,在AOM中,你可以 #{MySpringBean} 直接引用此Bean。

  • 所有在 AOM 中定义的 LiteBean,都能够被当成 Spring 中的 Bean 直接使用。

    你可以理解成:假设你在 AOM 中定义了一个 MyLiteBean,那么,在 Spring 中,你可以通过 ApplicationContext.getBean("MyLiteBean")获得它

  • 在 Spring 中定义的 Bean,同样能够获得 IoVC 的支持。

    你可以理解成:假设你在某个 Spring Bean的某个属性上加以 @Bind 的声明,那么该属性依然可以被绑定到页面控件

至于有了上述三个特性,算不算得“无缝集成”,则是仁者见仁,智者见智了。

4. 对Spring集成的示例性说明

做个简单的例子,来验证第一点:所有在 Spring 中定义的 Bean,都能够被当成 AOM 中的 LiteBean 直接使用。

首先将 Spring 等相关 jar 包部署到 WEB-INF/lib 目录中,然后在web.xml中增加以下内容(这都是 Spring 的相关知识):

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>

再在 WEB-INF 中放一个 applicationContext.xml 文件,其内容及详细注释如下:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation=
          "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
           http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">

  <!-- Attention:this bean is essential!
       Making LiteBeans available in Spring container. -->
  <bean class="org.operamasks.faces.spring.ManagedBeanConfigurer"/>

  <!-- Attention: this bean is recommended!  
       Config the apusic application server transaction manager as the Spring transaction manager -->
  <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManagerName">
      <value>java:/TransactionManager</value>
    </property>
  </bean>

  <!-- This is a sample bean -->
  <bean id="MySpringBean" class="demo.MySpringBean" scope="session">
    <property name="name" value="Kevin"/>
  </bean>
</beans>

请注意:上面的 org.operamasks.faces.spring.ManagedBeanConfigurer是 AOM 默认提供的一个 Spring Bean 定义,必须在Spring中配置此Bean,它的作用是:让 AOM 中的 LiteBean 同样能够被 Spring 所感应到。同时,如果你使用 Apusic 应用服务器,我们还建议你正确配置 Apusic 应用服务器的 TransactionManager。

将我们的注意力回到 MySpringBean 的定义上,以下是示例性代码:

public class MySpringBean {

  private String name;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String sayHello() {
    System.out.println("hello " + name);
    return null;
  }

  @Override
  public String toString() {
    return "MySpringBean";
  }

}

我们再准备一个 mySpring.xhtml的faces page:

<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
  xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
  renderKitId="AJAX">
  <w:page title="spring">
    <w:form>
      <layout:panelGrid columns="2">
        <w:textField value="#{MySpringBean.name}" />
        <w:button value="sayHello" action="#{MySpringBean.sayHello}" />
      </layout:panelGrid>
    </w:form>
  </w:page>
</f:view>

此页面的运行效果如下:

我们可以看到,<w:textField>能够正常显示name属性,并且,当我们点击 sayHello 按钮时,程序也可以正常运行。由此可见:在 AOM 中,是可以把一个 Spring Bean 当成 LiteBean 来使用的。

再来验证第二点:所有在 AOM 中定义的 LiteBean,都能够被当成 Spring 中的 Bean 直接使用。

首先声明一个LiteBean:

@ManagedBean(scope=ManagedBeanScope.SESSION)
public class MyLiteBean {

  @Override
  public String toString() {
    return "MyLiteBean";
  }
}

然后再写一个test.xhtml页面测试一下:

<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
	xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
	xmlns:h="http://java.sun.com/jsf/html" xmlns:ajax="http://www.apusic.com/jsf/ajax"
	renderKitId="AJAX">
	<w:head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	</w:head>
	<w:page title="Insert title here">
		<h:outputText id="spring"></h:outputText>
		<br/>
		<h:outputText id="elite"></h:outputText>
	</w:page>
</f:view>

声明testBean:

@ManagedBean(name = "testBean", scope = ManagedBeanScope.SESSION)
public class TestBean implements Serializable {
	
	@Bind(id = "spring", attribute = "value")
	private String spring;

	@Bind(id = "elite", attribute = "value")
	private String elite;

	@BeforeRender
	public void beforeRender(boolean isPostback) {
		WebApplicationContext appContext = WebApplicationContextUtils
				.getWebApplicationContext(((HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(true)).getServletContext());
		MySpringBean mySpringBean = (MySpringBean) appContext.getBean("MySpringBean");
		spring = "The bean defined in Spring: " + mySpringBean;
		MyLiteBean myLiteBean = (MyLiteBean) appContext.getBean("MyLiteBean");
		elite = "The bean defined in AOM: " + myLiteBean;
	}
}

此页面的运行效果如下:

由此可见,在 AOM 中定义的 LiteBean,在 Spring 容器中是同样可见的。

最后再来验证第三点:在 Spring 中定义的 Bean,同样能够获得 IoVC 的支持。

首先,根据“约定优于配置”原则,mySpring.xhtml页面是可以自动找到 MySpringBean 的,那么,我们将 MySpringBean 修订成这样:

public class MySpringBean {

  @Bind
  private String name;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
 
  @Action
  public String sayHello() {
    System.out.println("hello " + name);
    return null;
  }

  @Override
  public String toString() {
    return "MySpringBean";
  }
}

然后再将 mySpring.xhtml 修订成如下示例:

<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
  xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
  renderKitId="AJAX">
  <w:page title="spring">
    <w:form>
      <layout:panelGrid columns="2">
        <w:textField id="name"/>
        <w:button id="sayHello"/>
      </layout:panelGrid>
    </w:form>
  </w:page>
</f:view>

页面执行效果如下:

页面可以正常显示及运行,由此可见:在Spring中定义的Bean,其IoVC能力依然得以保留。

最后,再看一下基于IoVC思想下的 mySpring.xhtml 的源码,忍不住再赞一下:)

5. EJB 3的支持

EJB 3也是一种非常优秀的组件模型,可能是由于 EJB 2.x 版本带给大家的不佳印象,以致于 EJB 3 并没有得到像 Spring 那样的流行程度。 AOM 对 EJB 3同样提供了良好的支持,总结成两句话:

  • 一个 EJB 3 对象也可以同时当作一个 LiteBean 来使用,

  • 你还可以通过 @EJB 标注,将 EJB 对象注入到 LiteBean中使用,并且,这种做法更符合大家的习惯

还是需要特意加以说明的是:将一个 EJB 3对象当成一个 LiteBean 使用,需要更改 EJB 容器的实现代码,因此,这个特性只有 Apusic 应用服务器予以支持。但好像我一说这是 Apusic 应用服务器的私有特性,就总有那么一些同学善意的或者中性的再或者不是那么善意的跳了出来:“你们的动机不纯,你们对 AOM 进行开源是为了多卖几套你们的服务器,强烈鄙视你们的这种行为!”诸如此类的一堆言语,唉,人言可畏,众口铄金,AOM 对EJB 3 的支持特性,我,还是决定闭嘴了:(

6. 总结

很多同学想知道如何将 AOM、Spring、Hibernate结合在一起使用,本文介绍了 AOM 与 Spring的集成,至于 AOM与Hibernate的集成,其实我感觉更多的还是 Spring 与 Hibernate的集成。有必要再写一篇 AOM 与 Hibernate 集成使用的文章吗?需要吗?不需要吗?...

所有评论
蜜汁肥叉烧 2010-01-06 评论道:
请看文章第五节: "还是需要特意加以说明的是:将一个 EJB 3对象当成一个 LiteBean 使用,需要更改 EJB 容器的实现代码,因此,这个特性只有 Apusic 应用服务器予以支持。"
hgs 2009-12-29 评论道:
你还可以通过 @EJB 标注,将 EJB 对象注入到 LiteBean中使用,并且,这种做法更符合大家的习惯 但是我在JBOSS里面使用@EJB标注,无法注入EJB对象,注入为NULL。高手请指点。
夜了醉了 2008-05-26 评论道:
还是很希望你写一个有关于HIBERNATE的集成
马宏毅 2008-04-24 评论道:
总不能因为别人的评论,你就闭嘴了啊!你这一闭嘴,不但害了你们的支持者,也害了你们自己啊强烈要求内容及时更新,特别是参考的文档,否则对用户来说是一种……
1   共1页
您还没有登录,请登录后发表评论