Chapter 4. 设置 Seam 组件

seam中,对基于XML的设置予以简化,其作用是非常巨大的。然而,有很多原因,使我们应当用XML来设置seam组件:从java代码中分离出特定的部署信息,建立复用框架,设置seam的内建功能,等等。对于设置组件,Seam提供两种基本的途径:通过设置属性文件或web.xml里的属性,以及通过设置components.xml文件。

 

4.1.通过属性设定来设置组件

提供Seam组件时可以带有属性配置,它们是由servlet context参数,或者classpath根部的seam.properties文件提供的。可配置的seam组件必须为可配置的属性建立JavaBeans类型的setter方法。如果一个名称为com.jboss.myapp.settings seam组件有一个名称为setLocale()setter方法,我们就可以在seam.properties文件中提供一个名称为com.jboss.myapp.settings.locale的属性,seam在实例化这个组件时,将据此设置locale属性的值。

 

设置seam本身时也使用了这种机制,例如,为设置会话时间,我们在web.xmlseam.propertiesorg.jboss.seam.core.manager.conversationTimeout提供了一个值。(seam

中有一个名为org.jboss.seam.core.managerseam组件,它有一个名为setConversationTimeout()setter方法)

 

4.2.通过components.xml配置组件

 

components.xml文件比属性设定更强大一些。它可以让你:

设置已经自动安装的组件包括内建的组件,和用@Name标注了的和seam的部署扫描器安装的应用程序组件。

把没有用@Name标注的类安装为seam组件--这对某些特定的底层组件非常有用,这种底层组件可以用不同的名称安装多次(例如Seam-managed persistence contexts)。

安装确实有@Name标注,但是由于有@Install标注(表明这个组件不应该安装)默认没被安装的组件。

覆盖组件的生命期。

 

一个components.xml文件可能出现在以下位置:

• War文件的WEB-INF目录。

• Jar文件的META-INF目录。

包含具有@Name标注的类的jar文件的任何目录。

 

For example, the following components.xml file installs jBPM:

一般说来,当部署扫描器发现一个含有@Name标注的类,这个类在seam.properties META-INF/components.xml文件中作了登记,部署扫描器将安装这个类(除非这个组件@Instal标注,表明它默认不应安装)。components.xml文件允许我们处理需要覆盖标注的特殊情况。

 

例如,以下components.xml文件安装jBPM

 

<components xmlns="http://jboss.com/products/seam/components" 
   
   
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   
   
            xmlns:bpm="http://jboss.com/products/seam/bpm">
   
   
    <bpm:jbpm/>
   
   
</components>
   
   

 

下面例子将做同样的事:

 

<components>
   
   
    <component class="org.jboss.seam.bpm.Jbpm"/>
   
   
</components>
   
   

 

下面例子安装并设置两种不同的Seam-managed persistence contexts

 

<components xmlns="http://jboss.com/products/seam/components" 
   
   
            xmlns:persistence="http://jboss.com/products/seam/persistence"
   
   

   
   
    
     
   
   
    <persistence:managed-persistence-context name="customerDatabase"
   
   
                       persistence-unit-jndi-name="java:/customerEntityManagerFactory"/>
   
   
        
   
   
    <persistence:managed-persistence-context name="accountingDatabase"
   
   
                       persistence-unit-jndi-name="java:/accountingEntityManagerFactory"/>            
   
   

   
   
    
     
   
   
</components>
   
   

 

与以下例子作用相同:

 

<components>
   
   
    <component name="customerDatabase" 
   
   
              class="org.jboss.seam.persistence.ManagedPersistenceContext">
   
   
        <property name="persistenceUnitJndiName">java:/customerEntityManagerFactory</property>
   
   
    </component>
   
   
    
   
   
    <component name="accountingDatabase"
   
   
              class="org.jboss.seam.persistence.ManagedPersistenceContext">
   
   
        <property name="persistenceUnitJndiName">java:/accountingEntityManagerFactory</property>
   
   
    </component>
   
   
</components>
   
   

 

这个例子建立了一个session会话期的Seam-managed persistence context(实践中不推荐这么做):

 

<components xmlns="http://jboss.com/products/seam/components" 
   
   
            xmlns:persistence="http://jboss.com/products/seam/persistence"
   
   

   
   
    
     
   
   
  <persistence:managed-persistence-context name="productDatabase" 
   
   
                                          scope="session"
   
   
                     persistence-unit-jndi-name="java:/productEntityManagerFactory"/>        
   
   

   
   
    
     
   
   
</components>
   
   
<components>
   
   
            
   
   
    <component name="productDatabase"
   
   
              scope="session"
   
   
              class="org.jboss.seam.persistence.ManagedPersistenceContext">
   
   
        <property name="persistenceUnitJndiName">java:/productEntityManagerFactory</property>
   
   
    </component>
   
   

   
   
    
     
   
   
</components>
   
   

 

对基层对象,比如persistence contexts通常可以用auto-create 选项。使用persistence contexts的一个好处是,当你使用@In标注时,不必显式声明create=true

<components xmlns="http://jboss.com/products/seam/components" 
   
   
            xmlns:persistence="http://jboss.com/products/seam/persistence"
   
   

   
   
    
     
   
   
  <persistence:managed-persistence-context name="productDatabase" 
   
   
                                    auto-create="true"
   
   
                     persistence-unit-jndi-name="java:/productEntityManagerFactory"/>        
   
   

   
   
    
     
   
   
</components>
   
   
<components>
   
   
            
   
   
    <component name="productDatabase"
   
   
        auto-create="true"
   
   
              class="org.jboss.seam.persistence.ManagedPersistenceContext">
   
   
        <property name="persistenceUnitJndiName">java:/productEntityManagerFactory</property>
   
   
    </component>
   
   

   
   
    
     
   
   
</components>
   
   

 

 

<factory>声明用于指定一个值或方法表达式,以便在第一次被引用时初始化context变量的值。

 

<components>
   
   

   
   
    
     
   
   
    <factory name="contact" method="#{contactManager.loadContact}" scope="CONVERSATION"/>
   
   

   
   
    
     
   
   
</components>
   
   

 

可以为seam组件建立一个“别名”(第二个名字):

<components>
   
   

   
   
    
     
   
   
    <factory name="user" value="#{actor}" scope="STATELESS"/>
   
   

   
   
    
     
   
   
</components>
   
   

 

甚至可以为常用的表达式建立一个别名:

<components>
   
   

   
   
    
     
   
   
    <factory name="contact" value="#{contactManager.contact}" scope="STATELESS"/>
   
   

   
   
    
     
   
   
</components>
   
   

 

带有<factory> auto-create="true"参数的<factory>声明尤其常见:

<components>
   
   

   
   
    
     
   
   
    <factory name="session" value="#{entityManager.delegate}" scope="STATELESS" auto-create="true"/>
   
   

   
   
    
     
   
   
</components>
   
   

 

有时我们想在部署和测试时以最小的改变复用 components.xml seam 允许你在 components.xml 文件中使用通配符 @wildcard@ ,它可以被你的 Ant build script (部署时)或被一个类路径下(部署时)名为 compon-ents.properties 文件替换。在 seam 例子中你会见到这种方式。

 

4.3. 细粒度配置文件

 

如果你需要用XML配置大量的组件,那么把components.xml中的信息分离开来是很有必要的。例如,可以把com.helloworld.Hello类的设置信息放到名为com/helloworld/Hello.component.xml的文件中。(你可能熟悉这种模式,因为这与Hibernate中的相同 该文件的根元素可以是<components> <component>

 

第一种方式你可以定义多个组件:

<components>
   
   
    <component class="com.helloworld.Hello" name="hello">
   
   
        <property name="name">#{user.name}</property>
   
   
    </component>
   
   
    <factory name="message" value="#{hello.message}"/>
   
   
</components>
   
   

第二种方式仅能定义或设置一个组件,但更简单:

<component name="hello">

<property name="name">#{user.name}</property>

</component>
   
   

 

第二种方式中,类名称由组件定义文件来暗示。

你也可以把com.helloworld 包中的所有类设置放到 com/helloworld/components.xml 中。


 

4.4. 可以设置的属性类型

如你所愿,可以设置的属性类型有string primitive primitive wrapper

 

org.jboss.seam.core.manager.conversationTimeout 60000
   
   
<core:manager conversation-timeout="60000"/>
   
   
<component name="org.jboss.seam.core.manager">
   
   
    <property name="conversationTimeout">60000</property>
   
   
</component>
   
   

也支持Arrays, sets lists of strings primitives

org.jboss.seam.bpm.jbpm.processDefinitions order.jpdl.xml, return.jpdl.xml, inventory.jpdl.xml
   
   
<core:jbpm>
   
   
    <core:process-definitions>
   
   
        <value>order.jpdl.xml</value>
   
   
        <value>return.jpdl.xml</value>
   
   
        <value>inventory.jpdl.xml</value>
   
   
    </core:process-definitions>
   
   
</core:jbpm>
   
   
<component name="org.jboss.seam.bpm.jbpm">
   
   
    <property name="processDefinitions">
   
   
        <value>order.jpdl.xml</value>
   
   
        <value>return.jpdl.xml</value>
   
   
        <value>inventory.jpdl.xml</value>
   
   
    </property>
   
   
</component>
   
   

支持Even maps with String-valued keys string primitive 值:

<component name="issueEditor">
   
   
    <property name="issueStatuses">
   
   
        <key>open</key> <value>open issue</value>
   
   
        <key>resolved</key> <value>issue resolved by developer</value>
   
   
        <key>closed</key> <value>resolution accepted by user</value>
   
   
    </property>
   
   
</component>
   
   

最后,你可以用一个值绑定表达式将多个组件打包。注意,这与用@In 注入有很大不同,因为这发生在组件实例化之时,而非被调用之时。因此,这与传统的IoC容器,像JSF Spring提供的依赖注入环境(dependency injection facilities)更相似。

<drools:managed-working-memory name="policyPricingWorkingMemory" rule-base="#{policyPricingRules}"/>
   
   
<component name="policyPricingWorkingMemory"
   
   
          class="org.jboss.seam.drools.ManagedWorkingMemory">
   
   
    <property name="ruleBase">#{policyPricingRules}</property>
   
   
</component>
   
   

4.5. 使用XML 命名空间

在所有例子中,声明组件时有两种竞争的方式:用或者不用XML命名空间。下面的例子显示了一种典型的不用命名空间的components.xml

<?xml version="1.0" encoding="UTF-8"?>
   
   
<components xmlns="http://jboss.com/products/seam/components"
   
   
            xsi:schemaLocation="http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.0.xsd">
   
   

   
   
    
     
   
   
    <component class="org.jboss.seam.core.init">
   
   
        <property name="debug">true</property>
   
   
        <property name="jndiPattern">@jndiPattern@</property>
   
   
    </component>
   
   
    
   
   
</components>
   
   

这有点冗长。更糟的是,组件和属性在开发时是不可用的。

命名空间版像这样:

<?xml version="1.0" encoding="UTF-8"?>
   
   
<components xmlns="http://jboss.com/products/seam/components"
   
   
            xmlns:core="http://jboss.com/products/seam/core"
   
   
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   
   
            xsi:schemaLocation=
   
   
                "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.0.xsd 
   
   
                 http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.0.xsd">
   
   

   
   
    
     
   
   
    <core:init debug="true" jndi-pattern="@jndiPattern@"/>
   
   

   
   
    
     
   
   
</components>
   
   

虽然对schema的声明较长,不过真正的XML内容较短且易懂。Schemas提供了关于每个组件和属性的详细信息,允许XML编辑器提供自动完成(intelligent autocomplete)功能。命名空间元素的使用使生成与维护正确的components.xml文件变得非常容易。

现在,对内建seam组件来说,这种机制已经非常完善,但是,用户组件如何呢?有两个选项。第一,seam支持两种模型的混合,允许对用户组件使用普通的<component>声明,同时对内建seam组件使用命名空间声明。更妙的是,seam允许对你自己的组件快速声明命名空间。

@Namespace标注过的任何Java package皆可以关联一个XML命名空间。(包目录中package-info.java文件可以声明Package-level annotations)这里是取自seampay演示的例子:

@Namespace(value="http://jboss.com/products/seam/examples/seampay")
   
   
package org.jboss.seam.example.seampay;
   
   

   
   
    
     
   
   
import org.jboss.seam.annotations.Namespace;
   
   

这就是需要你在components.xml做的全部工作!现在我们可以这样写:

<components xmlns="http://jboss.com/products/seam/components"
   
   
            xmlns:pay="http://jboss.com/products/seam/examples/seampay"
   
   
            ... >
   
   

   
   
    
     
   
   
    <pay:payment-home new-instance="#{newPayment}"
   
   
                      created-message="Created a new payment to #{newPayment.payee}" />
   
   

   
   
    
     
   
   
    <pay:payment name="newPayment"
   
   
                 payee="Somebody"
   
   
                 account="#{selectedAccount}"
   
   
                 payment-date="#{currentDatetime}"
   
   
                 created-date="#{currentDatetime}" />
   
   
     ...
   
   
</components>
   
   

或者这样写:

<components xmlns="http://jboss.com/products/seam/components"
   
   
            xmlns:pay="http://jboss.com/products/seam/examples/seampay"
   
   
            ... >
   
   

   
   
    
     
   
   
    <pay:payment-home>
   
   
        <pay:new-instance>"#{newPayment}"</pay:new-instance>
   
   
        <pay:created-message>Created a new payment to #{newPayment.payee}</pay:created-message>
   
   
    </pay:payment-home>
   
   
    
   
   
    <pay:payment name="newPayment">
   
   
        <pay:payee>Somebody"</pay:payee>
   
   
        <pay:account>#{selectedAccount}</pay:account>
   
   
        <pay:payment-date>#{currentDatetime}</pay:payment-date>
   
   
        <pay:created-date>#{currentDatetime}</pay:created-date>
   
   
     </pay:payment>
   
   
     ...
   
   
</components>
   
   

这些例子演示了一个命名空间元素的两种使用模式。第一个声明中,<pay:payment-home>引用了paymentHome组件:

package org.jboss.seam.example.seampay;
   
   
...
   
   
@Name("paymentHome")
   
   
public class PaymentController
   
   
    extends EntityHome<Payment>
   
   
{
   
   
    ... 
   
   
}
   
   

元素名称是连字符型的组件名称。元素属性是连字符型的属性名称。

第二个声明中,<pay:payment>元素指的是org.jboss.seam.example.seampay包中的Payment类。在本例中,Payment是一个声明为seam组件的entity

package org.jboss.seam.example.seampay;
   
   
...
   
   
@Entity
   
   
public class Payment
   
   
    implements Serializable
   
   
{
   
   
    ...
   
   
}
   
   

如果我们想为用户定义的组件实现校验及自动完成功能,则需要一个schemaSeam还没有为一系列组件自动生成schema的功能,所以必须手工生成。可以参照标准seam包的schema定义。

以下是seam使用的命名空间:

 

• components — http://jboss.com/products/seam/components

• core — http://jboss.com/products/seam/core

• drools — http://jboss.com/products/seam/drools

• framework — http://jboss.com/products/seam/framework

• jms — http://jboss.com/products/seam/jms

• remoting — http://jboss.com/products/seam/remoting

• theme — http://jboss.com/products/seam/theme

• security — http://jboss.com/products/seam/security

• mail — http://jboss.com/products/seam/mail

• web — http://jboss.com/products/seam/web

• pdf — http://jboss.com/products/seam/pdf

• spring — http://jboss.com/products/seam/spring

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值