Nirvana Studio » 2006 » 五月 :: 分享知识,传播技术

Archive for 五月, 2006

克隆的反攻

Posted by ShiningRay on 31st 五月 2006

  • 题目:Attack of the Clones
  • 译名:克隆的反攻
  • 作者:James Noble & Brian Foote
  • 翻译:ShiningRay
  • 摘要:Self是一个基于原型的编程语言,常常被说成“比Smalltalk还Smalltalk”的。本文将展示Self中的一些设计模式的实现,并且指出Self中实现和其他面向对象编程语言之间的区别。
  • 中文版:PDF
  • 英文原文:PDF

Copyright © 2002, Australian Computer Society, Inc. 本文已发表在程序模式语言第三次亚太会议上。 (KoalaPLoP 2002), Melbourne, Australia. Conferences in Research and Practice in Information Technology, Vol. 13. James Noble and Paul Taylor, Eds. 允许以学术、非盈利的目的进行复制,并保证文中包含这些版权声明文字。

Posted in SELF, 设计模式 | 1 Comment »

Self:简洁的威力

Posted by ShiningRay on 31st 五月 2006

  • 题目:Self: The Power of Simplicity
  • 译名:Self:简洁的威力
  • 作者:David Ungar 及 Randall B. Smith
  • 翻译:ShiningRay
  • 摘要SELF是一个针对探索式编程的面向对象语言,它基于几个很简单和具体的概念:原型、槽和行为。原型结合了继承和实例化,以提供一个比当前大多数面向对象语言更简单更有弹性和框架。槽则将变量和过程统一成一个结构,这就可以令继承层次取代传统语言中的词法范围的功能。最后,因为SELF并不区别对待状态和行为,所以他减少了普通对象、过程和闭包之间的差别。SELF的简洁和表现力给面向对象计算提供了一种全新的视角。
  • 中文版下载:PDF
  • 英文原文: Self: The Power of Simplicity

”OOPSLA ‘87 Conference Proceedings, pp. 227-241, Orlando, FL, October, 1987.
Published as SIGPLAN Notices 22(12), December, 1987. Also published in Lisp and Symbolic Computation 4(3), Kluwer Academic Publishers, June, 1991. ”

Posted in SELF | 3 Comments »

jBPM 流程部署文件研究

Posted by Nicholas Ding on 29th 五月 2006

jBPM 为流程定义及其相关文件专门使用了一种打包机制,就是.par文件,似乎JBoss很喜欢这样的形式,之前还有为Hibernate提供的.har包。这个.par被称为Process Archive,故名思义,里面包含了流程需要的所有信息。

其实.par文件就是一个简单的zip格式的压缩包。里面的核心文件是processdefinition.xml这个流程定义,当然用Eclipse jBPM插件制作的流程还含有一个流程图片,可以使用jBPM提供的webapp动态标示当前所执行的流程。除次之外,classes这个目录以内的文件都会被动态加载到内存,因为流程里面定义的Action和Task等的实现类都需要去Classpath找,jBPM会在部署.par包的时候用自己的Class Loader加载进去。(PS:也可以直接放在上层Classpath里面,只要能够加载到就可以)

流程部署详解

如果认为一定要使用Eclipse jBPM插件来部署流程的话,那就错了,jBPM插件从一定程度上简化了jBPM开发,尤其是Deployment功能为大家省了不少事情,但是如果要手工部署,怎么做呢?接下来就要研究一下到底部署这个.par文件的时候做了哪些事情。

首先要让Eclipse jBPM的部署功能有效,那么要确保服务器使用jBPM提供的webapp,并且让起Context位于/jbpm这个位置。例如http://localhost:8080/jbpm,那么在jBPM插件里面写上localhost,端口8080,测试一下连接就可以了。那么我们分析一下webapp,发现原来是org.jbpm.webapp.servlet.UploadServlet这个类在起作用。

看一下UploadServlet的代码,看handleRequest里面的内容,用Commons Fileupload做的文件上传,如果文件小直接加载到内存,文件大会用磁盘的临时空间(Fileupload的文档上有解释)。文件上传完毕,那么就执行doDeployment操作。这个doDeployment才是部署的关键入口。

ZipInputStream zipInputStream = new ZipInputStream(fileItem.getInputStream());

这行代码解释了如何加载.par文件,首先作为Zip格式读取,然后得到jbpmContext来进行流程部署。这个JbpmContext也是采用了ThreadLocal,感觉原理上和Hibernate用的差不多(到这篇文章为止,我在Weblogic还没法成功使用这个得到jbpmContext,还只能用jbpmConfiguration来获取)。
JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext();
ProcessDefinition processDefinition = ProcessDefinition.parseParZipInputStream(zipInputStream);
jbpmContext.deployProcessDefinition(processDefinition);

这样以来,一个流程就这么简单的部署上去了。当然了,如果不想Upload,还可以使用本地文件系统直接部署,需要提供一个URL就可以了,请参考DeployServlet,还可以使用ant进行部署。
这么看来,部署一个流程就变得非常方便了。

部署文件怎么就消失了,到底去了哪里?

在部署完.par流程包之后,仿佛就不再需要这个.par文件了,但是是什么原因能够让服务器不必知道.par的位置而又能每次正常运行这个流程呢?这个问题我诼磨了很久,一个zip文件不可能凭空消失啊,至少他应该存在于引擎可以找到的地方。而这个地方,正是数据库!

看一下jbpm生成的数据库,包含两张比较特别的表jbpm_bytearray和jbpm_byteblock,正是这两张表纯储了.par文件的内容。可以说,他是将zip里面的内容拆开存到了数据库。

mysql> select * from jbpm_bytearray;
+-----+------------------------------------------------------+-----------------+

| ID_ | NAME_                                                | FILEDEFINITION_ |

+-----+------------------------------------------------------+-----------------+

|   1 | processimage.jpg                                     |               1 |

|   2 | gpd.xml                                              |               1 |

|   3 | processimage.jpg                                     |               4 |

|   4 | gpd.xml                                              |               4 |

|   5 | classes/com/sample/action/MessageActionHandler.class |               4 |

+-----+------------------------------------------------------+-----------------+

jbpm_bytearray这张表把.par文件目录存了进去,jbpm_byteblock则是将二进制内容存了进去。可以说如果你的.par文件里面含有Java Bytecode,那么引擎会从数据库读出byte[]数组然后作为类加载,如果你的类存在于引擎可见的Classpath,那么他会从那里面加载。

总结

jBPM在流程的部署上着实下了不少功夫,从流程的部署上可以看到jBPM引擎的一些工作方式,这也有点类似IoC的概念,本身jBPM提供了基于有限状态机的编程模型,这一模型大大的简化了编程难度,同时将流程的定义和实现分离出来,使得可以在流程实现的功能子集定义新的流程。
在流程部署上提供了版本机制,即连续部署两个相同的流程会出现版本增量,总是新建高版本的流程,但是低版本的流程在执行过程中不会因为高版本的部署而自动取消,直到运行完毕。

Posted in Java | No Comments »

AJAX 入门

Posted by Nicholas Ding on 17th 五月 2006

AJAX in Action

像其他人一样,当我看到一下RIA应用,例如Google Maps和Google Suggest的时候我都非常惊讶。我希望知道是如何实现的。现在,谜底揭开了,那就是AJAX。这是在我花了一段时间研究AJAX之后才知晓的。这里有一个很好的例子让我们知道AJAX是如何很好的应用在 JavaRSS.com 里面的。

什么是AJAX:
AJAX 是一个架构(architecture)并不是一种技术。AJAX代表异步的JavaScript和XML。
妙语(Punch Line):
延迟加载
问题:
当JavaRSS.com首页加载时,他同时加载了所有条目的介绍(如果你在设置中激活了)。这些介绍只有当你鼠标移动到该条目的上面的时候才显示。

现在的问题是用户不可能是鼠标移过所有的条目,所以预先加载所有的介绍不是个好主意。

解决方案: 使用AJAX,当鼠标移过的时候从服务器动态加载条目的介绍。

这么做可以使初始页的加载大小减小一半甚至更多,这样一来页面加载就更快,就内能得到一个更好的用户体验。

时序图:

AJAX Sequence Diagram

我们首先会在onmouseover事件中调用JavaScript函数getDescription。下面是html代码:

<a href="/" onmouseover="getDescription(3,1)">Java & J2EE News</a>

下面是 getDescription 函数的代码:

var url = 'http://localhost:8080/getDescription.jsp?channelId=' + channelId + '&itemId=' + itemId;
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        req = new ActiveXObject("Microsoft.XMLHTTP");
    }
    req.onreadystatechange = processRequest;
    req.open("GET", url, true);
    req.send(null);

XMLHttpRequest 对象将用来进行http连接并取回xml文档。我们需要检测一下是否是IE并且创建 XMLHttpRequest 对象。

if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        req = new ActiveXObject("Microsoft.XMLHTTP");
    }

设置回调函数,并且发送”GET”请求至服务器接收xml文档:

req.onreadystatechange = processRequest;
    req.open("GET", url, true);
    req.send(null);

JSP将根据适当的条目编号创建具有相应介绍的xml文档。

<%
String channelId = request.getParameter("channelId");
String itemId = request.getParameter("itemId");
//String description = new Channel(channelId).getItemDescription(itemId);
String description = "This is the description for the channelId: " + channelId + "and itemId: " + itemId;
 
if (description != null) {
   response.setContentType("text/xml");
   response.setHeader("Cache-Control", "no-cache");
   response.getWriter().write("<description>" + description.toString() + "</description>");
} else {
   //nothing to show
   response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
%>

检测HTTP请求返回状态码,状态为200,即OK。

function processRequest() {
    if (req.readyState == 4) {
        if (req.status == 200) {
          parseMessages();
        } else {
  alert ( "Not able to retrieve description" );
        }
    }
}

readyState = 4 的情况下文档被加载。

readyState Status Codes:

  • 0 = uninitialized
  • 1 = loading
  • 2 = loaded
  • 3 = interactive
  • 4 = complete

最后,我们解析XML文档并显示介绍。

问题: 唯一的问题就是我遭遇到的 “&” 字符。 “&” 在XML文档里面不是一个有效字符。所以我需要将他转换成 “&amp;”。

function parseMessages() {
	response  = req.responseXML.documentElement;
	itemDescription = response.getElementsByTagName('description')[0].firstChild.data;
	alert(itemDescription);
}

下面是所有的代码:

HTML Code:

<a href="/" onmouseover="getDescription(3,1)">Java & J2EE News<a>

JavaScript Code:
function getDescription(channelId,itemId) {
    var url = 'http://localhost:8080/getDescription.jsp?channelId=' + channelId + '&itemId=' + itemId;
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        req = new ActiveXObject("Microsoft.XMLHTTP");
    }
    req.onreadystatechange = processRequest;
    req.open("GET", url, true);
    req.send(null);
}
 
function processRequest() {
    if (req.readyState == 4) {
        if (req.status == 200) {
          parseMessages();
        } else {
          alert ( "Not able to retrieve description" );
				}
    }
}
 
function parseMessages() {
	response  = req.responseXML.documentElement;
	itemDescription = response.getElementsByTagName('description')[0].firstChild.data;
	alert ( itemDescription );
}

JSP Code:
<%
String channelId = request.getParameter("channelId");
String itemId = request.getParameter("itemId");
description = "This is the description for the channelId: " + channelId + "and itemId: " + itemId;
 
if (description != null) {
   response.setContentType("text/xml");
   response.setHeader("Cache-Control", "no-cache");
   response.getWriter().write("<description>" + description.toString() + "</description>");
} else {
   //nothing to show
   response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
%>

资源:

使用AJAX的Google站点:

关于作者:

  • Jay 具有10年以上的IT工作经验,并且自从Java & J2EE诞生那天起就开始接触他们了。
  • 译者Nicholas@NirvanaStudio

Posted in Ajax | No Comments »

什么是 Cake?

Posted by ShiningRay on 1st 五月 2006

Cake 是一个针对PHP的,使用了诸如ActiveRecordAssociation Data MappingFront ControllerMVC等知名设计模式的快速开发框架。我们的主要目标是提供一个可以令各种层次的PHP用户快速地开发出健壮的Web应用,而又不失弹性。

为什么使用 Cake?

  1. 灵活的许可证MIT License
  2. 完全自主的知识产权:每一行代码都是由CakePHP开发小组写出来的。
  3. 极其简洁:只要看看名字就知道了……
  4. 快速开发:开发之迅速史无前例。(看看zZine的文章
  5. 最佳实践:Cake很容易理解,而且已经把工业标准设置在了安全性、会话处理和其他的东西中。
  6. 面向对象: 无论你是一个老练的OO程序员还是一个初学者,都可以感到十分轻松。
  7. 无需配置:只要安装好数据库,好戏就开场了。

厌倦了不断重复?总是Ctrl-C然后Ctrl-V代码?想让你的应用更快速地转化成产品?请选择Cake!看看Wiki立刻上手。

关键特性

  • 兼容 PHP4 和 PHP5
  • 提供了集成的数据库 CRUD 和简化了的查询
  • 请求分配器,和美观的、可自定义URL。
  • 快速、灵活的模版机制(使用PHP语法和助手方法)
  • 可以从任何网站的子目录中运行,只需要少量甚至无需改动Apache的配置。

立刻加入

我们一直在寻找人手来帮助我们写指导、进行测试和书写文档。参与的最佳地点就是IRC。我们正在完善一些针对希望对这个项目编写代码的贡献者指导方针。当然,任何人都可以提出您宝贵的意见和建议。
#cakephp at irc.freenode.net ? CakePHP Wiki ? CakePHP Google Group ? CakeTRAC (development site)

指南

Posted in PHP | 3 Comments »