- 浏览: 1186935 次
-
文章分类
最新评论
-
shunyang218:
图刷不出来 ,有点可惜了。
android facebook twitter开发 与 OAUTH -
whoshaofeng:
eval('('+str+')') 为什么加 '('
JSON那些事 -
ileson:
可否把代码贴出来、研究一下。
分享几个超级震憾的图片特效
Springframework 2.0 与 ZK 混合开发实例
导读:
什么是ZK
利用ZK框架设计的web应用程序具备丰富的胖客户端特性和简单的设计模型。ZK包括一个基于AJAX可自动进行交互式操作的事件驱动引擎和一套兼容XUL的组件。利用直观的事件驱动模型,你可以用具有XUL特性的组件来表示你的应用程序并通过由用户触发的监听事件来操作这些组件,就像开发桌面应用程序一样简单。
先来点直观的感受:http://www.zkoss.org/zkdemo/userguide/
什么是Springframework 2.0
大名鼎鼎的Springframework相信没有人不知道吧,就在不久前,Interface21又推出了Spring 2.0版本,Spring2.0的发布恐怕算得上2006年Java社区的一件大事了。Spring2.0中一些新的特性,如:基于XML Schema语法的配置、JPA的支持、支持动态语言、异步JMS等诸多功能都非常不错,总体来说,Spring2.0将向未来的宏大目标又迈进了一大步。
动机
因为工作需要,要写一个基于Web的JMS消息发送程序,当然,这对于技术人员来说,是小菜一碟,现实问题摆在面前,一是时间紧,二是由于客户对技术方面一般,所以GUI的美观程度至关重要,怎么办呢?思前想后,决定使用Ajax技术,但我们也知道,如今Ajax的框架多如牛毛,我该选择哪一个呢,无意中,通过Google找到了ZK。在看完她的在线演示后,被她华丽的外观,简洁实现方式所吸引。于是,就这样,我一边看着ZK技术手册,一边上路了。
第一次重构 — Spring登场
ZK作为表现层技术,一般通过两种手段与业务层交互,一种方式是只使用ZK做表现层,当页面提交后,再由用户指定的servlet来处理具体的业务逻辑,另一种方式是通过象.NET的WebForm一样基于事件响应方式编程。例如:
<window title="event listener demo" border="normal" width="200px"><br> <label id="mylabel" value="Hello, World!"> <br> <button label="Change label"> <br> <attribute name="onClick"><br> mylabel.value = "Hello, Event!" <br> </attribute><br> </button> <br> </label></window>
很明显,使用第二种方式会更加简单,更加容易理解,但问题也随之产生,因为每个事件处理都要使用大量类信息,随着业务逻辑的复杂性增加,每个ZUL(ZK页面)也会变得相当的臃肿,怎么办呢?当然是使用Spring!!原因有二:一是可以将大量业务逻辑代码封装成bean,减少表现层的复杂性,另一个好处是,由于业务场景需要处理JMS要关内容,通过Spring2.0对JMS强大的支持功能,也可以大大减少工作量。说干就干,通过研究尝试,我发现在ZK中可以通过如下方式访问Spring的上下文:
…..

...{
importorg.springframework.web.context.WebApplicationContext;
importorg.springframework.web.context.support.WebApplicationContextUtils;
WebApplicationContextctx=(WebApplicationContext)Executions.getCurrent().getDesktop().getWebApp().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
…
这样就如鱼得水了,我可以任意使用用Spring管理的Bean了。
第二次重构 — Spring JMS发送
我们知道在Spring中处理JMS的发送一般来讲是通过配置的方式得到JmsTemplate,然后当要发送消息时,我们再创建一个匿名类,如下:
….

this.jmsTemplate.send(this.queue,newMessageCreator()...{

publicMessagecreateMessage(Sessionsession)throwsJMSException...{
returnsession.createTextMessage("helloqueueworld");
}
});
…
通过分析,很显然,使用匿名类的原因就在于,只有在消息发送这一时刻才能决定发送什么类型的消息以及消息内容是什么,知道了这一点,其实我们可以写一个工具Bean类,来封装这个逻辑,来避免这个繁琐的过程,代码如下:
MessageCreatorBean.java
packagebean;
importjava.io.ByteArrayOutputStream;
importjava.io.File;
importjava.io.InputStream;
importjava.util.Date;
importjava.util.HashMap;
importjava.util.Iterator;
importjava.util.Map;
importjava.util.Properties;
importjava.util.Set;
importjava.util.Map.Entry;
importjavax.jms.BytesMessage;
importjavax.jms.JMSException;
importjavax.jms.Message;
importjavax.jms.Session;
importorg.apache.commons.logging.Log;
importorg.apache.commons.logging.LogFactory;
importorg.springframework.jms.core.MessageCreator;
importorg.zkoss.util.media.Media;

publicclassMessageCreatorBeanimplementsMessageCreator...{
privateMediamedia;
privateMapproperties;
privateStringtext;

publicvoidsetText(Stringstr)...{
text=str;
}

publicStringgetText()...{
returntext;
}

publicvoidsetMedia(Mediam)...{
media=m;
}

publicMediagetMedia()...{
returnmedia;
}

publicvoidsetProperties(Mapmap)...{
properties=map;
}

publicMapgetProperties()...{
returnproperties;
}

privatecreateBinaryMessage(Sessionsession)throwsJMSException...{
BytesMessagemsg=null;
byte[]bytes=null;

try...{
bytes=media.getByteData();
}

catch(IllegalStateExceptionise)...{

try...{
InputStreamis=media.getStreamData();
ByteArrayOutputStreambaos=newByteArrayOutputStream();
byte[]buf=newbyte[1000];
intbyteread=0;

while((byteread=is.read(buf))!=-1)...{
baos.write(buf,0,byteread);
}
bytes=baos.toByteArray();
}

catch(IOExceptionio)...{
}
}
msg=session.createBytesMessage();
msg.writeBytes(bytes);
properties.put("m_name",media.getName());
properties.put("m_format",media.getFormat());
properties.put("m_ctype",media.getContentType());
returnmsg;
}

privateMessagecreateTextMessage(Sessionsession)throwsJMSException...{
Messagemsg=session.createTextMessage(text);
properties.put("m_name",(newDate()).getTime()+".xml");
properties.put("m_format","xml");
properties.put("m_ctype","text/xml");
returnmsg;
}

publicMessagecreateMessage(Sessionsession)throwsJMSException...{
Messagemsg=null;
if(properties==null)properties=newProperties();

if(media==null)...{
msg=createTextMessage(session);
}

else...{
msg=createBinaryMessage(session);
}
applyProperties(msg);
returnmsg;
}

publicvoidmergeProperties(Propertiesprops)...{

if(properties==null)...{
properties=newProperties();
}

if(props!=null)...{
Setkeys=props.keySet();

for(Iteratorit=keys.iterator();it.hasNext();)...{
Stringkey=(String)it.next();
properties.put(key,props.get(key));
}
}
}

privatevoidapplyProperties(Messagemsg)throwsJMSException...{

if(properties!=null)...{

for(Objects:properties.keySet())...{
msg.setStringProperty((String)s,(String)properties.get(s));
}
}
}
}
配置Springframework Context:
<bean id="normalMessageCreator"><br></bean>
class="com.bea.de.bean.< class="com.bea.de.bean.MessageCreatorBean"/>
使用的时候我们就可以通过Spring来访问了。
…

voidsend(Mediamedia,Propertiesprops)...{
WebApplicationContextctx=(WebApplicationContext)Executions.getCurrent().getDesktop().getWebApp().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
JmsTemplatejt=(JmsTemplate)ctx.getBean("jmsTemplate");
Queuequeue=(Queue)ctx.getBean("binaryQueue");
MessageCreatorBeanmc=(MessageCreatorBean)ctx.getBean("binaryMessageCreator");
Propertiesp=(Properties)ctx.getBean("messageProperties");
mc.mergeProperties(p);
mc.mergeProperties(props);
mc.setMedia(media);
jt.send(queue,mc);
}
…
第三次重构—BSH(BeanShell)登场
虽然Spring与JMS发送问题解决了,但是还有一个潜在的问题,就是如果发送的消息类型或逻辑攺变了,我们不得不重写MessageCreatorBean这个类,当然,这就引起了重编译部署的问题,怎么能不编译就可以攺变业务逻辑呢?我想到了Spring 2.0的新特性,对脚本语言的支持,Spring 2.0现在支持三种脚本语言:BSH、JRuby、JGroovy。这三种脚本语言使用起来大同小异,我选择了语法更贴近Java的BSH。过程如下:
先编写一个接口
packagecom.bea.de.scripting;
importjava.util.Map;
…..

publicinterfaceMessageCreatorBeanextendsMessageCreator...{
publicvoidsetMedia(Mediamsg);
publicMediagetMedia();
publicvoidsetProperties(Mapmap);
publicMapgetProperties();
publicMessagecreateMessage(Sessionsession)throwsJMSException;
publicvoidmergeProperties(Propertiesprops);
}
然后再写一个实现类
文件名MessageCreatorBean.bsh
Mediamedia;
Mapproperties;
Stringtext;

publicvoidsetText(Stringstr)...{
text=str;
}

publicStringgetText()...{
returntext;
}

publicvoidsetMedia(Mediam)...{
media=m;
}

publicMediagetMedia()...{
returnmedia;
}

publicvoidsetProperties(Mapmap)...{
properties=map;
}

publicMapgetProperties()...{
returnproperties;
}

privatecreateBinaryMessage(Sessionsession)throwsJMSException...{
BytesMessagemsg=null;
byte[]bytes=null;

try...{
bytes=media.getByteData();
}

catch(IllegalStateExceptionise)...{

try...{
InputStreamis=media.getStreamData();
ByteArrayOutputStreambaos=newByteArrayOutputStream();
byte[]buf=newbyte[1000];
intbyteread=0;

while((byteread=is.read(buf))!=-1)...{
baos.write(buf,0,byteread);
}
bytes=baos.toByteArray();
}

catch(IOExceptionio)...{
}
}
msg=session.createBytesMessage();
msg.writeBytes(bytes);
properties.put("m_name",media.getName());
properties.put("m_format",media.getFormat());
properties.put("m_ctype",media.getContentType());
returnmsg;
}

privateMessagecreateTextMessage(Sessionsession)throwsJMSException...{
Messagemsg=session.createTextMessage(text);
properties.put("m_name",(newDate()).getTime()+".xml");
properties.put("m_format","xml");
properties.put("m_ctype","text/xml");
returnmsg;
}

publicMessagecreateMessage(Sessionsession)throwsJMSException...{
Messagemsg=null;
if(properties==null)properties=newProperties();

if(media==null)...{
msg=createTextMessage(session);
}

else...{
msg=createBinaryMessage(session);
}
applyProperties(msg);
returnmsg;
}

publicvoidmergeProperties(Propertiesprops)...{

if(properties==null)...{
properties=newProperties();
}

if(props!=null)...{
Setkeys=props.keySet();

for(Iteratorit=keys.iterator();it.hasNext();)...{
Stringkey=(String)it.next();
properties.put(key,props.get(key));
}
}
}

privatevoidapplyProperties(Messagemsg)throwsJMSException...{

if(properties!=null)...{

for(Objects:properties.keySet())...{
msg.setStringProperty((String)s,(String)properties.get(s));
}
}
}
最后编写配置文件
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/langhttp://www.springframework.org/schema/lang/spring-lang-2.0.xsd
http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-2.0.xsd">
….
<lang:bshid="normalMessageCreator"
script-source="classpath:bsh/MessageCreatorBean.bsh"
script-interfaces="com.bea.de.scripting.MessageCreatorBean"
refresh-check-delay="5000"/>
<beans xmlns="http://www.springframework.org/schema/beans"><bsh id="normalMessageCreator"><br> <strong>解释:</strong> <br> <strong>script-source:</strong>具体业务逻辑的的脚本实现文件,当系统上线后,如果我们想修攺业务逻辑,只需修攺这个脚本就可以了,无需重编译类文件。 <br> <strong>script-interface:</strong>业务接口,这个接口文件一定要在前期定好,不然如果要对接口修攺,就要重编译了。如果使用JGroovy就无需这个参数了。 <br> <strong>refresh-check-delay:</strong>引擎每隔多长时间检查脚本状态,如果脚本被攺动就会自动编译。 <br> <strong>第四次重构—Spring JMS接收</strong> <br> 以往我们在实现JMS消息的接收时,往往是通过(MDB-消息EJB)或启用一个后台进程,等待JMS消息进行处理,代码量和复杂度都非常高,因此,我想到了Spring对JMS Container的支持。也就是说,由Spring监控消息以及维护消息处理Bean。实现如下: <br><bsh id="normalMessageListener"><bean id="normalMessageListenerContainer"><property name="concurrentConsumers" value="5"><property name="connectionFactory" ref="connectionFactory"><property name="destination" ref="receiveNormalQueue"><property name="messageListener" ref="normalMessageListener"></property></property></property></property></bean></bsh></bsh></beans>
….
<lang:bshid="normalMessageListener"
script-source="classpath:bsh/DiskMessageListenerBean.bsh"
script-interfaces="com.bea.de.scripting.DiskMessageListenerBean"
refresh-check-delay="5000">
<lang:propertyname="basePath"value="${jms.listener.disk.normal}"/>
</lang:bsh>

<beanid="normalMessageListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<propertyname="concurrentConsumers"value="5"/>
<propertyname="connectionFactory"ref="connectionFactory"/>
<propertyname="destination"ref="receiveNormalQueue"/>
<propertyname="messageListener"ref="normalMessageListener"/>
</bean>
normalMessageListener:是一个实现了javax.jms. MessageListener接口的Bean,用来处理消息处理逻辑,我们可以看到,为了维护的方便,此处,我还是使用了BSH。
normalMessageListenerContainer:是一个用来维护消息处理Bean的容器。
第五次重构—Spring JMS消息Pooling机制
经过一系列的大手术,基本上完成了客户所需要的功能,但这时客户有了新的想法:客户的外部系统定期生成数据(以文件方式写入文件目录 ),然后,由信息平台将数据传出。当时第一想法就是使用Quartz,虽然Quartz功能强大,但总觉得其非出生名门,所以最终采用了JDK Timer支持,结合Spring的强大功能,实现了此功能。
代码如下:
<bsh id="poolingMessageExecutor"><br></bsh>
<lang:bshid="poolingMessageExecutor"
script-source="classpath:bsh/PoolingMessageTimerTaskBean.bsh"
script-interfaces="com.bea.de.scripting.MessageTaskExecutor"
refresh-check-delay="5000">
<lang:propertyname="jmsTemplate"ref="jmsTemplate"/>
<lang:propertyname="messageProperties"ref="messageProperties"/>
<lang:propertyname="targetQueue"ref="binaryQueue"/>
<lang:propertyname="basePath"value="${jms.pooling.disk}"/>
<lang:propertyname="messageCreator"ref="binaryMessageCreator"/>
</lang:bsh>

<beanid="poolingMessageTimerTask"
class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
<propertyname="targetObject"ref="poolingMessageExecutor"/>
<propertyname="targetMethod"value="execute"/>
</bean>

<beanid="scheduledPoolingMessageTask"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
<propertyname="delay"value="10000"/>
<propertyname="period"value="50000"/>
<propertyname="timerTask"ref="poolingMessageTimerTask"/>
</bean>

<beanid="scheduler"
class="org.springframework.scheduling.timer.TimerFactoryBean">
<propertyname="scheduledTimerTasks">
<list>
<refbean="scheduledPoolingMessageTask"/>
</list>
</property>
</bean>
<property name="jmsTemplate" ref="jmsTemplate"><property name="messageProperties" ref="messageProperties"><property name="targetQueue" ref="binaryQueue"><property name="basePath" value="${jms.pooling.disk}"><bean id="poolingMessageTimerTask"><property name="targetObject" ref="poolingMessageExecutor"><bean id="scheduledPoolingMessageTask"><property name="delay" value="10000"><property name="period" value="50000"><bean id="scheduler"><br> <br> <strong>解释:</strong> <br> <strong>poolingMessageExecutor</strong>:是一个纯的POJO对象(这也是我选此方式的一个很大原因),当然,具体的逻辑还是由BSH完成。 <br> <strong>poolingMessageTimerTask:</strong>此对象用来指明任务执行器的哪个函数进行具体的任务处理。 <br> <strong>scheduledPoolingMessageTask:</strong>配置任务调度信息,如延时、时间间隔 <br> <strong>scheduler:</strong>调度触发器 <br> <strong>第五次重构—ZK代码精减</strong> <br> 至此,全部功能实现完毕,由于Spring与ZK的出色表现,具然提供完成了任务,但回过头来看自己的代码,虽然有了Spring的帮助,但页面中的代码还是显得有些臃肿,因此,决定再次调整。 <br> <strong>第一步:</strong> <br> 调整的第一步就是把共性功能进行包装,然后将这些封装后的代码做成库的型式。例: <br> 生成库文件:common.zs <br> <br></bean></property></property></bean></property></bean></property></property></property></property>
…
importorg.springframework.web.context.WebApplicationContext;
importcom.bea.de.scripting.DiskMessageListenerBean;

voidsend(Mediamedia,Propertiesprops)...{
……..
jt.send(queue,mc);
}

voidsend(Stringstr,Propertiesprops)...{
……
jt.send(queue,mc);
}
其它ZUL页面调用时只需如下方式:
….
<zscriptsrc="/lib/common.zs"/>
….
<zscript src="/lib/common.zs"> <strong>第二步:ZK组件化</strong> <br> 通过分析,我发现有很多功能类型的页面,例如:由于发送消息的类型不同(二进制、文件等),所以我采用了不同的页面实现消息发送,但实际上有很多功能是类似的,为什么我们不同将这些功能模块化呢?说干就干,我为消息发送制做了一个发送组件:Sender.zul,此页面与其它页面没有什么不同,只是它可以接收参数,例如:如果我们想使用调用者传来的desc参数,就使用${arg.desc}。 <br> 代码如下: <br> <strong>文件名:Sender.zul</strong> <br></zscript>
<?xmlversion="1.0"encoding="UTF-8"?>
<vbox>
<groupboxmold="3d"width="800px">
<captionlabel="控制面板"></caption>

<windowwidth="100%">
<zscriptsrc="/lib/common.zs"/>
<zscript>


org.zkoss.util.media.Mediamedia=null;
booleanisText=true;


voiddoUpload()...{

media=Fileupload.get();

if(media==null)return;


if(media.getFormat().equals("txt")||media.getFormat().equals("xml"))...{

Stringcontent=newString(media.getByteData());
msgTextbox.value=content;
isText=true;
}

else...{
isText=false;
msgTextbox.value="上传文件名-->"+media.getName();
}

msgTextbox.disabled=true;
}


voiddoSend()...{

Stringcontent=msgTextbox.value.trim();
Propertiesprops=newProperties();



if(msgTypeRadiogroup.selectedItem.value.equals("P2P"))...{


if(hospitalListbox.selectedItem==null)...{

Messagebox.show("请选择医院!");

hospitalListbox.focus();
return;
}

Setsel=hospitalListbox.getSelectedItems();

StringBufferbuf=newStringBuffer();


for(Listitemitem:sel)...{

buf.append(item.getValue()).append("|");
}

Stringtmp=buf.toString();
Stringhospitals=tmp.substring(0,tmp.length()-1);

props.put("MessageFor","P2P");
props.put("MessageTarget",hospitals);
}

else...{

if(diseaseListbox.selectedItem==null)...{

Messagebox.show("请选择疾病类型!");
diseaseListbox.focus();
return;
}
props.put("MessageFor","Report");
props.put("MessageTarget",diseaseListbox.selectedItem.value);
}


if(content==null||content.equals(""))...{

Messagebox.show("请输入消息内容!");
}

else...{

if(routingTypeRadiogroup.selectedItem.value.equals("BodyRouting"))...{


if(!isText)...{

Messagebox.show("不能基于流体文件路由,请选择-消息头路由-方式!!");
msgTextbox.focus();
return;
}

else...{

send(content,props);
}
}

elseif(media!=null)...{

send(media,props);
}

else...{

media=neworg.zkoss.util.media.AMedia((newDate()).getTime()+".xml","xml","text/xml",content.getBytes());
send(media,props);
}
Messagebox.show("发送成功");
msgTextbox.focus();
}

msgTextbox.disabled=false;
}


voiddoClear()...{

msgTextbox.value="";
msgTextbox.disabled=true;
media=null;
msgTextbox.focus();
}

</zscript>
<grid>
<rows>
<row>
<labelvalue="文件路径"/>
<hbox>
<textbox/>
<buttonlabel="上传文件"onClick="doUpload()"/>
</hbox>
</row>
<row>
<labelvalue="路由类型"/>
<radiogroupid="routingTypeRadiogroup">

<radiolabel="消息头路由"value="HeadRouting"checked="true"/>
<radiolabel="消息体路由"value="BodyRouting"/>
</radiogroup>
</row>
<row>
<labelvalue="消息内容"/>
<textboxid="msgTextbox"cols="80"multiline="true"rows="20"value="${arg.content}"/>
</row>
<row>
<labelvalue="消息类型"/>
<radiogroupid="msgTypeRadiogroup">

<radiolabel="点对点"value="P2P"checked="true"onCheck="p2pRow.visible=true;reportRow.visible=false;"/>
<radiolabel="上报数据"value="Report"onCheck="p2pRow.visible=false;reportRow.visible=true"/>
</radiogroup>
</row>

<rowid="p2pRow">
<labelvalue="XX"/>
<zscript>
ListModelhospitalModel=getListModel("P2P");
</zscript>
<listboxcheckmark="true"multiple="true"width="200px"id="hospitalListbox"itemRenderer="com.bea.de.ui.MapListItemRender"model="${hospitalModel}">
<listhead>
<listheaderlabel="XX名称"/>
</listhead>
</listbox>
</row>
<rowid="reportRow"visible="false">
<labelvalue="XX类型"/>
<bandboxid="bd1">
<bandpopup>
<zscript>
ListModeldiseaseModel=getListModel("Report");
</zscript>
<listboxwidth="200px"id="diseaseListbox"onSelect="bd1.value=self.selectedItem.label;bd1.closeDropdown();"itemRenderer="com.bea.de.ui.MapListItemRender"model="${diseaseModel}">
<listhead>
<listheaderlabel="XX类型名称"/>
</listhead>
</listbox>
</bandpopup>
</bandbox>
</row>
<row>

<labelvalue="操作"/>
<hbox>
<buttonlabel="发送"onClick="doSend();"/>

<buttonlabel="清空"onClick="doClear();"/>

</hbox>
</row>
</rows>
</grid>
</window>
</groupbox>

<groupboxmold="3d"open="false"width="800px">
<captionlabel="功能说明"></caption>
<windowborder="normal"width="100%">
<includesrc="${arg.desc}"/><!—这里就是接收参数的地方-->
</window>
</groupbox>
</vbox>
<vbox><groupbox mold="3d" width="800px"><window width="100%"><zscript src="/lib/common.zs"><grid><rows><row><label value="文件路径"><row><label value="路由类型"><radiogroup id="routingTypeRadiogroup"><row><label value="消息内容"><br> <br> <strong>组件调用方代码如下:</strong> <br> <br></label></row></radiogroup></label></row></label></row></rows></grid></zscript></window></groupbox></vbox>
<?xmlversion="1.0"encoding="UTF-8"?>
<?componentname="sender"macro-uri="/macros/Sender.zul"?>
<window>
<sender>
<attributename="content"><![CDATA[xxxxx]]></attribute>
<attributename="desc"><![CDATA[/descs/Sender.xhtml]]></attribute>
</sender>
</window>
<window><br> </window>
大功告成,看看成果!!

后记:
在刚接触ZK时,一般使用Zero Kode开发ZUL页面,就在2006年10月9日,Zero Kode终于投入了eZing Builder的怀抱,这下子Eclipse的fans有救了。
其实,还有很多地方还可以进一步的优化(自定义页面组件、数据验证等),但由于时间关系,也只能做到这一步,今后有机会一定再和大家分享。
参考资料:
ZK官方网站:http://www.zkoss.org/
Springframework官方网站:http://www.springframework.org
eZing Builder官方网站http://ezingbuilder.sourceforge.net/cms/
Springframework在线文档:
ZK在线文档:
ZK在线演示:
Contact List with ZK and Spring
Painting with Zero Kode: A real-time web page designer based on ZK, Part I
本文转自
http://dev2dev.bea.com.cn/techdoc/20061127901.html
什么是ZK
利用ZK框架设计的web应用程序具备丰富的胖客户端特性和简单的设计模型。ZK包括一个基于AJAX可自动进行交互式操作的事件驱动引擎和一套兼容XUL的组件。利用直观的事件驱动模型,你可以用具有XUL特性的组件来表示你的应用程序并通过由用户触发的监听事件来操作这些组件,就像开发桌面应用程序一样简单。
先来点直观的感受:http://www.zkoss.org/zkdemo/userguide/
什么是Springframework 2.0
大名鼎鼎的Springframework相信没有人不知道吧,就在不久前,Interface21又推出了Spring 2.0版本,Spring2.0的发布恐怕算得上2006年Java社区的一件大事了。Spring2.0中一些新的特性,如:基于XML Schema语法的配置、JPA的支持、支持动态语言、异步JMS等诸多功能都非常不错,总体来说,Spring2.0将向未来的宏大目标又迈进了一大步。
动机
因为工作需要,要写一个基于Web的JMS消息发送程序,当然,这对于技术人员来说,是小菜一碟,现实问题摆在面前,一是时间紧,二是由于客户对技术方面一般,所以GUI的美观程度至关重要,怎么办呢?思前想后,决定使用Ajax技术,但我们也知道,如今Ajax的框架多如牛毛,我该选择哪一个呢,无意中,通过Google找到了ZK。在看完她的在线演示后,被她华丽的外观,简洁实现方式所吸引。于是,就这样,我一边看着ZK技术手册,一边上路了。
第一次重构 — Spring登场
ZK作为表现层技术,一般通过两种手段与业务层交互,一种方式是只使用ZK做表现层,当页面提交后,再由用户指定的servlet来处理具体的业务逻辑,另一种方式是通过象.NET的WebForm一样基于事件响应方式编程。例如:
<window title="event listener demo" border="normal" width="200px"><br> <label id="mylabel" value="Hello, World!"> <br> <button label="Change label"> <br> <attribute name="onClick"><br> mylabel.value = "Hello, Event!" <br> </attribute><br> </button> <br> </label></window>
很明显,使用第二种方式会更加简单,更加容易理解,但问题也随之产生,因为每个事件处理都要使用大量类信息,随着业务逻辑的复杂性增加,每个ZUL(ZK页面)也会变得相当的臃肿,怎么办呢?当然是使用Spring!!原因有二:一是可以将大量业务逻辑代码封装成bean,减少表现层的复杂性,另一个好处是,由于业务场景需要处理JMS要关内容,通过Spring2.0对JMS强大的支持功能,也可以大大减少工作量。说干就干,通过研究尝试,我发现在ZK中可以通过如下方式访问Spring的上下文:









这样就如鱼得水了,我可以任意使用用Spring管理的Bean了。
第二次重构 — Spring JMS发送
我们知道在Spring中处理JMS的发送一般来讲是通过配置的方式得到JmsTemplate,然后当要发送消息时,我们再创建一个匿名类,如下:









通过分析,很显然,使用匿名类的原因就在于,只有在消息发送这一时刻才能决定发送什么类型的消息以及消息内容是什么,知道了这一点,其实我们可以写一个工具Bean类,来封装这个逻辑,来避免这个繁琐的过程,代码如下:
MessageCreatorBean.java















































































































































配置Springframework Context:
<bean id="normalMessageCreator"><br></bean>

使用的时候我们就可以通过Spring来访问了。














第三次重构—BSH(BeanShell)登场
虽然Spring与JMS发送问题解决了,但是还有一个潜在的问题,就是如果发送的消息类型或逻辑攺变了,我们不得不重写MessageCreatorBean这个类,当然,这就引起了重编译部署的问题,怎么能不编译就可以攺变业务逻辑呢?我想到了Spring 2.0的新特性,对脚本语言的支持,Spring 2.0现在支持三种脚本语言:BSH、JRuby、JGroovy。这三种脚本语言使用起来大同小异,我选择了语法更贴近Java的BSH。过程如下:
先编写一个接口












然后再写一个实现类
文件名MessageCreatorBean.bsh






























































































































最后编写配置文件
































normalMessageListener:是一个实现了javax.jms. MessageListener接口的Bean,用来处理消息处理逻辑,我们可以看到,为了维护的方便,此处,我还是使用了BSH。
normalMessageListenerContainer:是一个用来维护消息处理Bean的容器。
第五次重构—Spring JMS消息Pooling机制
经过一系列的大手术,基本上完成了客户所需要的功能,但这时客户有了新的想法:客户的外部系统定期生成数据(以文件方式写入文件目录 ),然后,由信息平台将数据传出。当时第一想法就是使用Quartz,虽然Quartz功能强大,但总觉得其非出生名门,所以最终采用了JDK Timer支持,结合Spring的强大功能,实现了此功能。
代码如下:
<bsh id="poolingMessageExecutor"><br></bsh>














































其它ZUL页面调用时只需如下方式:



<zscript src="/lib/common.zs"> <strong>第二步:ZK组件化</strong> <br> 通过分析,我发现有很多功能类型的页面,例如:由于发送消息的类型不同(二进制、文件等),所以我采用了不同的页面实现消息发送,但实际上有很多功能是类似的,为什么我们不同将这些功能模块化呢?说干就干,我为消息发送制做了一个发送组件:Sender.zul,此页面与其它页面没有什么不同,只是它可以接收参数,例如:如果我们想使用调用者传来的desc参数,就使用${arg.desc}。 <br> 代码如下: <br> <strong>文件名:Sender.zul</strong> <br></zscript>





























































































































































































































大功告成,看看成果!!

后记:
在刚接触ZK时,一般使用Zero Kode开发ZUL页面,就在2006年10月9日,Zero Kode终于投入了eZing Builder的怀抱,这下子Eclipse的fans有救了。
其实,还有很多地方还可以进一步的优化(自定义页面组件、数据验证等),但由于时间关系,也只能做到这一步,今后有机会一定再和大家分享。
参考资料:
ZK官方网站:http://www.zkoss.org/
Springframework官方网站:http://www.springframework.org
eZing Builder官方网站http://ezingbuilder.sourceforge.net/cms/
Springframework在线文档:
ZK在线文档:
ZK在线演示:
Contact List with ZK and Spring
Painting with Zero Kode: A real-time web page designer based on ZK, Part I
本文转自
http://dev2dev.bea.com.cn/techdoc/20061127901.html
相关推荐
通过深入学习《Spring Framework 2.0 中文参考手册》,开发者能够掌握Spring的核心理念和实际应用,从而在Java企业级应用开发中游刃有余。虽然现在Spring已经更新到更高的版本,但2.0版本的知识仍然是理解和学习后续...
《Spring Framework 2.0开发参考手册》是Java开发者的重要参考资料,它全面涵盖了Spring框架2.0版本的核心特性和使用方法。Spring作为一个轻量级、全面的企业级应用框架,为Java开发提供了强大的支持,尤其在依赖...
Spring Framework 2.0 是一个里程碑式的版本,它在Java企业级开发中占据了重要的地位,为开发者提供了丰富的功能和强大的支持。这个"spring framework 2.0 dist"资源文件包含了该版本的所有核心组件和相关文档,是...
Spring Framework是中国Java开发领域中最广泛使用的开源框架之一,它的出现极大地简化了企业级应用的开发。Spring 2.0版本是该框架的一个重要里程碑,它引入了许多关键特性,为开发者提供了更多的灵活性和控制力。本...
在Spring 2.0版本中,引入了一系列重要的改进和新特性,这些改变极大地提升了开发效率和灵活性。以下是对Spring Framework 2.0关键知识点的详细解析: 1. **依赖注入(Dependency Injection, DI)**:Spring 2.0...
《Spring Framework 2.0 中文开发参考手册》是一份详尽的指南,旨在帮助开发者深入理解并有效地利用Spring框架2.0版本进行Java应用程序的开发。Spring框架是Java平台上一个核心的开源框架,它主要关注应用的后端开发...
3. **Bean工厂与ApplicationContext**:在Spring 2.0中,Bean工厂是基础的容器,而ApplicationContext是更高级的容器,提供了更多的企业级服务,如消息源、国际化支持等。ApplicationContext还支持XML和注解配置,...
《Spring Framework 2.0:历史、核心概念与应用》 Spring Framework,作为Java领域最为广泛应用的开源框架之一,自2003年发布以来,为无数开发者提供了强大的支持。在2005年,Spring Framework 2.0的发布带来了许多...
《Spring Framework 2.0--2.5中文参考手册》是针对Spring框架2.0到2.5版本的详尽指南,它包含了该版本范围内的核心概念、特性、API使用及最佳实践。Spring是一个开源的Java平台,它极大地简化了企业级应用开发,通过...
标题“Learning Spring Boot 2.0”指出了本书的目标读者是希望通过Spring Boot 2.0版本进行开发的学习者。Spring Boot是一种基于Java的开源框架,旨在简化新Spring应用的初始搭建以及开发过程。它使用了“约定优于...
总之,Spring Framework 2.0是Spring发展史上的一个重要里程碑,它的各项改进大大提升了开发效率,降低了复杂性,使得Spring成为企业级Java应用的首选框架。对于想要深入理解和使用Spring的开发者来说,对这个版本的...
《Learning Spring Boot 2.0》是一本专为开发者设计的深入指南,旨在帮助读者全面理解和掌握Spring Boot 2.0这一强大框架。Spring Boot以其快速启动、简化配置和易于开发的特点,在Java企业级应用开发中占据着重要的...
Spring Framework。 官网 Spring Framework API。 Spring Framework 开发文档。
在"struts2.0与spring2.0集成实例"中,主要的知识点包括以下几个方面: 1. **Struts2.0**:Struts2.0的核心是Action类,它是业务逻辑的入口点。它通过配置文件(struts.xml)与前端视图(JSP)和后端模型...
Get up to date with the defining characteristics of Spring Boot 2.0 in Spring Framework 5 Learn to perform Reactive programming with SpringBoot Learn about developer tools, AMQP messaging, WebSockets,...
在2.0中,它加强了与其他Spring Cloud组件的集成,提高了通信效率。 7. **服务认证和授权**: Spring Cloud Security提供了安全相关的工具,包括OAuth2、JWT等,帮助构建安全的微服务架构。2.0版本对安全策略进行...
这个"spring oauth2.0 例子"是一个在MyEclipse集成开发环境中创建的示例项目,用于演示如何在Spring框架中实现OAuth2.0认证和授权流程。 首先,OAuth2.0的核心概念包括客户端、资源所有者(用户)、授权服务器和...
spring-framework-2.0-with-dependencies.zip spring-framework-2.0-with-dependencies.zip spring-framework-2.0-with-dependencies.zip spring-framework-2.0-with-dependencies.zip spring-framework-2.0-with-...
《Learning Spring Boot 2.0 Second Edition》是学习Spring Boot 2.0的重要参考资料,它深入浅出地介绍了这个流行的Java开发框架的核心概念和技术。Spring Boot简化了Spring应用程序的初始搭建以及开发过程,旨在...