`
benqend
  • 浏览: 32802 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

Seam的HelloWorld 使用Seam开发简单的Web应用

    博客分类:
  • seam
 
阅读更多
Seam版Hello World

我们下面使用Seam框架开发一个HelloWrld的例子。

Seam的难不再Seam本身,而在于Seam使用的内容,Seam使用JSF和EJB3,所以想要使用Seam必须首先学会JSF和EJB3,另外Seam的难还在于Seam的开发和部署结构,Seam程序被推荐以ear的形式部署,而ear又是由war,jar构成,这本身给Seam的使用增加了难度,虽然这些配置文件在多个不同的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.properties
│  │
│  ├─com
│  │  └─jpleasure
│  │      └─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.In;
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组建,标记了在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 -->
    <listener>
        <listener-class>org.jboss.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/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 jndi-pattern="helloworld/#{ejbName}/local" debug="false"/>

  <core:manager conversation-timeout="120000"/>

</components>



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



seam.properties文件用来定义seam的一些基本配置,这里暂时不需要,所以seam.properties为空。



ejb模块中,META-INF/ejb-jar.xml文件,用来定义EJB,这里由于这里都是用了标注(@Stateless,@Entity等)所以这里没有ejb的定义,只有Seam的一个拦截器的定义,对所有EJB的调用都需要经过SeamInterceptor,这是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.jar.

ear的META-INF目录包含了对这个ear项目定义的application.xml文件,内容为:

<application>
  <display-name>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-ui.jar

   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 Seam:</p>
    <h:dataTable value="#{fans}" var="fan">
        <h:column>
            <h:outputText value="#{fan.name}"/>
        </h:column>
    </h:dataTable>
</f:subview>

</body>
</html>

Link:http://blog.csdn.net/struts2/article/details/1882980
分享到:
评论

相关推荐

    Seam 例子 Hello World

    通过这个简单的Hello World示例,我们可以看到Seam框架如何简化了Java Web应用程序的开发过程。从实体定义到页面处理,再到事件处理器的设计,Seam都提供了简便的方式来实现这些功能,大大提高了开发效率。希望这个...

    Seam简单入门学习教程.docx

    Seam的核心特性在于它简化了组件之间的交互,使得开发人员能够更高效地构建复杂的Web应用程序,而无需过多关注底层的集成细节。 在传统的Java EE应用中,开发人员通常需要手动进行JNDI查找、XML声明组件、值对象和...

    jsf-seam-jpa文档

    在实际开发中,Seam的使用涵盖了从创建简单的Hello World程序到构建复杂的业务流程驱动的应用。例如,通过Seam,开发者可以轻松实现RESTful服务,使得HTTP GET和POST操作都能得到妥善处理。此外,Seam与jBPM的集成...

    JBoss Seam: Simplicity and Power Beyond Java EE

    - **示例代码**:通过一个简单的 HelloWorld 应用程序来展示 Seam 的基本用法。 - **集成环境**:演示如何设置开发环境,包括安装 JBoss AS 和配置 Seam。 - **数据库集成**:简述如何将数据库与 Seam 应用集成...

    netbeans_Facelets_Seam_Ejb3编程入门

    在“基本Seam应用开发”章节,作者通过一个简单的“Hello World”示例,演示了如何创建一个包含Seam组件的EAR(Enterprise Archive)项目。这涉及到: - **EAR项目配置**:如何在NetBeans中创建和配置一个包含多个...

    JBoss Seam工程的创建

    例如,如果你的项目名为“helloworld”,那么访问`http://localhost:8080/helloworld`,可以看到一个使用Facelets(view/home.xhtml)和模板(view/layout/template.xhtml)构建的首页。你可以直接在Eclipse中编辑...

    自己做的seam例子

    总的来说,这个Seam例子展示了如何使用Seam框架构建具有用户注册、登录、工作流管理和简单交互的应用程序。通过学习这个例子,开发者可以熟悉Seam的组件、事件模型、安全机制以及如何集成第三方库如jbpm来处理复杂的...

    JBoss Seam 工作原理、seam和hibernate的范例、RESTFul的seam、seam-gen起步、seam组件、配置组件、jsf,jboss、标签、PDF、注解等等

    1.6. 一个完整的Seam 应用程序:宾馆预订范例............................................................................................................ 45 1.6.1. 介绍......................................

    beginning jboss seam

    总之,《Beginning JBoss Seam》是一本全面介绍Seam框架的入门教程,适合对Java EE感兴趣的开发者阅读,无论你是初学者还是有经验的开发者,都能从中获益,提升你的企业级应用开发能力。通过这本书,你将学会如何...

    webbean.pdf

    这一技术在Seam框架的发展方向上占据着重要的位置,对于想要深入理解并掌握现代Java Web应用开发的开发者来说,非常值得学习。 #### WebBeans简介 WebBeans主要关注两个方面:依赖注入和上下文状态管理。依赖注入...

    Simple JSF application with RichFaces

    构建一个简单的JSF应用并集成RichFaces不仅能够提高Web应用的交互性和响应速度,还能够简化前端开发的复杂度。通过上述步骤,你可以快速上手并在实际项目中运用这些知识。希望本指南能对你有所帮助!

    richfaces_reference的相关文档

    ### RichFaces框架:深入解析与应用 ...通过上述内容的详细介绍,我们不仅能够对RichFaces框架有全面的了解,还能掌握其实际应用中的各种技巧和最佳实践,为高效、美观的Web应用开发打下坚实的基础。

    hibernate validate 中文文档 英文文档

    13. 与其他框架的集成(Integrating with other frameworks):Hibernate Validator提供了与其他流行Java框架的集成支持,如ORM集成、JavaServer Faces和Seam、CDI、Java EE以及JavaFX。 14. Hibernate Validator...

    生命编码:每天编程。程序不仅使计算机更智能,而且使我们也更智能。 所以继续解决并编写程序

    生活编码 每天解决一个问题。 我所有的日常解决问题都生活在此仓库中。 这里也有一些错误的尝试。 如果您遵循此仓库,请确保您运行代码并尝试使用测试用例。... String s="HelloWorld"; Map&lt;Character&gt; m

Global site tag (gtag.js) - Google Analytics