(tng) Ofbiz(http://www.ofbiz.org) ?Open Source 的商务Y件系l,充分利用?jin)各优秀的的Open Source 目Q?br />?Tomcat, Ant, BeanShell, Jboss {,构徏?jin)一个强大的pȝq_QOfbiz 已经完成?jin)大部分商务cY件系l?br />都需要的部gQ像用户认证、工作流、商务规则处理等QOfbiz 的核?j)技术在?Entity EngineQ其他的lg基本?br />是基于它的。简单来?Entity Engine 的主要功能是数据库表创建、对象与数据表的映射、对象的查询{做?jin)强?br />装Q你可以在一个简单的 XML 文g中定义数据库表结构,Ofbiz ?x)自动帮你在数据库徏表,q动态生成映对象,
你在E序中可以只考虑?Object 的处理,Ofbiz ?x)自动通过事务逻辑更新到数据库中。Ofbiz 宣称的优点之一是用
很少?Code 完成复杂的处理?
2.Ofbiz 下蝲与安?/p>
(tng) 首先要安?J2SDK1.4Q到 http://java.sun.com 上下载,安装后设?JAVA_HOME 环境变量?J2SDK 的安装目录?/p>
(tng) 讉K|站 http://www.ofbiz.orgQ上面有下蝲的连接,请选择 Complete 包,因ؓ(f)q个包中已经包含?jin)运?Ofbiz
的所有东西,下蝲下来解开后就可以q行?jin)?/p>
(tng) 解开 Ofbiz 包到一个目录下Q假设是 “C:\ofbiz”,该目录下会(x)?catalina ?ofbiz 两个目录Q?catalina
目录?Tomcat 的目录,Ofbiz 对其配置做了(jin)修改Qofbiz 目录?Ofbiz 的程序代码目录。在命o(h)行状态下q入
“c:\ofbiz\catalina\bin?目录Q运行?ofbiz run”命令,可以启?OfbizQ启动后你可以用览器访?
“http://localhost:8080/ecommerce”,q可以访?Ofbiz 的电(sh)子商务模块,通过面上面的连接你可以讉K?br />其他模块?/p>
3.Ofbiz Schema 的创?
Ofbiz 应用入门Q?/p>
(tng) 以一个实例说明,假设我们需要徏一个客戯料表Qv名ؓ(f) StudyCustomerQ各个段分别如下Q?br /> (tng) StudyCustomer {
(tng) (tng) (tng) customerId (tng) (tng) (tng) (tng) (tng) Integer,
(tng) (tng) (tng) customerName (tng) (tng) (tng) String,
(tng) (tng) (tng) customerNote (tng) (tng) (tng) String,
(tng) }
(tng) 我们来实现基本的数据操作---???查询Q具体步骤如下:(x)
(tng) 1.?XML 文g中定义数?SchemaQ?br /> (tng) (tng) (tng) 需要用C个文Ӟ一个是我们要徏的项目的 entitymodel_xxx.xml ?entityengine.xmlQ还?br /> (tng) (tng) (tng) entitygroup.xml,
(tng) (tng) (tng) entitymodel_xxx.xml 是需要我们自己创建的Q假设我们v名ؓ(f) entitymodel_study.xmlQ放?
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) “c:\ofbiz\ofbiz\commonapp\entitydef”目录下Q?br /> (tng) (tng) (tng) entityengine.xml ?Ofbiz 已经有的Q放?“c:\ofbiz\commonapp\etc”目录下Q用来包含我?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 定义?entitymodel 文g?br /> (tng) (tng) (tng) entitygroup.xml (tng) 也是 Ofbiz 已经有的Q跟 engityengine.xml 在同一目录下,我们需要把我们?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Schema 定义加入到该文g?/p>
(tng) (tng) (tng) entitymodel_study.xml 文g的定义格式如下:(x)
<!--================================================================================-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE entitymodel PUBLIC "-//OFBiz//DTD Entity Model//EN"
"http://www.ofbiz.org/dtds/entitymodel.dtd">
<entitymodel>
(tng) (tng) <title>Entity of an Open For Business Project Component</title>
(tng) (tng) <description>None</description>
(tng) (tng) <copyright>Copyright (c) 2002 The Open For Business Project - www.ofbiz.org</copyright>
(tng) (tng) <author>None</author>
(tng) (tng) <version>1.0</version>
(tng) <!-- ========================================================= -->
(tng) <!-- ======================== Data Model ===================== -->
(tng) <!-- The modules in this file are as follows: (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) -->
(tng) <!-- (tng) - org.ofbiz.commonapp.study -->
(tng) <!-- ========================================================= -->
(tng) <!-- ========================================================= -->
(tng) <!-- org.ofbiz.commonapp.study -->
(tng) <!-- ========================================================= -->
(tng) (tng) <entity entity-name="StudyCustomer"
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) package-name="org.ofbiz.commonapp.study"
(tng) (tng) title="Study Customer Entity">
(tng)<field name="customerId" type="id-ne"></field>
(tng)<field name="customerName" type="long-varchar"></field>
(tng)<field name="customerNote" type="long-varchar"></field>
(tng)<prim-key field="customerId"/>
(tng) </entity>
(tng)</entitymodel>
<!--================================================================================-->
(tng) q个 XML 文g中的 Tag 基本是看得明白的Q只?field ?type ?Ofbiz 已经预定义好的,q?br />是ؓ(f)?jin)保证数据库间的q移?/p>
(tng) ?entityengine.xml 加入我们刚才定义的文Ӟ加入一行在合适的位置Q?br /> (tng) (tng) <resource loader="mainfile" location="entitymodel_study.xml"/>
(tng) 具体攄位置我们可以通过查看 entityengine.xml 扑ֈQ里面已l有加好的其他文件?/p>
(tng) ?entitygroup.xml 加入我们?Schema 定义Q在后面加入一?br /> (tng) (tng) <entity-group group="org.ofbiz.commonapp" entity="StudyCustomer" />
(tng) q样我们定义好?SchemaQ现在把 c:\ofbiz\commonapp\etc\entityengine.xml 拯?br /> (tng) c:\ofbiz\catalina\shared\classes 目录下,q点要切讎ͼ我以前就因ؓ(f)没有拯Q最?Schema
(tng) 怎么也创Z?jin)?/p>
(tng) 重新启动 OfbizQ访?URL: http://localhost:8080/webtoolsQ点d上方?"Login" 链接Q?br /> (tng) ?admin/ofbiz dQ登录进入后选择链接“Check/Update Database”,q时?x)出?Check ?FormQ?br /> (tng) 该表单可以只(g)?Schema 是否改变Q默认的 GroupName 是“org.ofbiz.commonapp”,q个不需要变Q?br /> (tng) 点击“Check Only”按钮,Ofbiz ?x)检验变动情况,昄Z个完整的列表Q你可以查一下是否有我们刚徏?br /> (tng) "StudyCustomer"Q如果没有,可能是我们前面定义的有些问题Q检查一下再重新做?/p>
(tng) 在检查到以后Q可以再选择“Check and Add Missing”,q是 Ofbiz 很强大的一个功能,你在 XML 中新
(tng) 增了(jin)表,或在某个表中新增?jin)段Q它?x)自动映到数据库中Q避免我们去直接操作数据库?/p>
(tng) 现在已经完成?StudyCustomer Schema 的创?如果x(chng)验一下是否有表创建,我们可以用编辑器打开
(tng) c:\ofbiz\data\ofbiz.script Q在里面查询 CREATE TABLE StudyCustomer 的字P如果前面没有
(tng) 问题Q我们可以找到的?/p>
(tng)
4.如何使用已经定义?Schema
如何使用已经定义?Schema
(tng) (tng) Ofbiz 遵@ MVC 的设计模式,?View 端,?JSP 端主要?Ofbiz 定义?Tag 来显C或
(tng) (tng) 提取数据QControl 是一?Controller ServletQ我们在 Controller Servlet ?URI mapping
(tng) (tng) 配置文g中定义各 URL 应该指向什么程序,q样Q通过q个 mapping 配置文gQ可以保证我们各个页?br /> (tng) (tng) ?qing)具体处理程序之间的独立性,例我们可以通过修改q个配置文g可以改变某?Form ?Post Action
(tng) (tng) ?URLQ而不需要修改实际的 HTML ?JSP 代码?/p>
(tng) (tng) Ofbiz 中定义了(jin) Regions 的概念,卛_一?HTML 面分成几个区域Q像 Top, Left, Right, Main
(tng) (tng) {,通过q些 Regions 我们可以方便的组?UI 界面Qƈ且可以方便改变各部分所处的位置Q如我们可以
(tng) (tng) 把菜单很Ҏ(gu)的从上方Ud下方Q只需要改变(sh)个配|文件。Regions cM?HTML 中的 FrameQ但它是
(tng) (tng) 通过一个页面来l合界面QFrame 是通过几个面昄在不同的帧中QFrame 的控制比较复杂,而且需?br /> (tng) (tng) 改变相关的程序?/p>
(tng) (tng) ?Ofbiz 中,我们可以直接?JSP 中操?Schema 定义?ObjectQ即我们刚定义的 StudyCustomerQ?br /> (tng) (tng) CZ如下Q?/p>
<%@ taglib uri="ofbizTags" prefix="ofbiz" %>
<%@ page import="java.util.*" %>
<%@ page import="org.ofbiz.core.util.*, org.ofbiz.core.pseudotag.*" %>
<%@ page import="org.ofbiz.core.entity.*" %>
<jsp:useBean id="delegator" type="org.ofbiz.core.entity.GenericDelegator" scope="request" />
<jsp:useBean id="security" type="org.ofbiz.core.security.Security" scope="request" />
<%if(security.hasEntityPermission("PARTYMGR", "_VIEW", session)) {%>
<%
(tng) try {
(tng) (tng) (tng) delegator.create("StudyCustomer",
(tng) (tng) (tng) (tng) (tng) UtilMisc.toMap("customerId","1","customerName","Cust1","customerNote","Customer Note 1"));
(tng) (tng) (tng) Iterator custs = (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)
UtilMisc.toIterator(delegator.findAll("StudyCustomer",UtilMisc.toList("customerId","customerName","customerNote")));
(tng) (tng) (tng) while(custs.hasNext())
(tng) (tng) (tng) {
(tng)GenericValue cust = (GenericValue)custs.next();
(tng)out.println(cust.getString("customerId"));
(tng)out.println(cust.getString("customerName"));
(tng)out.println(cust.getString("customerNote"));
(tng) (tng) (tng) }
(tng) } catch(Exception e)
(tng) {
(tng) (tng) (tng) out.println(e.getMessage());
(tng) }
%>
<%}else{%>
(tng) <h3>You do not have permission to view this page. ("PARTYMGR_VIEW" or "PARTYMGR_ADMIN" needed)</h3>
<%}%>
(tng) q段E序挺容易理解,先是通过 delegator 创徏一?ObjectQ该 Object 会(x)?Ofbiz 自动同步?br />数据库中。然后通过 delegator ?findAll 取到所有已保存?ObjectQ最后通过一?Iterator 对象
昄出来?/p>
(tng) q个E序起名?testofbiz.jspQؓ(f)单v见,我们攑ֈ Ofbiz 已有的一?Webapp 的目录下Q放?br />c:\ofbiz\ofbiz\partymgr\webapp\party 目录下。然后我们需要修改两个配|文Ӟ(x)controller.xml
?regions.xmlQ这两个文g是我们上面提到?mapping ?regions 配置文g?/p>
(tng) q两个文仉在:(x)c:\ofbiz\ofbiz\partymgr\webapp\WEB-INF 下,?controller.xml 中加入下?/p>
(tng) (tng) <request-map uri="testofbiz">
(tng) (tng) (tng) (tng) (tng) <description>Test Ofbiz</description>
(tng) (tng) (tng) (tng) (tng) <security https="false" auth="false"/>
(tng) (tng) (tng) (tng) (tng) <response name="success" type="view" value="testofbiz"/>
(tng) (tng) </request-map>
(tng) ?br /> (tng) (tng) <view-map name="testofbiz" type="region"/>
(tng)
(tng) 加入位置请参?controller.xml 中已l有的配|。在 regions.xml 中加入:(x)
(tng) (tng) <define id='testofbiz' region='MAIN_REGION'>
(tng) (tng) (tng) (tng) (tng) (tng) <put section='title'>Test Ofbiz</put>
(tng) (tng) (tng) (tng) (tng) (tng) <put section='content' content='/party/testofbiz.jsp'/>
(tng) (tng) </define>
(tng) 具体加入位置请参考已有的配置?/p>
(tng) 配置完后Q重新启?ofbizQ然后访?URL:
(tng) http://localhost:8080/partymgr/control/testofbiz
(tng) ׃我们?testofbiz.jsp E序中用了(jin) Ofbiz 的安全控制机Ӟpȝ?x)提C现在没有访?br /> (tng) 权限Q需要登录,点击双的“Login??admin/ofbiz d后会(x)看到我们E序 testofbiz.jsp
(tng) 的运行结果。如果需要增加新记录Q请修改
(tng) UtilMisc.toMap("customerId","1","customerName","Cust1","customerNote","Customer Note 1"));
(tng) 中的各个D늚|然后再访?http://localhost:8080/partymgr/control/testofbizQ如果不修改
(tng) 而直接访问那?URL Ӟpȝ?x)提C?Primary key 冲突?/p>
5.按照昄与逻辑分离的原则?Schema:
(tng) 上篇讲了(jin)如何?JSP 中用创建的 Schema 对象Q这ơ我们来讲述一下如何把E序
逻辑攑ֈ JavaBeans 中,把显C处理放?JSP 中,q?controller.xml 两
部分整合h?/p>
(tng) 首先我们来创Z?JavaBeansQ来完成Add/Get/Delete/Update Schema 对象
的操作,E序文g名ؓ(f) TestOfbiz.javaQ放|在
(tng) c:\ofbiz\ofbiz\testOfbiz\com\geeyo\ofbiz 目录? 具体E序如下Q?/p>
>=================================================================
package com.geeyo.ofbiz;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.net.*;
import org.ofbiz.core.util.*;
import org.ofbiz.core.entity.*;
import org.ofbiz.core.service.*;
import org.ofbiz.core.security.*;
import org.ofbiz.core.stats.*;
public class TestOfbiz
{
(tng) public static void main(String[] args)
(tng) throws Exception
(tng) {
(tng) (tng) (tng) (tng) GenericDelegator delegator = GenericDelegator.getGenericDelegator("default");
(tng) (tng) (tng) (tng) delegator.create("StudyCustomer",UtilMisc.toMap("customerId","3","customerName","Kane3","customerNote","This is test customer.3"));
(tng) (tng) (tng) (tng) Iterator custs = UtilMisc.toIterator(delegator.findAll("StudyCustomer",UtilMisc.toList("customerId","customerName","customerNote")));
(tng) (tng) (tng) (tng) while(custs.hasNext())
(tng) (tng) (tng) (tng) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) GenericValue cust = (GenericValue)custs.next();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println(cust.getString("customerId"));
(tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println(cust.getString("customerName"));
(tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println(cust.getString("customerNote"));
(tng) (tng) (tng) (tng) }
(tng) }
(tng) public static String createNewRecord(HttpServletRequest request, HttpServletResponse response)
(tng) throws Exception
(tng) {
(tng) (tng) (tng) (tng) Map paras = UtilMisc.getParameterMap(request);
(tng) (tng) (tng) (tng) GenericDelegator delegator = GenericDelegator.getGenericDelegator("default");
(tng) (tng) (tng) (tng) delegator.create("StudyCustomer",paras);
(tng) (tng) (tng) (tng) return "success";
(tng) }
(tng) public static String lookAllRecords(HttpServletRequest request, HttpServletResponse response)
(tng) throws Exception
(tng) {
(tng) (tng) (tng) (tng) GenericDelegator delegator = GenericDelegator.getGenericDelegator("default");
(tng) (tng) (tng) (tng) Iterator custs = UtilMisc.toIterator(delegator.findAll("StudyCustomer",UtilMisc.toList("customerId","customerName","customerNote")));
(tng) (tng) (tng) (tng) Collection col = new ArrayList();
(tng) (tng) (tng) (tng) while(custs.hasNext())
(tng) (tng) (tng) (tng) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) GenericValue cust = (GenericValue)custs.next();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) col.add(cust);
(tng) (tng)
(tng) (tng) (tng) (tng) }
(tng) (tng) (tng) (tng) request.getSession().setAttribute("search_results",col);
(tng) (tng) (tng) (tng) return "success";
(tng) }
(tng) public static String findRecord(HttpServletRequest request, HttpServletResponse response)
(tng) throws Exception
(tng) {
(tng) (tng) (tng) (tng) String id = (String)request.getParameter("customerId");
(tng) (tng) (tng) (tng) GenericDelegator delegator = GenericDelegator.getGenericDelegator("default");
(tng) (tng) (tng) (tng) try {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) GenericValue cust = delegator.findByPrimaryKey("StudyCustomer",UtilMisc.toMap("customerId",id));
(tng) (tng) (tng) (tng) (tng) (tng) (tng) request.getSession().setAttribute("edit_cust",cust);
(tng) (tng) (tng) (tng) } catch (GenericEntityException gee) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) Debug.logWarning(gee);
(tng) (tng) (tng) (tng) }
(tng) (tng) (tng) (tng) return "success";
(tng) }
(tng) public static String updateRecord(HttpServletRequest request, HttpServletResponse response)
(tng) throws Exception
(tng) {
(tng) (tng) (tng) (tng) Map paras = UtilMisc.getParameterMap(request);
(tng) (tng) (tng) (tng) GenericDelegator delegator = GenericDelegator.getGenericDelegator("default");
(tng) (tng) (tng) (tng) GenericValue cust = delegator.findByPrimaryKey("StudyCustomer",UtilMisc.toMap("customerId",paras.get("customerId")));
(tng) (tng) (tng) (tng) cust.setNonPKFields(paras);
(tng) (tng) (tng) (tng) cust.store();
(tng) (tng) (tng) (tng) request.getSession().setAttribute("edit_cust",cust);
(tng) (tng) (tng) (tng) return "success";
(tng) }
(tng) public static String removeRecord(HttpServletRequest request, HttpServletResponse response)
(tng) throws Exception
(tng) {
(tng) (tng) (tng) (tng) String strId = request.getParameter("id");
(tng) (tng) (tng) (tng) GenericDelegator delegator = GenericDelegator.getGenericDelegator("default");
(tng) (tng) (tng) (tng) GenericValue cust = delegator.findByPrimaryKey("StudyCustomer",UtilMisc.toMap("customerId",strId));
(tng) (tng) (tng) (tng) cust.remove();
(tng) (tng) (tng) (tng) return "success";
(tng) }
(tng)
}
>=================================================================
E序中的处理大部分可以看懂的Q其中有个功能,?br /> (tng) Map paras = UtilMisc.getParameterMap(request);
q是 Ofbiz 的一个有但非常有用的功能,它是?request 中各D늚名字和值映到一?Map
对象中,然后使用
(tng) cust.setNonPKFields(paras);
可以赋l?Object cust 的各个段Q免?jin)我们?request.getParameter("name")来取各个
|在值很多的时候这个功能可以大大减冗余代码量?/p>
(tng) 基本E序的逻辑是这L(fng)Q?br /> (tng) 1.?request d传来的?br />?2.使用 delegator 来处理,Add/Update/Delete/Query
(tng) 3.返回结果放?Session 中传l?JSP
(tng) 我做?jin)?Ant build.xml 文g可以帮助~译Q把q个文g攑֜:
(tng) (tng) c:\ofbiz\ofbiz\testOfbiz\ 目录下,然后在命令行H口下进入该目录Q敲?ant
(tng) 来编译(需要保证已l安?AntQ,~译后的 .class ?x)放?br /> (tng) (tng) c:\ofbiz\ofbiz\testOfbiz\com\geeyo\ofbiz 下,
(tng) 拯 c:\ofbiz\ofbiz\testofbiz\com 目录?c:\ofbiz\ofbiz\partymgr\webapp\WEB-INF\classes
(tng) 目录下?/p>
(tng) build.xml
>=============================================================================
<project name="TestOfbiz" default="dist" basedir=".">
(tng) (tng) (tng) <description>
(tng) (tng) (tng) Test ofbiz
(tng) (tng) (tng) </description>
(tng) <!--test cvs-->
(tng) <!-- set global properties for this build -->
(tng) <property name="src" location="."/>
(tng) <property name="build" location="."/>
(tng) <property name="lib_dir" (tng) location="c:/ofbiz/catalina/shared/lib"/>
(tng) <property name="lib1_dir" (tng) location="c:/ofbiz/catalina/common/lib"/>
(tng) <path id="project.class.path">
(tng) (tng) (tng) <fileset dir="${lib_dir}">
(tng) (tng) (tng) (tng) (tng) (tng) <include name="*.jar"/>
(tng) (tng) (tng) </fileset>
(tng) (tng) (tng) <fileset dir="${lib1_dir}">
(tng) (tng) (tng) (tng) (tng) (tng) <include name="*.jar"/>
(tng) (tng) (tng) </fileset>
(tng) </path>
(tng) <target name="init">
(tng) (tng) (tng) <!-- Create the time stamp -->
(tng) (tng) (tng) <tstamp/>
(tng) (tng) (tng) <!-- Create the build directory structure used by compile -->
(tng) (tng) (tng) <mkdir dir="${build}"/>
(tng) </target>
(tng) <target name="compile" depends="init"
(tng) (tng) (tng) (tng) (tng) (tng) (tng) description="compile the source " >
(tng) (tng) (tng) <!-- Compile the java code from ${src} into ${build} -->
(tng) (tng) (tng) <javac srcdir="${src}" destdir="${build}">
(tng) (tng) (tng) (tng) (tng) <classpath refid="project.class.path"/>
(tng) (tng) (tng) </javac>
(tng) </target>
(tng) <target name="dist" depends="compile"
(tng) (tng) (tng) (tng) (tng) (tng) (tng) description="generate the distribution" >
(tng) (tng) (tng) <!-- Create the distribution directory -->
(tng) </target>
(tng) <target name="clean"
(tng) (tng) (tng) (tng) (tng) (tng) (tng) description="clean up" >
(tng) (tng) (tng) <!-- Delete the ${build} and ${dist} directory trees -->
(tng) </target>
</project>
>=============================================================================
然后我们来创?JSP E序QJSP E序全部攑֜
(tng) c:\ofbiz\ofbiz\partymgr\webapp\party 下面
(tng) 1.listofbiz.jsp
>=============================================================================
<%@ taglib uri="ofbizTags" prefix="ofbiz" %>
<%@ page import="java.util.*, org.ofbiz.core.service.ModelService" %>
<%@ page import="org.ofbiz.core.util.*, org.ofbiz.core.pseudotag.*" %>
<%@ page import="org.ofbiz.core.entity.*" %>
<jsp:useBean id="security" type="org.ofbiz.core.security.Security" scope="request" />
<jsp:useBean id="delegator" type="org.ofbiz.core.entity.GenericDelegator" scope="request" />
<script language="JavaScript">
(tng) function confirmDelete()
(tng) {
(tng) (tng) (tng) (tng) return confirm("Are your sure to delete?");
(tng) }
</script>
<%if(security.hasEntityPermission("PARTYMGR", "_VIEW", session)) {%>
<table width="600" align="center">
(tng) <ofbiz:if name="search_results">
(tng) (tng) <tr><th>Id</th><th>Name</th><th>Note</th><th></th></tr>
(tng) (tng) (tng) <ofbiz:iterator name="cust" property="search_results">
(tng) (tng) (tng) (tng) (tng) <tr>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <td><ofbiz:entityfield attribute="cust" field="customerId"/></td>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <td><ofbiz:entityfield attribute="cust" field="customerName"/></td>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <td><ofbiz:entityfield attribute="cust" field="customerNote"/></td>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <td>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <a href='<ofbiz:url>/showtest?customerId=<ofbiz:entityfield attribute="cust" field="customerId"/></ofbiz:url>' class="buttontext">[Edit]</a>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <a href='<ofbiz:url>/removetest?customerId=<ofbiz:entityfield attribute="cust" field="customerId"/></ofbiz:url>' class="buttontext" onclick="return confirmDelete()">[Remove]</a>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) </td>
(tng) (tng) (tng) (tng) (tng) </tr>
(tng) (tng) (tng) (tng) </ofbiz:iterator>
(tng) (tng) (tng) </ofbiz:if>
</table>
<table width="200" align="center">
(tng) <tr>
(tng) <td><a href='<ofbiz:url>/createTestForm</ofbiz:url>'>Create customer</a></td>
(tng) </tr>
</table>
<%}else{%>
(tng) <h3>You do not have permission to view this page. ("PARTYMGR_VIEW" or "PARTYMGR_ADMIN" needed)</h3>
<%}%>
>=============================================================================
(tng)上面E序中需要说明的?br /> (tng) <ofbiz:if name="search_results">
(tng)?br /> (tng) <ofbiz:iterator name="cust" property="search_results">Q?br /> (tng)
(tng)<ofbiz:if name="search_results"> 是用来检验在 session ?pageContext 对象
中是否包?search_results 对象Q该对象是由我们的程序放?session 中的?br /> (tng)<ofbiz:iterator name="cust" property="search_results"> 是用来@环读取对?br />search_resultsQ是?Collection 对象Q中存储的各对象Qƈ赋给custQ然后在循环?br />中,我们可以用 cust 对象来读取各个段的g(jin)?/p>
2.createofbiz.jsp
>=============================================================================
<%@ taglib uri="ofbizTags" prefix="ofbiz" %>
<%@ page import="java.util.*, org.ofbiz.core.service.ModelService" %>
<%@ page import="org.ofbiz.core.util.*, org.ofbiz.core.pseudotag.*" %>
<%@ page import="org.ofbiz.core.entity.*" %>
<jsp:useBean id="security" type="org.ofbiz.core.security.Security" scope="request" />
<jsp:useBean id="delegator" type="org.ofbiz.core.entity.GenericDelegator" scope="request" />
<%if(security.hasEntityPermission("PARTYMGR", "_VIEW", session)) {%>
<form method="post" action="<ofbiz:url>/createTest</ofbiz:url>" name="createofbiz">
<table width="300" align="center">
(tng) <tr>
(tng) (tng) <td>Id</td><td><input type="text" name="customerId" size="20"></td>
(tng) </tr>
(tng) <tr>
(tng) (tng) <td>Name</td><td><input type="text" name="customerName" size="20"></td>
(tng) </tr>
(tng) <tr>
(tng) (tng) <td>Note</td><td><input type="text" name="customerNote" size="30"></td>
(tng) </tr>
(tng) <tr>
(tng) (tng) <td></td>
(tng) <td><input type="submit"></td>
(tng) </tr>
</table>
</form>
<%}else{%>
(tng) <h3>You do not have permission to view this page. ("PARTYMGR_VIEW" or "PARTYMGR_ADMIN" needed)</h3>
<%}%>
>=============================================================================
(tng) q个E序很容易理解,需要注意的是每个文本框的名字,要跟 Schema StudyCustomer 的各
个段一_(d)以ɽE序中跟Ҏ(gu)处理?/p>
(tng)3.showofbiz.jsp
>=============================================================================
<%@ taglib uri="ofbizTags" prefix="ofbiz" %>
<%@ page import="java.util.*, org.ofbiz.core.service.ModelService" %>
<%@ page import="org.ofbiz.core.util.*, org.ofbiz.core.pseudotag.*" %>
<%@ page import="org.ofbiz.core.entity.*" %>
<jsp:useBean id="security" type="org.ofbiz.core.security.Security" scope="request" />
<jsp:useBean id="delegator" type="org.ofbiz.core.entity.GenericDelegator" scope="request" />
<%if(security.hasEntityPermission("PARTYMGR", "_VIEW", session)) {%>
<form method="post" action="<ofbiz:url>/updateTest</ofbiz:url>" name="updateofbiz">
<table width="300" align="center">
(tng) <tr>
(tng) (tng) <td>Id</td><td><input type="text" name="customerId" size="20" value="<ofbiz:entityfield attribute="edit_cust" field="customerId"/>"></td>
(tng) </tr>
(tng) <tr>
(tng) (tng) <td>Name</td><td><input type="text" name="customerName" size="20" value="<ofbiz:entityfield attribute="edit_cust" field="customerName"/>"></td>
(tng) </tr>
(tng) <tr>
(tng) (tng) <td>Note</td><td><input type="text" name="customerNote" size="30" value="<ofbiz:entityfield attribute="edit_cust" field="customerNote"/>"></td>
(tng) </tr>
(tng) <tr>
(tng) (tng) <td></td>
(tng) (tng) <td><input type="submit"></td>
(tng) </tr>
</table>
</form>
<%}else{%>
(tng) <h3>You do not have permission to view this page. ("PARTYMGR_VIEW" or "PARTYMGR_ADMIN" needed)</h3>
<%}%>
>=============================================================================
(tng) q个E序中,主要是通过
(tng) <ofbiz:entityfield attribute="edit_cust" field="customerId"/>
(tng) 把取到的对象的段昄出来, 对象 edit_cust 是我们在E序中取到ƈ攑ֈ session 中的?/p>
下面我们来配|?controller.xml ?regions.xml, ?controller.xml 中加?
>=============================================================================
(tng) (tng) <request-map uri="createTestForm">
(tng) (tng) (tng) (tng) (tng) <description>Show the create form</description>
(tng) (tng) (tng) (tng) (tng) <security https="false" auth="false"/>
(tng) (tng) (tng) (tng) (tng) <response name="success" type="view" value="createTestForm"/>
(tng) (tng) </request-map>
(tng) (tng) <request-map uri="testofbiz">
(tng) (tng) (tng) (tng) (tng) <description>Test Ofbiz</description>
(tng) (tng) (tng) (tng) (tng) <security https="false" auth="false"/>
(tng) (tng) (tng) (tng) (tng) <response name="success" type="view" value="testofbiz"/>
(tng) (tng) </request-map>
(tng)
(tng) (tng) <request-map uri="listtest">
(tng) (tng) (tng) (tng) (tng) <description>List all records</description>
(tng) (tng) (tng) (tng) (tng) <security https="false" auth="false"/>
(tng) (tng) (tng) (tng) (tng) <event type="java" path="com.geeyo.ofbiz.TestOfbiz" invoke="lookAllRecords" />
(tng) (tng) (tng) (tng) (tng) <response name="success" type="view" value="listAllTest"/>
(tng) (tng) </request-map>
(tng) (tng) <request-map uri="showtest">
(tng) (tng) (tng) (tng) (tng) <description>Show records</description>
(tng) (tng) (tng) (tng) (tng) <security https="false" auth="false"/>
(tng) (tng) (tng) (tng) (tng) <event type="java" path="com.geeyo.ofbiz.TestOfbiz" invoke="findRecord" />
(tng) (tng) (tng) (tng) (tng) <response name="success" type="view" value="showTest"/>
(tng) (tng) </request-map>
(tng) (tng) <request-map uri="createTest">
(tng) (tng) (tng) (tng) (tng) (tng) <security https="true" auth="true"/>
(tng) (tng) (tng) (tng) (tng) (tng) <event type="java" path="com.geeyo.ofbiz.TestOfbiz" invoke="createNewRecord"/>
(tng) (tng) (tng) (tng) (tng) (tng) <response name="success" type="request" value="listtest"/>
(tng) (tng) (tng) (tng) (tng) (tng) <response name="error" type="view" value="createTestForm"/>
(tng) (tng) </request-map>
(tng) (tng) <request-map uri="updateTest">
(tng) (tng) (tng) (tng) (tng) <description>update a record</description>
(tng) (tng) (tng) (tng) (tng) <security https="false" auth="false"/>
(tng) (tng) (tng) (tng) (tng) <event type="java" path="com.geeyo.ofbiz.TestOfbiz" invoke="updateRecord" />
(tng) (tng) (tng) (tng) (tng) <response name="success" type="request" value="listtest"/>
(tng) (tng) </request-map>
(tng) (tng) <request-map uri="removetest">
(tng) (tng) (tng) (tng) (tng) <description>remove a record</description>
(tng) (tng) (tng) (tng) (tng) <security https="false" auth="false"/>
(tng) (tng) (tng) (tng) (tng) <event type="java" path="com.geeyo.ofbiz.TestOfbiz" invoke="removeRecord" />
(tng) (tng) (tng) (tng) (tng) <response name="success" type="request" value="listtest"/>
(tng) (tng) </request-map>
(tng) (tng) <view-map name="listAllTest" type="region"/>
(tng) (tng) <view-map name="createTestForm" type="region"/>
(tng) (tng) <view-map name="showTest" type="region"/>
>=============================================================================
(tng) ?regions.xml 中加入:(x)
>=============================================================================
(tng) (tng) <define id='createTestForm' region='MAIN_REGION'>
(tng) (tng) (tng) (tng) (tng) (tng) <put section='title'>Create Ofbiz</put>
(tng) (tng) (tng) (tng) (tng) (tng) <put section='content' content='/party/createofbiz.jsp'/>
(tng) (tng) </define>
(tng) (tng) <define id='listAllTest' region='MAIN_REGION'>
(tng) (tng) (tng) (tng) (tng) (tng) <put section='title'>List Ofbiz</put>
(tng) (tng) (tng) (tng) (tng) (tng) <put section='content' content='/party/listofbiz.jsp'/>
(tng) (tng) </define>
(tng) (tng) <define id='showTest' region='MAIN_REGION'>
(tng) (tng) (tng) (tng) (tng) (tng) <put section='title'>Show Ofbiz</put>
(tng) (tng) (tng) (tng) (tng) (tng) <put section='content' content='/party/showofbiz.jsp'/>
(tng) (tng) </define>
>=============================================================================
(tng) 现在完成了(jin)Q我们重新启?OfbizQ然后用 IE 讉KQ?br /> (tng) http://localhost:8080/partymgr/control/listtestQ用admin/ofbiz d后就可以
看到我们刚才的工作成果了(jin)Q你现在可以增加/删除/修改记录?/p>
6.Ofbiz 通过 XML 来完成数据库操作Q非常强大的功能Q?/p>
(tng) q是 Ofbiz 的一个非常强大的功能Q可能通过单的 XML 文g来完成数据增/?改的处理Q?br />q些处理在数据库应用中是非常多的Q因为很多需要维护的数据Q所以写E序也是最花时间的Q?br />Ofbiz 把这些操作通过 XML 来完成,不能不说是一大革?--使我们不用写E序可以完成大
部分处理Q这是每个程序员都向往的终极目标?/p>
(tng) 我们下面举例来讲qC下,处理的数据还是利用我们前面创建的 StudyCustomerQ?XML
配置文g来完成前面程?TestOfbiz.java 的大部分操作?/p>
(tng) ?c:\ofbiz\ofbiz\testOfbiz\com\geeyo\ofbiz 目录下创建文?TestOfbizServices.xmlQ?br />该文件的内容如下Q?/p>
>=================================================================
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE simple-methods PUBLIC "-//OFBiz//DTD Simple Methods//EN" "http://www.ofbiz.org/dtds/simple-methods.dtd">
<simple-methods>
(tng) (tng) <!-- TestOfbiz methods -->
(tng) (tng) <simple-method method-name="createNewRecord" short-description="Create a new record">
(tng) (tng) (tng) (tng) (tng) (tng) <check-permission permission="STUDYCUSTOMER" action="_CREATE"><fail-message message="Security Error: to run createRecord you must have the STUDYCUSTOMER_CREATE permission"/></check-permission> (tng) (tng) (tng) (tng) (tng) (tng) (tng) <check-errors/>
(tng) (tng) (tng) (tng) (tng) (tng) <make-value entity-name="StudyCustomer" value-name="newEntity"/>
(tng) (tng) (tng) (tng) (tng) (tng) <set-pk-fields map-name="parameters" value-name="newEntity"/>
(tng) (tng) (tng) (tng) (tng) (tng) <set-nonpk-fields map-name="parameters" value-name="newEntity"/>
(tng) (tng) (tng) (tng) (tng) (tng) <create-value value-name="newEntity"/>
(tng) (tng) </simple-method>
(tng) (tng) <simple-method method-name="updateRecord" short-description="Update a record">
(tng) (tng) (tng) (tng) (tng) (tng) <check-permission permission="STUDYCUSTOMER" action="_UPDATE"><fail-message message="Security Error: to run updateRecord you must have the STUDYCUSTOMER_UPDATE permission"/></check-permission>
(tng) (tng) (tng) (tng) (tng) (tng) <check-errors/>
(tng) (tng) (tng) (tng) (tng) (tng) <make-value entity-name="StudyCustomer" value-name="lookupPKMap"/>
(tng) (tng) (tng) (tng) (tng) (tng) <set-pk-fields map-name="parameters" value-name="lookupPKMap"/>
(tng) (tng) (tng) (tng) (tng) (tng) <find-by-primary-key entity-name="StudyCustomer" map-name="lookupPKMap" value-name="lookedUpValue"/>
(tng) (tng) (tng) (tng) (tng) (tng) <set-nonpk-fields map-name="parameters" value-name="lookedUpValue"/>
(tng) (tng) (tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) <store-value value-name="lookedUpValue"/>
(tng) (tng) </simple-method>
(tng) (tng) <simple-method method-name="findRecord" short-description="lookup a record">
(tng) (tng) (tng) (tng) (tng) (tng) <check-errors/>
(tng) (tng) (tng) (tng) (tng) (tng) <make-value entity-name="StudyCustomer" value-name="lookupPKMap"/>
(tng) (tng) (tng) (tng) (tng) (tng) <set-pk-fields map-name="parameters" value-name="lookupPKMap"/>
(tng) (tng) (tng) (tng) (tng) (tng) <find-by-primary-key entity-name="StudyCustomer" map-name="lookupPKMap" value-name="edit_cust"/>
(tng) (tng) <field-to-session field-name="edit_cust"/>
(tng) (tng) </simple-method>
(tng) (tng) <simple-method method-name="removeRecord" short-description="Delete a record">
(tng) (tng) (tng) (tng) (tng) (tng) <check-permission permission="STUDYCUSTOMER" action="_DELETE"><fail-message message="Security Error: to run deleteRecord you must have the STUDYCUSTOMER_DELETE permission"/></check-permission>
(tng) (tng) (tng) (tng) (tng) (tng) <check-errors/>
(tng) (tng) (tng) (tng) (tng) (tng) <make-value entity-name="StudyCustomer" value-name="lookupPKMap"/>
(tng) (tng) (tng) (tng) (tng) (tng) <set-pk-fields map-name="parameters" value-name="lookupPKMap"/>
(tng) (tng) (tng) (tng) (tng) (tng) <find-by-primary-key entity-name="StudyCustomer" map-name="lookupPKMap" value-name="lookedUpValue"/>
(tng) (tng) (tng) (tng) (tng) (tng) <remove-value value-name="lookedUpValue"/>
(tng) (tng) </simple-method>
(tng) (tng) <simple-method method-name="lookAllRecords" short-description="lookup suitable records">
(tng) (tng) (tng) (tng) (tng) (tng) <check-errors/>
(tng) (tng) (tng) (tng) (tng) (tng) <find-by-and entity-name="StudyCustomer" list-name="search_results"/>
(tng) (tng) <field-to-session field-name="search_results"/>
(tng) (tng) </simple-method>
(tng) (tng)
</simple-methods>
>=================================================================
(tng)上面?XML 基本是不用解释的Q定义了(jin)
(tng) createNewRecord
(tng) updateRecord
(tng) lookAllRecords
(tng) removeRecord
(tng) findRecord
(tng) q几个方法,而且都有对用h限的(g)查,q几个方法对应于前面 TestOfbiz.java 中的几个Ҏ(gu)Q?br />q样来做数据库操作显然比?Java E序写要单得多,
(tng) 下面q需要在 controller.xmlQ具体文件得位置请参照前面的教程Q更改一?mapping 的设|,
更改如下Q以前?TestOfbiz.java 时的配置我以注释的方式保留着以做参照Q?/p>
>=================================================================
(tng) (tng) <request-map uri="createTestForm">
(tng) (tng) (tng) (tng) (tng) <description>Show the create form</description>
(tng) (tng) (tng) (tng) (tng) <security https="false" auth="false"/>
(tng) (tng) (tng) (tng) (tng) <response name="success" type="view" value="createTestForm"/>
(tng) (tng) </request-map>
(tng) (tng) <request-map uri="listtest">
(tng) (tng) (tng) (tng) (tng) <description>List all records</description>
(tng) (tng) (tng) (tng) (tng) <security https="false" auth="false"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <event type="simple" path="com/geeyo/ofbiz/TestOfbizServices.xml" invoke="lookAllRecords" />
(tng) (tng) (tng) (tng) (tng) <response name="success" type="view" value="listAllTest"/>
(tng) (tng) </request-map>
(tng) (tng) <request-map uri="showtest">
(tng) (tng) (tng) (tng) (tng) <description>Show records</description>
(tng) (tng) (tng) (tng) (tng) <security https="false" auth="false"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <event type="simple" path="com/geeyo/ofbiz/TestOfbizServices.xml" invoke="findRecord" />
(tng) (tng) (tng) (tng) (tng) <response name="success" type="view" value="showTest"/>
(tng) (tng) </request-map>
(tng) (tng) <request-map uri="createTest">
(tng) (tng) (tng) (tng) (tng) (tng) <security https="true" auth="true"/>
(tng) (tng) (tng) (tng) (tng) (tng) <event type="simple" path="com/geeyo/ofbiz/TestOfbizServices.xml" invoke="createNewRecord"/>
(tng) (tng) (tng) (tng) (tng) (tng) <response name="success" type="request" value="listtest"/>
(tng) (tng) (tng) (tng) (tng) (tng) <response name="error" type="view" value="createTestForm"/>
(tng) (tng) </request-map>
(tng) (tng) <request-map uri="updateTest">
(tng) (tng) (tng) (tng) (tng) <description>update a record</description>
(tng) (tng) (tng) (tng) (tng) <security https="false" auth="false"/>
(tng) (tng) (tng) (tng) (tng) <event type="simple" path="com/geeyo/ofbiz/TestOfbizServices.xml" invoke="updateRecord" />
(tng) (tng) (tng) (tng) (tng) <response name="success" type="request" value="listtest"/>
(tng) (tng) </request-map>
(tng) (tng) <request-map uri="removetest">
(tng) (tng) (tng) (tng) (tng) <description>remove a record</description>
(tng) (tng) (tng) (tng) (tng) <security https="false" auth="false"/>
(tng) (tng) (tng) (tng) (tng) <event type="simple" path="com/geeyo/ofbiz/TestOfbizServices.xml" invoke="removeRecord" />
(tng) (tng) (tng) (tng) (tng) <response name="success" type="request" value="listtest"/>
(tng) (tng) </request-map>
(tng) (tng) <view-map name="listAllTest" type="region"/>
(tng) (tng) <view-map name="createTestForm" type="region"/>
(tng) (tng) <view-map name="testofbiz" type="region"/>
(tng) (tng) <view-map name="showTest" type="region"/>
>=================================================================
(tng) 配置该文件的Ҏ(gu)请参照前面的教程Qregions.xml 不需改动?/p>
(tng) 配置完后L(fng)前面讲过的方法访?URL: http://localhost:8080/partymgr/control/listtest
(tng) 现在我们可以看到QOfbiz ?MVC 斚w做得非常好,我们可以把后端的处理E序?java ?br />成用 XMl 控制Q而其他部分(?JSPQ不需M改动Q这可以保证我们pȝ各部分的独立性?/p>