• Seam科普


    声明:这是引用的,具体引用位置在最下面。 只供个人学习,免得忘记了又要到处找,十分感谢原作作者。如果有什么问题请联系我。


    Seam框架开发一个HelloWrld的例子。

    Seam本身,而在于Seam使用JSF和EJB3,所以想要使用Seam的难还在于Seam程序被推荐以ear的形式部署,而ear又是由war,jar构成,这本身给Seam应用之间大同小异,但是毕竟给初学者增加了难度。现在我们说一说war,jar和ear的结构。

    war,jar和ear都是和zip兼容的压缩格式,所以这些文件都可以使用winzip或者winrar直接打开查看结构,一个典型的war的结构为 

    app.war

        **/*.jsp

        **/*.js

        WEB-INF

            web.xml

            classes

            lib

    一个ejb类型的jar的典型结构为:

     app.jar

         META-INF

             ejb-jar.xml

         **/*.class  

    ear的结构有若干个war或者jar构成。

    我们接下来将要将的helloworld应用程序的结构如下,我们会逐步讲解这些内容

    helloworld.ear│ 
    ├—app.jar
    │  │  seam
    │  │          └—helloworld
    │  │                  Manager.class
    │  │                  ManagerAction.class
    │  │                  Person.class
    │  │                 
    │  └—META-INF
    │          ejb-jar.xml
    │          MANIFEST.MF
    │          persistence.xml
    │         
    ├—app.war
    │  │  hello.jsp
    │  │  index.html
    │  │ 
    │  ├—META-INF
    │  │      MANIFEST.MF
    │  │     
    │  └—WEB-INF
    │          components.xml
    │          faces-config.xml
    │          navigation.xml
    │          web.xml
    │         
    ├—lib
    │      jboss-el.jar
    │      jboss-seam.jar
    │     
    └—META-INF
            application.xml
            MANIFEST.MF
    

    这里先留一个问题,为什么所有的class文件都不在war文件内部,而在jar的内部呢?

    提示:jboss的classloader机制。

    程序的业务

    这个程序的业务很简单,只有一个页面,这个页面上面是一个输入组件,下面是一个列表组件。可以将自己的名字填写在输入组件中,点击提交按钮,将自己的名字登录到数据库中,同时回到这个页面,在下面的列表中输出数据库中所有的名字,这个例子来源于Michael JunTao Yuan的《JBoss Seam simplicity and power beyond java ee》请大家参考。

    数据库

    我们使用HSQL的内存数据库,每次启动的时候在内存中创建,每次停止的时候废弃所有的数据,HSQL的特点是开发非常的方便。

    我们首先定义一个EJB3的Entity Bean用来记录录入的人员信息,代码为:

    package com.jpleasure.seam.helloworld;
    
     
    
    import org.jboss.seam.annotations.Name;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import java.io.Serializable;
    
     
    
    @Entity
    @Name("person")
    public class Person implements Serializable {
        private long id;
        private String name;
    
    
        @Id
        @GeneratedValue
        public long getId() {
            return id;
        }
    
        public void setId(long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    这里需要介绍一些基本的内容,

    1. Entity需要实现Serializable接口,这是EJB3 的要求,对于可能存在远程调用的情况也是业务的要求。

    2. @Entity 这个标注(Annotation)标记了Person类似一个Entity Bean,也就是对应着数据库中的一张表,在默认的情况下这个表和这个类同名,所以数据库中的表名为Person 。

    3. @Name("person")是Seam的标注,在这个应用程序中以后可以使用person这个字符串来关联到Person的示例。

    4. @Id 说明private long id表示的属性在数据库中对应为主键

    5. @GeneratedValue表示这个主键会自动生成

    上述代码中最关键的是Name这个标注,在后续的代码中你将会看到如何使用Name这个标注。

    业务处理

    业务处理在Seam中使用EJB3中的Session Bean充当,使用Session Bean可以利用EJB容器提供的各种特定,例如声明式的事务,安全等。

    使用Session Bean一般需要定义一个接口,用来约束所能够提供的服务,这个接口为:

    package com.jpleasure.seam.helloworld;
    
    
    import javax.ejb.Local;
    @Local
    public interface Manager {
        public String sayHello();
    }
    

    一些说明:

    1. @Local说明了这是这个Session Bean的本地接口

    业务实现类(Session Bean)

    package com.jpleasure.seam.helloworld;
    
     
    
    import org.jboss.seam.annotations.Name;
    import org.jboss.seam.annotations.Out;
    
    import javax.ejb.Stateless;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import java.util.List;
    
     
    
    @Stateless
    @Name("manager")
    public class ManagerAction implements Manager {
    
        @In
        @Out
        private Person person;
    
        @Out
        private List<Person> fans;
    
        @PersistenceContext
        private EntityManager em;
    
        public String sayHello() {
            em.persist(person);
            person = new Person();
            fans = em.createQuery("select p from Person p")
                    .getResultList();
    
            return null;
        }
    }
    

    一些说明:

    1. @Stateless 标记这个类为Stateless 类型的Session Bean。

    2. @Name(“manager”)是Seam框架环境下ManagerAction这个Stateless Session Bean。

    3. @In表示这个对象可以被注入,也就是大家常说的依赖注入,在运行的时候每每生成一个ManagerAction,就会创建一个名字叫person的对象(@In没有参数的时候绑定属性名字相同的对象),也就是上面定义的Person这个EJB3的Entity Bean。

    3. @Out表示,这个属性所在的类(ManagerAction)的方法执行完毕之后,这个标注标记的属性会被注出到后续使用这个属性的地方。

       对于这个地方需要解释一下,当用户提交的信息的时候,这些信息会给放在Person类型的实例中,放在ManagerAction的person属性中,这是注入

       当sayHello执行完毕之后,person被赋值new Person(),这个时候上次所填写的内容将会被new Person()替代,后续使用到person属性的地方那个将会使用new Person(),而不会使用原来的输入内容,这叫做注出

        使用@In和@Out可以达到bijection的效果

    我们接着来看看JSF页面

    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
    
    <html>
    <body>
    <f:view>
    
        <f:verbatim>
            <h2>Seam Hello World</h2>
        </f:verbatim>
    
        <h:form>
            <f:verbatim>
                Please enter your name:<br/>
            </f:verbatim>
    
            <h:inputText value="#{person.name}" size="15"/><br/>
            <h:commandButton type="submit" value="Say Hello"
                             action="#{manager.sayHello}"/>
        </h:form>
    
        <f:subview id="fans"
                   rendered="#{!empty(fans)}">
            <f:verbatim>
                <p>The following fans have said "hello" to JBoss Seam:</p>
            </f:verbatim>
    
            <h:dataTable value="#{fans}" var="fan">
                <h:column>
                    <h:outputText value="#{fan.name}"/>
                </h:column>
            </h:dataTable>
        </f:subview>
    
    </f:view>
    </body>
    </html>
    
    一些说明:
    
    1. 关于表达式语言,例如 #{person.name}表示跟person的name属性绑定,根据上面@Name的定义,我们知道跟Person的一个实例绑定。
    
        #{manager.sayHello} 表示调用manager的sayHello方法,也就是ManagerAction的sayHello方法。
    
        #{fans} 由于ManagerAction的fans使用了@Out标注,且诶有制定名字,所以fans在表达式语言中表示ManagerAction的属性,这里只是用来表示,没有输入,所以我没有使用绑定这个词,绑定的含义是提交的时候赋值,输出的时候显示。
    
     
    
    再说一说配置文件:
    
    WEB-INF/web.xml文件是Web项目集成Seam的切入点,参看一下代码,特别是黑体部分: 
    
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.4"
             xmlns="http://java.sun.com/xml/ns/j2ee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
        <context-param>
            <param-name>javax.faces.CONFIG_FILES</param-name>
            <param-value>/WEB-INF/navigation.xml</param-value>
        </context-param>
    
        <!-- seam.servlet.SeamListener</listener-class>
        </listener>
    
        <context-param>
            <param-name>
                javax.faces.STATE_SAVING_METHOD
            </param-name>
            <param-value>server</param-value>
        </context-param>
    
        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>
                javax.faces.webapp.FacesServlet
            </servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>*.seam</url-pattern>
        </servlet-mapping>
    
    </web-app>
    

    WEB-INF/navigation.xml定义了JSF的画面迁移关系,由于只有一个页面,所以不用定义迁移关系:

     <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE faces-config
        PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
        "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
    
    <faces-config>
      <!-- single page app, no navigation rules -->
    </faces-config>
    

    WEB-INF/navigation.xml是JSF的基本配置文件,这里也为空,因为真的没什么可以配置的,我们的程序是Hello World。

    <faces-config version="1.2"
       xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
    
    </faces-config>
    

    WEB-INF/component.xml是Seam的基本配置文件,定义的内容如下,这些内容在不同的应用之间只有简单的变化,例如jndi-patter中helloworld替换为新的项目名字。 

    <?xml version="1.0" encoding="UTF-8"?>
    <components xmlns="http://jboss.com/products/http://jboss.com/products/http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation=
                  "http://jboss.com/products/http://jboss.com/products/http://jboss.com/products/http://jboss.com/products/seam/components-2.0.xsd">
    
      <core:init jndi-pattern="helloworld/#{ejbName}/local" debug="false"/>
    
      <core:manager conversation-timeout="120000"/>
    
    </components>
    

    conversation-timeout我们在后续状态部分讲解。

    seam的一些基本配置,这里暂时不需要,所以seam.properties为空。

    ejb模块中,META-INF/ejb-jar.xml文件,用来定义EJB,这里由于这里都是用了标注(@Stateless,@Entity等)所以这里没有ejb的定义,只有Seam对于EJB项目的切入点。

    <?xml version="1.0" encoding="UTF-8"?>
    <ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
             version="3.0">
      <interceptors>
         <interceptor>
           <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
         </interceptor>
       </interceptors>
    
      <assembly-descriptor>
        <interceptor-binding>
          <ejb-name>*</ejb-name>
          <interceptor-class>
            org.jboss.seam.ejb.SeamInterceptor
          </interceptor-class>
        </interceptor-binding>
      </assembly-descriptor>
    </ejb-jar>
    

    ejb模块中,META-INF/persistence.xml文件,这个文件根据EJB规范的要求,为EJB3中的Entity定义持久化单元(简单的说是数据访问的上下文环境),包含数据库,提供者等信息。

    <persistence>
      <persistence-unit name="helloworld">
        <provider>
          org.hibernate.ejb.HibernatePersistence
        </provider>
        <jta-data-source>java:/DefaultDS</jta-data-source>
        <properties>
          <property name="hibernate.dialect"
              value="org.hibernate.dialect.HSQLDialect"/>
          <property name="hibernate.hbm2ddl.auto"
              value="create-drop"/>
          <property name="hibernate.show_sql" value="true"/>
        </properties>
      </persistence-unit>
    </persistence> 
    
     
    

    ear的lib目录中包含了我们需要使用的类库文件,分别是jboss-el.jar和jboss-Seam Hello World</display-name>

     <module>
        <web>
          <web-uri>app.war</web-uri>
          <context-root>/helloworld</context-root>
        </web>
      </module>
    
      <module>
        <ejb>app.jar</ejb>
      </module>
    
      <module>
        <ejb>lib/jboss-seam.jar</ejb>
      </module>
    
    </application>
    

    现在回答前面我们设置的问题。

    在JBoss服务器启动的时候Load的继承机构为EJBCLassLoader是WEBClassLoader的父类,所以EBJClassLoader装在的内容在WEBClassLoader装在的内容中是可见的。

     

    添加Facelets功能

    1. 追加Facelets功能需要添加新的类库,这些类库文件需要放在WEB-INF/lib目录下,这些文件的名字是:

       jboss-seam-debug.jar

       jsf-facelets.jar 

    2. 需要配置JSF如何处理文件的方式,使用xhtml代替jsp文件:

    faces-config.xml文件追加如下内容:

    <application>
        <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
      </application>
    

    3. 还需要在web.xml添加如下内容:

    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
      </context-param>
    

    4. 将hello.jsp修改为hello.xhtml

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core">
    <body>
    
    <h2>The Facelets Demo</h2>
    
    <h:form>
        Please enter your name:<br/>
        <h:inputText value="#{person.name}" size="15"/><br/>
        <h:commandButton type="submit" value="Say Hello"
                         action="#{manager.sayHello(person)}"/>
    </h:form>
    
    <f:subview id="fans"
               rendered="#{!empty(fans)}">
        <p>The following people have said "hello" to JBoss         <h:column>
                <h:outputText value="#{fan.name}"/>
            </h:column>
        </h:dataTable>
    </f:subview>
    
    </body>
    </html>
    

    引用:http://cache.baiducontent.com/c?m=9d78d513d98216fc07f9d33e53198d205f1697624fcacd452189c65f93130a00113af4bb507e4742ce843a2746e9085cf7a376346c527ee0869edf0c8ee0cc69328b2d3e70178c43&p=ce65c54ad6c042be1ca2c7710f47cc&newp=8b2a9715d9c342ac0ca9cc3652508d231610db2151d7d2126b82c825d7331b001c3bbfb423241602d7ce7b6707a9435ee1f33375350523a3dda5c91d9fb4c57479&user=baidu&fm=sc&query=Seam&qid=e89454d20003ee29&p1=6&bcsi_scan_50cf319c8a3b1a7d=2JlSyvSW7io/n3ZP9Rtu3ezdRBUUAAAA6kNyCw==

  • 相关阅读:
    C# 实现从程序集中抽取内嵌资源文件
    git clone 显著提速,解决Github代码拉取速度缓慢问题
    C# 将List数据 导出到csv 文件
    Nginx的location匹配规则-根据url 路径重定向到不同的IP
    WinForm最小化到托盘以及托盘右键菜单
    安卓手机浏览器调试-Debug模式
    C#-Forms.Timer、Timers.Timer、Threading.Timer的比较和使用
    批处理实现批量创建快捷方式
    设计模式(六)装饰模式(转)
    设计模式(五)桥接模式(转)
  • 原文地址:https://www.cnblogs.com/Willie-WangLiang/p/7241243.html
Copyright © 2020-2023  润新知