4.2. CRUD

4.2.1. 前言

续Hello Duke篇,本文将通过一个更丰富的示例,介绍如何通过Apusic Studio快速的开发一个CRUD应用。

4.2.2. Step By Step

注:下列步骤中,如无特殊说明,均采用默认选项。

  1. 创建Apusic工程,工程名为:CRUD

  2. 创建EJB模块。

    工程上点击右键—>新建—>EJB模块,EJB模块名为:ejbJar(默认名)

  3. 在EJB模块中。ejbJar/src上右键New—>Package,包名为:org.operamasks.crud.entity。

  4. 在包上右键—>实体模型—>打开,打开实体模型编辑窗口。

  5. 设计实体模型,并通过模型生成实体代码、业务实现和数据库脚本。

    • 拖拽实体至编辑框中,命名为:Person。

    • 拖拽属性至实体中,添加属性:id、name、address、email。

    • 将id属性要设置为主键。

    • 点击Save按钮,或者Ctrl+s保存实体模型,并自动生成实体代码。

    • 在org.operamasks.crud.entity包上点击右键—>实体模型—>生成业务实现,流程如以下组图。

      (1)选择Session Bean

      (2)选择要生成业务实现的实体

      (3)预览及输出包的选择

      (4)代码自动生成

    • 在EJB模块上点击右键—>数据库工具—>生成数据库建表脚本。选择数据库类型,并指定脚本文件路径。本文中的数据库采用MySql,流程如下组图。

      (1)选择数据库类型和生成的脚本的目录,并点击“添加连接”。

      (2)进行驱动和连接设置

      (3)完成连接设置后回到数据库建表向导,点击next进入实体选择以及完成最后的数据库建表

  6. 配置数据源

    (1)配置服务器上的数据源,选择启动服务器并点击数据源项。

    (2)点击“增加”按钮开始配置新数据源

    (3)或者可以在%apusic_home%\domains\mydomain\config\datasources.xml中手动修改配置,添加数据源属性。

    <datasource name="CRUD"
         jndi-name="jdbc/CRUD"
         driver-class="com.mysql.jdbc.Driver"
         driver-classpath="D:\apusicstudio-5.1\apusicstudio\eclipse\plugins\com.apusic.studio.dev_5.1.5\connectionTemplates\mysql\mysql-connector-5.0.3.jar"
         url="jdbc:mysql://localhost:3306/crud"
      >
        <property name="user" value="root"/>
        <property name="password" value="server"/>
    </datasource>

    (4)配置JPA数据源,在EJB模块中META-INF文件夹中创建persistence.xml文件。并配置JPA数据源。

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
        <persistence-unit name="CRUD" transaction-type="JTA">
            <jta-data-source>jdbc/CRUD</jta-data-source>
        </persistence-unit>
    </persistence>
  7. 创建Web模块。

    (1)完成Web模块创建后创建Faces文件。名为:index.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:ajax="http://www.apusic.com/jsf/ajax" renderKitId="AJAX"
     xmlns:h="http://java.sun.com/jsf/html">
     <w:head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     </w:head>
     <w:page title="Insert title here">
      <w:form>
        <w:dataGrid paged="true" rows="10" id="personGrid" style="height: 155px; width: 784px">
        <w:outputColumn id="id" hidden="true"></w:outputColumn>
        <w:outputColumn id="name"></w:outputColumn>
        <w:outputColumn id="address"></w:outputColumn>
        <w:outputColumn id="email"></w:outputColumn>
       </w:dataGrid>
       <br />
       <layout:panelGrid columns="3">
        <w:button id="add" />
        <w:button id="delete" />
        <w:button id="modify" />
       </layout:panelGrid>
      </w:form>
      <layout:window height="150" width="230" x="300" y="300" id="actionWindow">
       <ajax:updater url="window.xhtml"></ajax:updater>
      </layout:window>
     </w:page>
    </f:view>

    (2)对应的托管Bean的代码如下。

    package org.operamasks.crud.bean;
    
    import java.io.Serializable;
    import java.util.List;
    import java.util.Map;
    import java.util.UUID;
    
    import javax.ejb.EJB;
    
    import org.operamasks.crud.entity.Person;
    import org.operamasks.crud.service.IPersonService;
    import org.operamasks.faces.annotation.Action;
    import org.operamasks.faces.annotation.Bind;
    import org.operamasks.faces.annotation.DataModel;
    import org.operamasks.faces.annotation.LocalString;
    import org.operamasks.faces.annotation.ManagedBean;
    import org.operamasks.faces.annotation.ManagedBeanScope;
    import org.operamasks.faces.component.layout.impl.UIWindow;
    import org.operamasks.faces.component.widget.grid.UIDataGrid;
    
    /**
     * 
     * This managed bean is generated automatically
     */
    @ManagedBean(name = "indexBean", scope = ManagedBeanScope.SESSION)
    @SuppressWarnings( { "unused", "serial" })
    public class IndexBean implements Serializable {
     @Bind(id = "personGrid", attribute = "binding")
     private UIDataGrid personGrid;
     
     @LocalString
     private Map<String,String> messages;
    
     /**
      * 注入EJB
      */
     @EJB(name = "org.operamasks.crud.service.PersonService")
     private IPersonService personService;
    
     @Bind(id = "actionWindow", attribute = "binding")
     private UIWindow actionWindow;
    
     @Bind(id = "personGrid", attribute = "rows")
     private int personGrid_rows;
    
     private Person currentPerson;
    
     public UIWindow getActionWindow() {
      return actionWindow;
     }
    
     /**
      * 返回所有Person
      */
     @DataModel(id = "personGrid")
     private List<Person> getPersonGridValues() {
      return personService.listPerson();
     }
    
     @Action(id = "add")
     public void add() {
      currentPerson = new Person();
      currentPerson.setId(UUID.randomUUID().toString());
      actionWindow.setTitle(this.messages.get("WindowBean.title.new"));
      actionWindow.show();
     }
    
     @Action(id = "delete")
     public void delete() {
      if (personGrid.getSelectedRow() > -1) {
       Object obj = personGrid.getSelectedRowData();
       if (obj instanceof Person) {
        Person person = (Person) obj;
        personService.removePerson(person);
        personGrid.reload();
       }
      }
     }
    
     public UIDataGrid getPersonGrid() {
      return personGrid;
     }
    
     public void setActionWindow(UIWindow actionWindow) {
      this.actionWindow = actionWindow;
     }
    
     @Action(id = "modify")
     public void modify() {
      if (personGrid.getSelectedRow() > -1) {
       Object obj = personGrid.getSelectedRowData();
       if (obj instanceof Person) {
        currentPerson = (Person) obj;
       }
       actionWindow.setTitle(this.messages.get("WindowBean.title.modify"));
       actionWindow.show();
      }
     }
    
     public Person getCurrentPerson() {
      return currentPerson;
     }
    }
    

    (3)创建Faces页面,名为:window.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:ajax="http://www.apusic.com/jsf/ajax" renderKitId="AJAX"
     xmlns:h="http://java.sun.com/jsf/html">
     <w:head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     </w:head>
     <w:page title="Insert title here">
      <w:form>
       <layout:panelGrid columns="3" width="200" style="height: 130px">
        <layout:cell colspan="1" rowspan="1" align="center" style="width: 97px">
         <h:outputLabel for="name"></h:outputLabel>
        </layout:cell>
        <layout:cell colspan="2" rowspan="1">
         <w:textField id="name"></w:textField>
        </layout:cell>
        <layout:cell colspan="1" rowspan="1" align="center">
         <h:outputLabel for="address"></h:outputLabel>
        </layout:cell>
        <layout:cell colspan="2" rowspan="1">
         <w:textField id="address"></w:textField>
        </layout:cell>
        <layout:cell colspan="1" rowspan="1" align="center">
         <h:outputLabel for="email"></h:outputLabel>
        </layout:cell>
        <layout:cell colspan="2" rowspan="1">
         <w:textField id="email"></w:textField>
        </layout:cell>
        <layout:cell colspan="1" rowspan="1">
        </layout:cell>
        <layout:cell colspan="1" rowspan="1">
         <w:button id="save" />
        </layout:cell>
        <layout:cell colspan="1" rowspan="1" align="left">
         <w:button id="cancel" />
        </layout:cell>
       </layout:panelGrid>
      </w:form>
     </w:page>
    </f:view>

    (4)对应托管Bean的代码如下。

    package org.operamasks.crud.bean;
    
    import java.io.Serializable;
    import java.util.Map;
    
    import javax.ejb.EJB;
    import javax.faces.event.PhaseEvent;
    import javax.faces.event.PhaseId;
    
    import org.operamasks.crud.entity.Person;
    import org.operamasks.crud.service.IPersonService;
    import org.operamasks.faces.annotation.Action;
    import org.operamasks.faces.annotation.BeforePhase;
    import org.operamasks.faces.annotation.Bind;
    import org.operamasks.faces.annotation.Inject;
    import org.operamasks.faces.annotation.Label;
    import org.operamasks.faces.annotation.LocalString;
    import org.operamasks.faces.annotation.ManagedBean;
    import org.operamasks.faces.annotation.ManagedBeanScope;
    import org.operamasks.faces.annotation.Required;
    import org.operamasks.faces.annotation.ValidateRegexp;
    import org.operamasks.faces.validator.CommonRegexpPatterns;
    
    /**
     * 
     * This managed bean is generated automatically
     */
    @ManagedBean(name = "windowBean", scope = ManagedBeanScope.REQUEST)
    public class WindowBean implements Serializable {
    
     @EJB(name = "org.operamasks.crud.service.PersonService")
     private IPersonService personService;
    
     @LocalString
     private Map<String, String> messages;
    
     private Person currentPerson;
    
     @Inject
     private IndexBean indexBean;
    
     @Bind(id = "name", attribute = "value")
     @Label(value = "#{this.messages.get('name')}")
     @Required(message = "#{this.messages.get('name.required')}")
     private String name;
    
     @Bind(id = "address", attribute = "value")
     @Label(value = "#{this.messages.get('address')}")
     @Required(message = "#{this.messages.get('address.required')}")
     private String address;
    
     @Bind(id = "email", attribute = "value")
     @Label(value = "#{this.messages.get('email')}")
     @Required(message = "#{this.messages.get('email.required')}")
     @ValidateRegexp(value = CommonRegexpPatterns.EMAIL_ADDRESS, message = "#{this.messages.get('email.invalid')}")
     private String email;
    
     @Action(id = "save")
     public void save() {
      currentPerson.setEmail(this.email);
      currentPerson.setName(this.name);
      currentPerson.setAddress(this.address);
      this.personService.modifyPerson(currentPerson);
      indexBean.getActionWindow().close();
      indexBean.getPersonGrid().reload();
     }
    
     @Action(id = "cancel")
     public void cancel() {
      indexBean.getActionWindow().close();
     }
    
     @BeforePhase
     public void phaseListener(PhaseEvent event) {
      if (event.getPhaseId() == PhaseId.INVOKE_APPLICATION || 
        event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
       currentPerson = indexBean.getCurrentPerson();
      }
      if(event.getPhaseId() == PhaseId.RENDER_RESPONSE){
       this.name = currentPerson.getName();
       this.address = currentPerson.getAddress();
       this.email = currentPerson.getEmail();
      }
     }
    }
    
  8. 国际化资源的配置。

    (1)在包org.operamasks.crud.bean点击右键—>新建—>Properties

    (2)填写文件名称及选择语言种类

    (3)编写资源:

  9. 在Apusic上部署。

    在index.xhtml上右键 -> Run As ->在Apusic应用服务器上运行。

  10. 查看运行结果。