Ofbiz

ofbiz学习之部署组件

2018-08-01  本文已影响0人  dounine

ofbiz学习之部署learning组件

一、部署前准备

1、环境及工具

eclipse2017;jdk1.8;Mysql5。

2、连接Mysql数据库

3、导入eclipse

二、创建组件

  右键点击ofbiz根目录下的build.xml——Run as(运行方式)——Ant构建(第二个)——在“选择要执行的目标”的框中——取消start——找到create component打钩——点击运行——在出现的输入框中都输入组建的名字learning——最后一步选择Y——完成——刷新左边的资源管理视图——hot-deploy下出现learning组件目录

三、初始部署

1、修改learning/ofbiz-component.xml文件中的webapp标签:

<webapp name="learning"
        title="learning"
        server="default-server"
        location="webapp/learning"
        base-permission="OFBTOOLS"
        mount-point="/learning"
        app-bar-display="true"/>

  base-permission代表登陆权限,app-bar-display="true"表示该应用会在后台应用主菜单中出现。

2、初次体验。启动ofbiz,浏览器进入后台目录管理界面,点击左上角的应用菜单,再点击learning,进入应用主页面。如果页面中显示“不允许你浏览这个页面。”,不必担心,这只是你未做任何添加前的自动生成页面。

3、创建controller。在learning/webapp/learning/WEB-INF/controller.xml中,添加一个请求映射:

<request-map uri="FindProductPlan">
    <security https="true" auth="true" />
    <response name="success" type="view" value="FindProductPlan" />
</request-map>

  根据请求映射,再添加一个响应的view视图映射:

<view-map name="FindProductPlan" type="screen" page="component://learning/widget/learningScreens.xml#FindProductPlan"/>

4、创建视图。在learning/widget/learningScreens.xml中,添加一个name=FindProductPlan的screen视图装饰器:

<screen name="FindProductPlan">
        <section>
            <actions>
                <set field="headerItem" value="ProductPlan"/>
            </actions>
            <widgets>
                <decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}">
                    <decorator-section name="body">
                        <section>
                             <widgets>
                                 <decorator-screen name="FindScreenDecorator" location="component://common/widget/CommonScreens.xml">
                                     <decorator-section name="menu-bar">
                                         <container style="button-bar">
                                             <link target="EditProductPlan" text="新建" style="buttontext create"/>
                                         </container>
                                     </decorator-section>
                                     <decorator-section name="search-options">
                                         <include-form name="FindProductPlan" location="component://learning/widget/learningForms.xml"/>
                                     </decorator-section>
                                     <decorator-section name="search-results">
                                         <include-form name="ListProductPlan" location="component://learning/widget/learningForms.xml"/>
                                     </decorator-section>
                                 </decorator-screen>
                             </widgets>
                         </section>
                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>

  关于ofbiz装饰器的配置规则,请参考Apache+OFBiz+开发初学者指南.chm(关于此份文档如何获取,请浏览文章结尾)。而在该装饰器中,外围嵌套了名为main-decorator(在CommonScreens.xml中)的主装饰器,负责页面的主体装饰。内层嵌套了名为FindScreenDecorator的装饰器,该装饰器主要分为两部分:search-options(搜索选项)和search-results(搜索结果)。在这两部分中分别布置一个搜索表单和列表表单。

5、创建表单。在learning/widget/learningForms.xml中,添加name= FindProductPlan和name=ListProductPlan的表单:

    <form name="FindProductPlan" type="single" target="FindProductPlan" title="" default-map-name="ProductPlan"
        header-row-style="header-row" default-table-style="basic-table">
        <field name="productPlanId" title=""><text-find/></field>
        <field name="itemId"><text-find/></field>
        <field name="principleId"><text-find/></field>
        <field name="submitButton" title="${uiLabelMap.CommonFind}">
            <submit button-type="button"/>
        </field>
    </form>
    <!-- !!!一定要注意list-name必须是listIt -->
    <form name="ListProductPlan" type="list" list-name="listIt"
          paginate-target="FindProductPlan" default-entity-name="ProductPlan" 
          odd-row-style="alternate-row" default-table-style="basic-table hover-bar"> 
        <actions>
            <set field="noConditionFind" value="Y"/>
            <service service-name="performFind" result-map="result" result-map-list="listIt">
                <field-map field-name="inputFields" from-field="parameters"/>
                <field-map field-name="entityName" value="ProductPlan"/>
            </service>
        </actions>
        <field name="productPlanId" widget-style="buttontext" title="生产计划编号">
            <hyperlink description="${productPlanId}" target="ViewProductPlan">
                <!-- 设定传递参数(parameter)的名字 -->
                <parameter param-name="productPlanId"/>
            </hyperlink>
        </field>
        <field name="itemId" title="项目编号"><display/></field>
        <field name="principleId" title="负责人编号"><display/></field>
        <field name="useProject" title="应用工程"><display/></field>  
        <!--type="date"表示只显示日期-->   
        <field name="startTime" title="开始日期"><display type="date"/></field>
        <field name="finishTime" title="结束日期"><display type="date"/></field>
        <field name="createdStamp" title="创建时间"><display/></field>
        <field name="deleteLink" title=" " widget-style="buttontext">
            <hyperlink target="RemoveProductPlan" description="${uiLabelMap.CommonDelete}" also-hidden="false">
                <parameter param-name="productPlanId"/>
            </hyperlink>
        </field>
    </form>

  关于表单的配置规则一样可以参考上述那个文档。同时,也要注意几个关键点:target属性相当于一个请求,当表单进行提交的时候,会定向到该请求上,如【1】target="FindProductPlan"对应请求转到learning/control/FindProductPlan;【2】<hyperlink>标签相当于一个超链接;【3】在ListProductPlan表单的<actions>预处理动作中,调用了ofbiz自带的查找服务performFind,使用该功能时一定要指明entity实体引擎即数据表的名字,同时使用该功能的<form>必须是type="list",且list-name必须是listIt(因为performFind服务返回的就是一个name=listIt列表);【4】第二个表单中的几个target使用了,现在还未定义的请求映射,可以置之不理或删除即可。

6、创建菜单。在learning/widget/learningMenus.xml文件的名为MainAppBar<menu>标签中,添加:

<menu-item name="ProductPlan" title="生产计划"><link target="FindProductPlan"/></menu-item>

四、部署实体

1、在learning/entitydef/entitymodel.xml中,添加entity实体(即数据库表):

<entity entity-name="ProductPlan" package-name="">
      <field name="productPlanId" type="id"/>
      <field name="itemId" type="id"/>
      <field name="startTime" type="date-time"/>
      <field name="finishTime" type="date-time"/>
      <field name="principleId" type="id-vlong"></field>
      <field name="division" type="long-varchar"></field>
      <field name="useProject" type="description"></field>
      <field name="stageIdenf" type="description"></field>
      <field name="tecnoDemand" type="description"></field>
      <field name="preparationId" type="id-vlong"></field>
      <field name="designDemand" type="id-vlong"></field>
      <field name="product" type="id-vlong"></field>
      <field name="outCheck" type="id-vlong"></field>
      <field name="documentPrepa" type="id-vlong"></field>
      <field name="armyCheck" type="id-vlong"></field>
      <field name="outJudge" type="id-vlong"></field>
      <field name="sureCompile" type="short-varchar"></field>
      <field name="sureJudge" type="short-varchar"></field>
      <field name="sureApprove" type="short-varchar"></field>
      <field name="date" type="date-time"></field>
      <field name="departmentId" type="id"></field>
      <prim-key field="productPlanId"/>
      <relation type="one" fk-name="ProductPlan_Item" rel-entity-name="ProductPlanItem">
        <key-map field-name="itemId" rel-field-name="id"/>
      </relation>
      <relation type="one" fk-name="ProductPlan_Person" rel-entity-name="ProductPlanPerson">
        <key-map field-name="principleId" rel-field-name="id"/>
      </relation>
      <relation type="one" fk-name="ProductPlan_Pre" rel-entity-name="ProductPlanPreparation">
        <key-map field-name="preparationId" rel-field-name="id"/>
      </relation>
    </entity>

    <entity entity-name="ProductPlanItem" package-name="">
        <field name="id" type="id"/>
        <field name="name" type="name"/>
        <field name="category" type="description"/>
        <field name="secretLevel" type="description"/>
        <field name="source" type="description"/>
        <field name="content" type="description"/>
        <prim-key field="id"/>
    </entity>
    
    <entity entity-name="ProductPlanPerson" package-name="">
        <field name="id" type="id"/>
        <field name="name" type="name"/>
        <field name="department" type="name"></field>
        <field name="phone" type="tel-number"/>
        <field name="address" type="description"/>
        <prim-key field="id"/>
    </entity>
    
    <entity entity-name="ProductPlanPlan" package-name="">
        <field name="id" type="id"/>
        <field name="content" type="description"/>
        <field name="startTime" type="date-time"/>
        <field name="finishTime" type="date-time"/>
        <field name="department" type="name"/>
        <field name="principleId" type="id"/>
        <prim-key field="id"/>
        <relation type="one" fk-name="Product_Plan_Person" rel-entity-name="ProductPlanPerson">
            <key-map field-name="principleId" rel-field-name="id"/>
        </relation>
    </entity>
    
    <entity entity-name="ProductPlanPreparation" package-name="">
        <field name="id" type="id"/>
        <field name="category" type="description"/>
        <field name="materialName" type="name"/>
        <field name="applyFinishTime" type="date-time"/>
        <field name="applyPrincipleId" type="id"/>
        <field name="processFinishTime" type="date-time"/>
        <field name="processPrincipleId" type="id"/>
        <field name="inCheckFinishTime" type="date-time"/>
        <field name="inCheckPrincipleId" type="id"/>
        <prim-key field="id"/>
        <relation type="one" fk-name="Product_Pre_Person1" rel-entity-name="ProductPlanPerson">
            <key-map field-name="applyPrincipleId" rel-field-name="id"/>
        </relation>
        <relation type="one" fk-name="Product_Pre_Person2" rel-entity-name="ProductPlanPerson">
            <key-map field-name="processPrincipleId" rel-field-name="id"/>
        </relation>
        <relation type="one" fk-name="Product_Pre_Person3" rel-entity-name="ProductPlanPerson">
            <key-map field-name="inCheckPrincipleId" rel-field-name="id"/>
        </relation>
    </entity>

  实体配置规则同样参照上述文档,此处不再复述。

2、利用相应的操作mysql数据库工具,对ProductPlan数据表新增一些数据。

五、小有成就

启动ofbiz,进入learning应用,点击菜单中的生产计划,即可看到FindProductPlan界面:

ofbiz.PNG

  在搜索选项中输入数据项,点击查找,便可出现相应的搜索结果,查找功能暂且完成。但这仅仅是个小小的成果,还有View展示详细数据、Create新建数据、Remove删除数据、Edit修改数据等功能需要我们去实现。路漫漫其修远兮,吾将上下而求索···

六、实现View功能

1、由于ProductPlan数据表有很多字段,所以我们需要一个ViewProductPlan页面显示某一个数据项的详细信息。展现一个页面的基本步骤,可以参照本文第三部分:【1】配置control.xml文件,将请求映射到视图,再由视图映射到具体的装饰器(screen);【2】在装饰器xml配置文件中,通过该装饰器对视图进行布置,同时还要调用表单;【3】在表单xml配置文件中,完成被调用表单的配置。

(PS:如果数据库表字段不多,仅通过上述FindProductPlan界面就能完全显示,那可以不需要View功能。)

2、代码如下:

(1)control.xml:

<request-map uri="ViewProductPlan">
        <security https="true" auth="true" />
        <response name="success" type="view" value="ViewProductPlan" />
    </request-map>

<view-map name="ViewProductPlan" type="screen" page="component://learning/widget/learningScreens.xml#ViewProductPlan"/>

(2)learningScreens.xml:

<screen name="ViewProductPlan">
        <section>
            <actions>
                <!-- 接受list表单传进来的parameter参数 -->
                <set field="ProductPlanId" from-field="parameters.ProductPlanId"/>
                <!-- 以下这句话非常关键? -->
                <entity-one entity-name="ProductPlan" value-field="ProductPlan"/>
            </actions>
            <widgets>
                <decorator-screen name="CommonRoutingDecorator" location="component://manufacturing/widget/manufacturing/RoutingScreens.xml">
                    <decorator-section name="body">
                        <screenlet title="生产计划表">
                            <container style="button-bar">
                                <link target="FindProductPlan" text="返回" style="buttontext"/>
                            </container>
                            <include-form name="ViewProductPlan" location="component://learning/widget/learningForms.xml"></include-form>
                        </screenlet>
                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>

  表单的actions预处理动作,保证了显示表单中的数据项是传进来的ProductPlanId的数据项(虽然笔者也不知为何?)。

(3)learningForms.xml:

<form name="ViewProductPlan" type="single" target="EditProductPlan" title="" default-map-name="ProductPlan">
        <field name="productPlanId" tooltip="" title="" position="1"><text/></field>
        <field name="itemId" position="2"><lookup target-form-name="LookupProductPlanItem" size="16"/></field>
        <field name="startTime" position="1"><text type="date"/></field>
        <field name="finishTime" position="2"><text type="date"/></field>
        <field name="principleId"><lookup target-form-name="LookupProductPlanPerson" size="16"/></field>
        <field name="division" position="2"><text/></field>
        <field name="useProject"><text/></field>
        <field name="stageIdenf" position="2"><text/></field>
        <field name="tecnoDemand"><text/></field>
        <field name="preparationId" position="2"><lookup target-form-name="LookupProductPlanPreparation" size="16"/></field>
        <field name="designDemand"><text/></field>
        <field name="product" position="2"><text/></field>
        <field name="outCheck"><text/></field>
        <field name="documentPrepa" position="2"><text/></field>
        <field name="armyCheck"><text/></field>
        <field name="outJudge" position="2"><text/></field>
        <field name="sureCompile"><text/></field>
        <field name="sureJudge" position="2"><text/></field>
        <field name="sureApprove"><text/></field>
        <field name="departmentId" position="2"><text/></field>
        <field name="submitButton" title="修改">
            <submit button-type="button"/>
        </field>
    </form>

  在该表中,有几个要点:【1】<field>的属性position="2"是表示该数据项的左右位置(默认是1),但相邻的数据项之间不能都等于2(此处玄学,笔者不甚了解);【2】<text type="date"/>表示该数据项只显示日期;【3】<lookup target-form-name="LookupProductPlanItem" size="16"/>是数据项的一种可以提供便捷查找功能的格式,其属性target对应一个请求(control/LookupProductPlanItem),说明我们还要创建一个请求以及响应视图才能使用这个功能。

(4)创建Lookup请求,在controller.xml中添加:

    <request-map uri="LookupProductPlanItem">
        <security https="true" auth="true" />
        <response name="success" type="view" value="LookupProductPlanItem" />
    </request-map>

    <view-map name="LookupProductPlanItem" type="screen" page="component://learning/widget/LearningScreens.xml#LookupProductPlanItem"/>

(5)创建Lookup视图,在LearningScreens.xml中添加:

    <screen name="LookupProductPlanItem">
        <section>
            <condition>
                <if-service-permission service-name="catalogPermissionCheck" main-action="VIEW"/>
            </condition>
            <actions>
                <set field="title" value="查找项目"/>
                <set field="queryString" from-field="result.queryString"/>
                
                <set field="entityName" value="ProductPlanItem"/>
                <set field="searchFields" value="[id, name, category, secretLevel]"/>
            </actions>
            <widgets>
                <decorator-screen name="LookupDecorator" location="component://common/widget/CommonScreens.xml">
                    <decorator-section name="search-options">
                        <include-form name="FindProductPlanItem" location="component://learning/widget/LearningForms.xml"/>
                    </decorator-section>
                    <decorator-section name="search-results">
                        <include-form name="ListProductPlanItem" location="component://learning/widget/LearningForms.xml"/>
                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>

  <actions>中的第三个<set>标签是指定具体数据库表;第四个是用来,在调用该Lookup功能的数据项旁,显示value中字段数据的。

(6)创建Form表单,在LearningForms.xml中添加:

    <form name="FindProductPlanItem" type="single" target="LookupProductPlanItem" title="" default-map-name="ProductPlanItem"
        header-row-style="header-row" default-table-style="basic-table">
        <field name="id" title=""><text-find/></field>
        <field name="name"><text-find/></field>
        <field name="category"><text-find/></field>
        <field name="submitButton" title="${uiLabelMap.CommonFind}">
            <submit button-type="button"/>
        </field>
    </form>
    
    <!-- !!!一定要注意list-name必须是listIt -->
    <form name="ListProductPlanItem" type="list" list-name="listIt"
          paginate-target="LookupProductPlanItem" default-entity-name="ProductPlanItem" 
          odd-row-style="alternate-row"> 
        <actions>
            <set field="noConditionFind" value="Y"/>
            <service service-name="performFind" result-map="result" result-map-list="listIt">
                <field-map field-name="inputFields" from-field="parameters"/>
                <field-map field-name="entityName" value="ProductPlanItem"/>
            </service>
        </actions>
        <!-- 以下是点击id后退出,并将点击的id显示id框中 -->
        <field name="id" widget-style="smallSubmit">
            <hyperlink also-hidden="false" target-type="plain" description="${id}" target="javascript:set_value('${id}')"/>
        </field>
        <field name="name"><display/></field>
        <field name="category"><display/></field>
        <field name="secretLevel"><display/></field>
        <field name="source"><display/></field>
        <field name="content"><display/></field>
    </form>

(7)完工的ViewProductPlan视图

ofbiz2.PNG

七、实现Create以及Update功能

1、在我们完成的第一张视图中,有一个“新增”按钮,它对应第三—4步的ProductPlan装饰器中的:

<container style="button-bar">
    <link target="EditProductPlan" text="新建" style="buttontext create"/>
</container>

  同时在完成的第二张视图中,有一个“修改”按钮,它对应第六—3步中的ViewProductPlan表单中的:

<field name="submitButton" title="修改">
    <submit button-type="button"/>
</field>

  这两个按钮都指向EditProductPlan请求(表单ViewProductPlan的target属性为EditProductPlan),因此,我们又得如出一辙地部署一个EditProductPlan请求和响应视图,重复性工作,直接上代码:

(1)controller.xml:

<request-map uri="EditProductPlan">
    <security https="true" auth="true" />
    <response name="success" type="view" value="EditProductPlan" />
</request-map>

<view-map name="EditProductPlan" type="screen" page="component://learning/widget/learningScreens.xml#EditProductPlan"/>

(2)learningScreens.xml:

    <screen name="EditProductPlan">
        <section>
            <actions>
                <set field="ProductPlanId" from-field="parameters.ProductPlanId"/>
                <entity-one entity-name="ProductPlan" value-field="ProductPlan"/>
            </actions>
            <widgets>
                <decorator-screen name="CommonRoutingDecorator" location="component://manufacturing/widget/manufacturing/RoutingScreens.xml">
                    <decorator-section name="body">
                        <screenlet title="生产计划表">
                            <container style="button-bar">
                                <link target="FindProductPlan" text="返回" style="buttontext"/>
                            </container>
                            <include-form name="EditProductPlan" location="component://learning/widget/learningForms.xml"></include-form>
                        </screenlet>
                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>

(3)learningForms.xml:

    <form name="EditProductPlan" type="single" target="UpdateProductPlan" title="" default-map-name="ProductPlan">
        <!-- 以下是当表单为空时,将请求交给Create -->
        <alt-target use-when="ProductPlan==null" target="CreateProductPlan" />
        <field name="productPlanId" title="" tooltip="*"  widget-style="required"><text/></field>
        <field name="itemId" tooltip="*"  widget-style="required"><lookup target-form-name="LookupProductPlanItem" size="16"/></field>
        <field name="principleId" tooltip="*"  widget-style="required"><lookup target-form-name="LookupProductPlanPerson" size="16"/></field>
        <field name="preparationId"><lookup target-form-name="LookupProductPlanPreparation" size="16"/></field>
        <field name="useProject"><text/></field>
        <field name="startTime"><date-time type="date"/></field>
        <field name="finishTime"><date-time type="date"/></field>
        <field name="submitButton" title="提交">
            <submit button-type="button"/>
        </field>
    </form>

2、当EditProductPlan表单完成后,会提交到CreateProductPlan或UpdateProductPlan请求,而这取决于表单一开始是否为空,例如新建时表单为空提交给CreateProductPlan。由于此处涉及到对数据库的增加和更新,则需要调用services服务,笔者在此使用java实现该服务。

(1)调用服务的第一步是要在learning/servicedef/services.xml文件中声明该服务:

<?xml version="1.0" encoding="UTF-8"?>
<services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/services.xsd">
    <description>learning Services</description>
    <vendor></vendor>
    <version>1.0</version>
    
    <service name="createProductPlan" engine="java" auth="true"
            location="org.ofbiz.learning.ProductPlanServices" invoke="createProductPlan">
        <description>Create a ProductPlan</description>
        <attribute name="productPlanId" type="String" mode="IN" optional="true" />
        <attribute name="itemId" type="String" mode="IN" optional="true" />
        <attribute name="principleId" type="String" mode="IN" optional="true" />
        <attribute name="preparationId" type="String" mode="IN" optional="true" />
        <attribute name="useProject" type="String" mode="IN" optional="true" />
        <attribute name="startTime" type="java.sql.Timestamp" mode="IN" optional="true" />
        <attribute name="finishTime" type="java.sql.Timestamp" mode="IN" optional="true"/>
    </service>
    
    <service name="updateProductPlan" engine="java" auth="true"
            location="org.ofbiz.learning.ProductPlanServices" invoke="updateProductPlan">
        <description>Update a ProductPlan</description>
        <attribute name="productPlanId" type="String" mode="IN" optional="true" />
        <attribute name="itemId" type="String" mode="IN" optional="true" />
        <attribute name="principleId" type="String" mode="IN" optional="true" />
        <attribute name="preparationId" type="String" mode="IN" optional="true" />
        <attribute name="useProject" type="String" mode="IN" optional="true" />
        <attribute name="startTime" type="java.sql.Timestamp" mode="IN" optional="true" />
        <attribute name="finishTime" type="java.sql.Timestamp" mode="IN" optional="true"/>
    </service>
    
</services>

  <sevice>标签中,name是该服务的名字,engine是服务的实现方式,location指向java类的位置,invoke指向该java类中的一个方法(函数)。<attribute>标签中,name是传进该方法中的数据项的名字,type是该数据项的类型,mode="IN"表示传进,"OUT"表示传出。

(2)实现该java类及方法。在learning/src下,创建org/ofbiz/learning/目录,并在该目录下创建一个名为ProductPlanServices的java类:

package org.ofbiz.learning;

import java.sql.Timestamp;
import java.util.Locale;
import java.util.Map;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.ServiceUtil;

public class ProductPlanServices {  
    public static final String module   = ProductPlanServices.class.getName();  
    public static final String resource = "ProductPlanUiLabels";  
      
    /** 
     * create xpp Learn 
     * @param dctx 
     * @param context 
     * @return 
     */  
    public static Map<String, Object> createProductPlan(DispatchContext dctx, Map<String, ? extends Object> context) 
    {  
        //获取用户信息
        Locale locale = (Locale) context.get("locale");
        //获取返回的Map类
        Map<String, Object> result = ServiceUtil.returnSuccess();  
        //获取数据库操作类
        Delegator delegator = dctx.getDelegator();  
        
        //获取传进来的数据项
        String productPlanId = (String) context.get("productPlanId");
        String itemId = (String) context.get("itemId");
        String principleId = (String) context.get("principleId");
        String preparationId = (String) context.get("preparationId");
        String useProject = (String) context.get("useProject");
        Timestamp startTime = (Timestamp) context.get("startTime");
        Timestamp finishTime = (Timestamp) context.get("finishTime");
        
        //将这些数据项放进一个Map类对象中
        Map<String, Object> ProductPlanMap = UtilMisc.toMap("productPlanId", productPlanId,"itemId",itemId,"principleId",principleId);
        ProductPlanMap.put("preparationId", preparationId);
        ProductPlanMap.put("useProject", useProject);
        ProductPlanMap.put("startTime", startTime);
        ProductPlanMap.put("finishTime", finishTime);
        
        //将Map类放入一个名为ProductPlan的数据表中,GenericValue类的对象相当于数据表中的一条记录
        GenericValue GV = delegator.makeValue("ProductPlan", ProductPlanMap);    
        try { 
            //创建这条记录
            GV.create(); }  
        catch (GenericEntityException e) {  
            Debug.logError(e, e.getMessage(), module);  
            return ServiceUtil.returnError(UtilProperties.getMessage(resource,  
                    "Learn.create.error", new Object[] { e.getMessage() }, locale));  
        }  
        return result;  
    }  
      
     /** 
     * update Learn xpp 
     * @param dctx 
     * @param context 
     * @return 
     */  
    public static Map<String, Object> updateProductPlan(DispatchContext dctx,Map<String, ? extends Object> context) 
    {  
        Locale locale = (Locale) context.get("locale");  
        Map<String, Object> result = ServiceUtil.returnSuccess();  
        Delegator delegator = dctx.getDelegator();  
        
        //获取传进的数据项
        String productPlanId = (String) context.get("productPlanId");
        String itemId = (String) context.get("itemId");
        String principleId = (String) context.get("principleId");
        String preparationId = (String) context.get("preparationId");
        String useProject = (String) context.get("useProject");
        Timestamp startTime = (Timestamp) context.get("startTime");
        Timestamp finishTime = (Timestamp) context.get("finishTime");
        
        //将id放进一个Map中
        Map<String, Object> ProductPlanMap = UtilMisc.toMap("productPlanId", productPlanId);
          
        try {  
            //通过该Map对象即ProductPlanId,寻找与该id相同的数据表中的记录
            GenericValue GV = delegator.findOne("ProductPlan", ProductPlanMap , false);  
            //如果找不到这条记录就报错
            if(UtilValidate.isEmpty(GV))
            {  
                return ServiceUtil.returnError(UtilProperties.getMessage(resource,"ProductPlan.update.error.entity.notFound", locale));  
            } 
            //如果找到了,就把传进来的数据放到该记录中
            GV.put("itemId", itemId);
            GV.put("principleId", principleId);
            GV.put("preparationId", preparationId);
            GV.put("useProject", useProject);
            GV.put("startTime", startTime);
            GV.put("finishTime", finishTime);  
            //更新该记录
            GV.store();  
        }catch (GenericEntityException e) {  
            Debug.logError(e, e.getMessage(), module);  
            return ServiceUtil.returnError(UtilProperties.getMessage(resource,  
                    "Learn.update.error", new Object[] { e.getMessage() }, locale));  
        }  
        return result;  
    }  
}  

  以上只是一个简单的操作数据库的java类,部分内容的讲解已经在该类的注释中,如果想更好地了解service服务,可以参考Apache+OFBiz+开发初学者指南.chm和ofbiz菜鸟笔记.doc。

(3)编写完类和方法后,接下来的工作非常重要:

【1】检查learning/ofbiz-component.xml中有没有以下代码:
<classpath type="jar" location="build/lib/*"/>

<service-resource type="model" loader="main" location="servicedef/services.xml"/>
【2】检查controller.xml中有没有以下代码:
<include location="component://common/webcommon/WEB-INF/common-controller.xml"/>
【3】当然,如果你是用笔者第二步提供的方法来创建learning组件,那么你可以不必检查。

(4)重中之重,右键learning/src—选择构建路径—选择做源文件夹。

(5)泰山之重,右键learning/build.xml文件—选择运行方式(Run as)—选择第二个Ant 构建—进入编辑配置界面—在目标界面选择jar(一般默认就已经选择)—点击运行,运行完成后检查learning/build下是不是有东西了(文件夹不算)。

3、在controller.xml添加:

    <request-map uri="CreateProductPlan">
        <security https="true" auth="true"/>
        <event type="service" invoke="createProductPlan"/>
        <response name="success" type="view" value="EditProductPlan"/>
        <response name="error" type="view" value="EditProductPlan"/>
    </request-map>
    <request-map uri="UpdateProductPlan">
        <security https="true" auth="true"/>
        <event type="service" invoke="updateProductPlan"/>
        <response name="success" type="view" value="EditProductPlan"/>
        <response name="error" type="view" value="EditProductPlan"/>
    </request-map>

  注意请求映射中多了一个event映射,表明该请求会调用该服务(invoke对应services.xml中声明的服务),通过该服务后才到达视图部分,而映射的视图此前已经创建完成了。

4、到此,Create以及Update功能已经完成,但增删改查还差了删除功能,不过这已经是手到擒来的了。

八、Remove功能

1、通过第七步,我们可以知道,涉及数据库操作功能时,我们不需要新建视图,只需要让该请求通过event进入服务,然后返回到已有视图即可,所以在controller.xml中,我们只需要添加:

    <request-map uri="RemoveProductPlan">
        <security https="true" auth="true"/>
        <event type="service" invoke="removeProductPlan"/>
        <response name="success" type="view" value="FindProductPlan"/>
        <response name="error" type="view" value="FindProductPlan"/>
    </request-map>

2、然后在services.xml中添加:

    <service name="removeProductPlan" engine="java" auth="true"
            location="org.ofbiz.learning.ProductPlanServices" invoke="removeProductPlan">
        <description>Remove a ProductPlan</description>
        <attribute name="productPlanId" type="String" mode="IN" optional="true" />
    </service>

  由于删除的时候只需要知道id号,因此传进id号即可。

3、在ProductPlanServices类中添加一个删除方法:

public static Map<String, Object> removeProductPlan(DispatchContext dctx,  
            Map<String, ? extends Object> context) {  
        Locale locale = (Locale) context.get("locale");  
        Map<String, Object> result = ServiceUtil.returnSuccess();  
        Delegator delegator = dctx.getDelegator();  
          
        String productPlanId = (String) context.get("productPlanId"); 
        
        try {  
            GenericValue gv = delegator.findOne("ProductPlan", UtilMisc.toMap("productPlanId", productPlanId),false);  
            if(UtilValidate.isEmpty(gv)){  
                return ServiceUtil.returnError(UtilProperties.getMessage(resource,"Learn.delete.error.entity.notFound", locale));  
            }  
            gv.remove();  
        }catch (GenericEntityException e) {  
            Debug.logError(e, e.getMessage(), module);  
            return ServiceUtil.returnError(UtilProperties.getMessage(resource,  
                    "Learn.delete.error", new Object[] { e.getMessage() }, locale));  
        }  
        return result;  
    }

4、最后,不要忘记通过build.xml对该类进行编译。另外,当对services.xml文件或java类进行修改后,要停止ofbiz再启动,否则修改无效。那如何停止ofbiz呢?右键ofbiz根目录下的build.xml,第二个Ant构建再选择stop,运行后ofbiz即停止。如果你能找到Eclipse的Ant视图,那就更方便了,但使用方法就要靠自己领悟了。

结语(本文结束的几个月后所添加的)

1.此处推荐一位ofbiz大神博客:上海香飘飘,博客中不仅有关于ofbiz的知识,有很多资源链接,读者可以下载阅读。其中就包括入门级指南Apache+OFBiz+开发初学者指南[Ob4.0-EN+Ob9.0-CN].chm。这份指南很全,若能认真反复阅读,必能获益匪浅。

2.随着笔者对ofbiz的研究时间日益长久,又有一番心得,包括如下几点:

上一篇 下一篇

猜你喜欢

热点阅读