每日一得

不求多得,只求一得 about java,hibernate,spring,design,database,Ror,ruby,快速开发
最近关心的内容:SSH,seam,flex,敏捷,TDD
本站的官方站点是:颠覆软件

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  220 随笔 :: 9 文章 :: 421 评论 :: 0 Trackbacks

#

key words: radio的值 Form

在jsp中获取radio的值很容易,直接 request.getParameter("myRadio");
但是在js中不行,我试验了一下,如果选择第一个没问题,但是你选第二个第三个的话就出现undefined.办法如下:

function Foo()
{
    
var selectedIndex = -1;
    
var form1 = document.getElementById("form1");
    
var i = 0;
    
    
for (i=0; i<form1.r.length; i++)
    {
        
if (form1.r[i].checked)
        {
            selectedIndex 
= i;
            alert(
"您选择项的 value 是:" + form1.r[i].value);
            
break;
        }
    }
    
    
if (selectedIndex < 0)
    {
        alert(
"您没有选择任何项");
    }
}


posted @ 2006-08-21 19:12 Alex 阅读(13692) | 评论 (7)编辑 收藏

key words: 脚本编码 中文乱码 js
在jsp中,通过js访问java代码比较容易(不过,也有缺陷,比如java代码的声明必须先于js),反过来则不方便,网上看到有通过其他组件的方式来做,感觉也不是很好,其实平时用的更多的是在js中有中文编码,而需要到下一个jsp页面中得到这个对应的值。

js中有函数escape和unescape,可惜的是java.net.*中的编码和解码与js的不一致,所以他们不能协同工作,有一个方法就是在java中重新实现一遍js里对应的方法,代码如下:
/**
 * java版本的escape和 unescape[对应javaScript里的函数]
 
*/
public class EscapeUnescape {
    
/**
     * escape ==> escape
     * 
@param src
     * 
@return String
     
*/
    
public static String escape(String src) {
        
int i;
        
char j;
        StringBuffer tmp 
= new StringBuffer();
        tmp.ensureCapacity(src.length() 
* 6);
        
for (i = 0; i < src.length(); i++) {
            j 
= src.charAt(i);
            
if (Character.isDigit(j) || Character.isLowerCase(j)
                    
|| Character.isUpperCase(j))
                tmp.append(j);
            
else if (j < 256) {
                tmp.append(
"%");
                
if (j < 16)
                    tmp.append(
"0");
                tmp.append(Integer.toString(j, 
16));
            } 
else {
                tmp.append(
"%u");
                tmp.append(Integer.toString(j, 
16));
            }
        }
        
return tmp.toString();
    }

    
/**
     * unescape ===>js
     * 
@param src
     * 
@return String
     
*/
    
public static String unescape(String src) {
        StringBuffer tmp 
= new StringBuffer();
        tmp.ensureCapacity(src.length());
        
int lastPos = 0, pos = 0;
        
char ch;
        
while (lastPos < src.length()) {
            pos 
= src.indexOf("%", lastPos);
            
if (pos == lastPos) {
                
if (src.charAt(pos + 1== 'u') {
                    ch 
= (char) Integer.parseInt(src.substring(pos + 2, pos + 6), 16);
                    tmp.append(ch);
                    lastPos 
= pos + 6;
                } 
else {
                    ch 
= (char) Integer.parseInt(src.substring(pos + 1, pos + 3), 16);
                    tmp.append(ch);
                    lastPos 
= pos + 3;
                }
            } 
else {
                
if (pos == -1) {
                    tmp.append(src.substring(lastPos));
                    lastPos 
= src.length();
                } 
else {
                    tmp.append(src.substring(lastPos, pos));
                    lastPos 
= pos;
                }
            }
        }
        
return tmp.toString();
    }
}


posted @ 2006-08-21 18:02 Alex 阅读(648) | 评论 (0)编辑 收藏

     摘要: OSWorkflow的第一支程式 (史帝芬, 2005/6/4, hi.steven@gmail.com) 自從C的聖經版以Hello World程式開始引導初學者學習程式語言以來,...  阅读全文
posted @ 2006-08-15 16:25 Alex 阅读(4326) | 评论 (0)编辑 收藏

key words : textarea空格问题
<textarea name="parentRemark" rows="10" cols="80" class="editor">
<%=rem[7]==null?"":rem[7]%>
</textarea>

猜猜这个textarea会有什么问题?

效果如下:

jiazhang.png

是不是很奇怪,哪来的空格啊,还以为从数据库中取出的数据有空格,检查也不是,后来才知道,原来是textarea换行惹得祸,不换行就OK了

<textarea name="parentRemark" rows="10" cols="80" class="editor"><%=rem[7]==null?"":rem[7]%></textarea>

posted @ 2006-08-15 11:08 Alex 阅读(352) | 评论 (0)编辑 收藏

十大事件

1990-1994:Java缘起
文/孟岩

Larry Wall说,优秀程序员应有的三个特点:懒惰、急躁和傲慢。Java就是诞生在一群懒惰、急躁而傲慢的程序天才之中。
1990年12月,Sun的工程师Patrick Naughton被当时糟糕的Sun C++工具折磨的快疯了。他大声抱怨,并威胁要离开Sun转投当时在Steve Jobs领导之下的NeXT公司。领导层为了留住他,给他一个机会,启动了一个叫做Stealth(秘密行动)的项目。随着James Gosling等人的加入,这个项目更名为Green。其目标是使用C++为嵌入式设备开发一种新的基础平台技术,James Gosling本人负责开发一个SGML编辑器。正如人们事后分析的那样,这位天才的程序员太懒惰,所以没有把C++学好,开发中碰了一头包;太急躁—— 所以不愿意停下来读读Scott Meyers的新书《Effective C++》;太傲慢——所以轻易地决定开发一中新的编程语言。他把这种语言命名为C++++--,意思是C++“加上一些好东西,减去一些坏东西”。显然这 个糟糕的名字不可能长命百岁,很快这种颇受同伴喜爱的小语言被命名为Oak。
到了1992年9月,Oak语言连同Green OS和一些应用程序一起发布在称做Start 7的小设备上,从而使之有了第一次精彩的亮相。随后,Sun开了一家名为FirstPerson的公司,整个团队被转移到这家公司里研发机顶盒,以投标时 代华纳公司的一个项目。这帮天才被技术狂热所鼓舞,开发出了一个高交互性的设备,结果没想到时代华纳公司和有线电视服务商并不愿意用户拥有那么大的控制 权,从而在竞标之战中败给了SGI。Oak的锋芒之锐,竟然把客户都给吓懵了。Sun沮丧地关闭了FirstPerson,召回了整个团队。事实证明,传 统行业中那些脑满肥肠的保守主义者是腐朽没落的。回去!回到激情澎湃的IT产业,抓住互联网的大潮,这才是出路!1994年,Oak被命名为Java,针 对互联网的新一轮开发如火如荼,一切已经就绪,熔岩在地下奔流,火山即将喷发。


1995: Java香浓世界
文/马伟

1995年,Sun正式对外公布了Java,并且发布了JDK 1.0。这种外形酷似C++,却包含一颗Smalltalk般纯洁的面向对象之心的全新程序设计语言及其平台,几乎在一夜之间就成为软件产业的新宠儿。 Java当时仅仅被用来为网站制作一些动态应用,诸如动画图片之类,但这仍然引起了很多Web开发者们的注意,他们非常渴望有一种安全的语言,可以在静态 的HTML网页上制作动画图片。Sun最终把Java集成到NetScape浏览器。同时因为它具有“只写一次,随处运行”的特性,而引起了很多开发者的 注意,他们可以再也不用为了使程序能够在不同型号的硬件上运行而耗费大量的时间来编译代码了。
当时的Web浏览器的出现也为Java的出现起到了很好的推动作用,通过Java和Web浏览器的结合,人们似乎看到了什么,有人甚至预言PC 将在一两年内退出历史的舞台,取而代之的是基于Java的浏览器应用程序,通过网络计算设备来进行应用。Java的出现为当时的软件产业带来了无限的遐 想。


1996:Java大跃进,盟主地位就此定
文/马伟

SUN在1996年一开始首先成立了JavaSoft组织,并在1月23日正式发布自己的Java 1.0,作为20世纪业界出现的最重要的技术之一,Java引起了编程世界的革命。直到现在,Java仍然是互联网上最流行的语言。
在Sun正式发布Java 1.0之后,Java这门新生的语言就拥有了自己的会议——JavaOne,这次会议初试啼音就吸引了600多名参与者。除了拥有这么多的积极参与者来进 行Java的开发之外,各大知名公司也纷纷向Sun申请Java的许可。一时间,NetScape、惠普、IBM、Oralce、Sybase甚至当时刚 推出Windows 95的微软都是Java的追随者。
Java的应用就像是世界上的顶级玩家们组成的一个公开联盟,告诉全世界我们大家就是都在用着Java。也正是因为如此,Java也找到了自己的归宿。现在的J2EE已经成为中大型企业级应用的标准,成为承接数据库和Web之间的一个重要桥梁。
当年Java的机会实在太多了,以至于很难知道到底该做什么。最终Java在应用服务器市场获得了难以取代的地位,也确定了J2EE的发展方向,并且仍将延续下去。


1997-2001: 微软与Sun的Java官司
文/孟岩

Java诞生的1995年,正是微软在软件产业地位达到巅峰的时代,Windows 95发布时的风光场面给人们留下的深刻印象至今难忘。尽管如此,作为最卓越的技术领袖,比尔?盖茨仍然敏锐地注意到Java。当他了解了Java的一些细 节之后,给予了这样的评价:“Java是很长时间以来最优秀的程序设计语言。”基于此,微软于1996年3月申请并获得了Java许可证。微软对于 Java的这一热情态度在当时大大提高了人们对Java的兴趣和信心,但也有不少人担心微软会依靠自己强大的影响力在标准之外另立标准,从而破坏Java 的纯洁性。
果然,从1997年发布Visual J++的第一个版本开始,微软就开始在Java中掺入自己的私有扩展。这毫无疑问引起Sun的高度重视。1997年10月,Sun向美国加州地方法院起诉 微软公司违反两公司就微软使用Java技术所签定的合同,指控微软公司在自己的Java产品中做了“不恰当的修改”,违反了合同中承诺向用户提供Java 兼容产品的条款。这一官司旷日持久,直到2001年1月双方达成和解,微软将继续提供采用Sun开发的Java技术的现有产品(包括测试版)。不过, Sun有限制地仅对包括Java 1.1.4的微软产品提供许可。到了2001年7月,微软公布新版的Windows XP将不再支持Sun的JVM,并且推出了.NET平台与Java分庭抗礼。
现在回过头去看,当时的这一场官司对Java世界产生了深远的影响。如果没有这一场官司,也许很多Java程序员都在使用Visual J++,基于WFC开发Windows客户端程序,同时不得不面对被两个不同的事实标准所分裂的Java世界。


1998:Java 2平台发布
文/陶文

1998年,Java 2平台正式发布。经过了三年时间的发展、热热闹闹的攻关宣传、红红火火的众厂商的热情参与,Sun终于知道Java适合干什么了。对比Java刚发明时的 技术定位,与Java的戏剧性触“网”的那段历史,Java 2平台的发布可真算得上是有的放矢了。根据官方的文档,Java 2是Sun意识到“one size doesn’t fit all”之后,把最初的Java技术打包成三个版本的产物,也就是著名的J2ME、J2SE、J2EE。
之所以说Java自从Java 2平台发布之后,进入了现代。那是因为之前的历史怎么看来都和现在程序员日常开发使用的技术无什么关系,比如Applet,已经很少有人使用了。Java 2之后的历史就不一样了,至少人们在推崇轻量级开发,猛批EJB时还不时会引用J2EE这个词是如何诞生的。而Java 2的三大版本中,除了J2EE得到了长足发展和广泛使用之外,J2ME也在手机市场上取得了遍地开花的结果。相较之下,J2SE难免落寞,只剩SWT这个 血统不纯的家伙在Rich Client回归的时代吸引着人们的眼球了。无论今天看来当时的Java 2有多么的不成熟,至少经过市场和时间的检验,Java 2规划出来的三大方向把Java技术指向了光明的方向是勿庸置疑的。


1998:JCP成立并正式运作,
Java开源社群开始蓬勃发展
文/黄海波

1998年,JCP组织成立,并且开始把握Java的发展方向。JCP组织的开放性,不但使得所有对Java感兴趣的商业公司可以参与Java的 发展,更重要的是JCP允许个人、非盈利组织、学校等加入,这就给Java带来了巨大的活力。随之兴起的Java开源运动的最大贡献是实现和鼓励了知识共 享,在众多热情的开源程序员们的努力和分享下,很多原先只被商业公司掌握的技术、思想和产品可以被所有需要的开发人员免费或者以较低的价格获得使用权, 并通过开放源代码更容易的获得反馈和改进意见从而进一步演化发展。我们知道,所谓知识不是孤立发展认知,而是人们的经验,认识是思考交流和积累的产物。而 开源运动所带来的开放、反馈、交流的风气正是符合人类社会知识形成和发展的规律。
开源运动起源于西方的发达国家,有其现实背景和文化根源。1990年代可以说是IT产业的一个黄金时代。信息时代的兴起对IT人员,特别是软件 人员有着巨大的需求。而软件开发又是一种类似艺术创作的脑力活动,和所有的艺术家、作家们一样,在作品打上自己的印记并流传在世界上是每一个创作人员的梦 想。互联网时代下的高收入的舒适生活,早九晚五的编写公司的代码并不能满足很多有激情的软件开发人员的梦想,再加上西方传统的基督教文化中十分推崇的分享 和交流,开源的出现和兴起也就水到渠成了。今天,开源运动已经不仅仅是一些个人天才程序员们的游乐园地,而是发展成为一项开源软件产业。


1998:WebLogic打开J2EE的魔匣
文/霍泰稳

Java语言的出现使得互联网络有了良好的交互性能,但这些很“酷”的技术仅被人们认为是一些小花招,它还无法消除企业级用户对它的怀疑。 1998年,BEA公司宣布收购WebLogic公司,并接着推出由Sun公司第一个授权使用J2EE许可证的WebLogic Server应用服务器,这个Java版的AppServer一推出就引起业界极大的兴趣。WebLoigc Server以其对标准的支持、强悍的运算能力和安全的架构设计等特性也很快征服了那些怀疑J2EE应用的人们。推出市场后不到一年,WebLogic Server就成为业内第一Java应用服务器。
这里我们援引一些当时著名咨询公司的调查数据来说明问题,“在IDC的报告中,BEA在应用服务器和交易服务器领域市场份额第一;在 Gartner的报告中,BEA WebLogic Server拥有业内最广泛的EJB应用安装基础;在Giga Group的报告中,BEA WebLogic Server市场份额占32%”。
因为应用服务器市场极大的发展潜力,在WebLogic Server之后,其它的很多公司也推出了自己的AppServer,如IBM的WebSphere、Sun公司的iPlanet等,逐渐地应用服务器取 代了传统意义上的各类中间件,成为企业应用的基础平台。应用服务器的出现使得Java有了真正意义上的发展。


2002-2004: Sun与微软的法律碰撞最终以喜剧收场
文/恶魔

2003年4月2 日,Sun与微软达成16亿美元的法律和解。如果不是晚了一天,许多人会以为这是一个在4月1日愚人节开的玩笑。尽管当时所有人都像是看到“太阳从西边出来了”那样张大了嘴巴,但这的确是事实。
根据两家公司达成的版权协议,双方会为采用对方的技术而支付专利费用,微软向Sun提前支付3.5亿美元使用费,Sun则承诺,如果Sun集成微软的某些技术,也会向微软付款。
毫无疑问,“私下了结”的方式对双方而言都是最好的结果。就在协议签署的当天,在美国旧金山由Sun和微软为“抛弃十年恩怨、携手合作“举行的新 闻发布会上,尽管比尔?盖茨没有到场,但这并没有防碍现场看起来异常轻松的气氛。麦克尼利和鲍尔默各自穿了一件密歇根州底特律“Red Wings”曲棍球队的运动服,并谈及了一起在哈佛大学读书的经历,麦克尼利还说:“当时我们两人是非常要好的朋友,当然我们也有吵架的时候。”人与人当 然可能成为终生的知己,但是公司与公司之间有的只能是利益上的分分合合。


2000-2004: JBoss和Eclipse
——Java开源软件的王者
文/莫映

Java和开源几乎就是天生的一对,这可以从无比兴盛繁荣的Java开源软件社区得到佐证。目前最有影响力的Java开源软件项目,要数 JBoss和Eclipse。可以说,几乎所有的Java开发人员都获多或少的听到过或接触和使用过它们。前者是目前最优秀、应用最为广泛的企业级开源 J2EE应用服务器,后者是功能完全可以替代商业产品的Java IDE。二者的覆盖功能之全、支持工具之广、子项目之多,几乎可以仅凭借它俩来完成企业应用的开发构建到部署实施的全过程,而软件开发者和客户也都可以最 大程度上享受高质量,高可靠Java开源软件所带来的低成本优势。
JBoss和Eclipse的巨大成功,几乎令各自领域的商用竞争者抓狂,其中BEA的WebLogic和IBM的WebSphere在商业利 润上受到JBoss的巨大侵蚀,而Borland的JBuilder、JetBrains的IDEA等诸多优秀的商用开发工具也不得不面对Eclipse 独大的现实。JBoss的CEO兼创始人 Marc Fleury曾直言不讳地表示,希望占据市场主导地位。“我们希望打败IBM,成为中间件领域里最大的厂商。”JBoss在4.0以前还只是以一个 Group存在,盈利手段主要靠服务和销售文档。但在最近,JBoss已经发展成为一个有限公司,并吸纳多家风险投资,专注于获取利润为目标之一的第二代 开源软件模式(JBoss自己称为“Professional Open Source”)的创新和运营。这区别于以理论研究为爱好的学院型开源或大公司为基础的非盈利组织开源,如Linux和Apache。当然JBoss的这 种运营方式势必会导致更多的代码控制和专有修改权,但按JBoss的说法是这样更能获得企业客户的信赖。JBoss的这种模式是否能获得成功还要我们拭目 以待。
不管JBoss和Eclipse的未来发展如何,JBoss和Eclipse的成功已经让我们看到了Java开源软件的威力,祝愿它们一路走好。


2004:Java 5.0
文/莫映

2004年9月30日,代号为“Tiger”,研发历时近三年的J2SE 5.0发布正式版本,这是Java平台历来发布版本中改动面波及最大的一次。
纵观Tiger,“Ease of development”是其核心主题,这一点着重体现于语言特性上的改进,这在很大程度上,简化了开发人员日常的编程任务,以往一些琐碎的手工劳动都代 之以轻松自然,而又安全可靠的自动化实现。其中的注解功能,以及随之而来的声明式编程,还对构筑于J2SE 5.0之上的J2EE 5.0产生了巨大影响。尽管Tiger在语言特性上做了很大的动作,但作为Java技术的基础支撑,这些改动都是深思熟虑的结果。
Tiger发布至今也有大半年了,那么Sun又是如何规划J2SE的未来蓝图的呢?据悉,J2SE的下两个版本分别是代号为“Mustang” 的J2SE 6.0和代号为“Dolphin”的J2SE 7.0,预计Mustang将于明年发布。在吸取了Tiger研发周期过长的教训之后,Sun副总裁Graham Hamilton表示,Mustang的发布周期将不会那么长。并且,Sun还将“Becoming more open” 作为Mustang的主题之一。未来JCP对Java技术的影响将会愈加深入,而整个研发过程也将会愈加透明。Mustang在正式发布前的内部版本也会 陆续见诸于众,如此,广大Java开发者便可以更加及时的了解到Java发展的最新情况。在语言层面上的扩展依然会比较谨慎,比如像AOP这样的当下热门 技术,依然不太可能会见诸其中。据Hamilton所言,一个有可能被引入的语法特性被称作“friends”import机制,它将使由多个包组成的大 型项目变得易于管理。

----------------------------------------------------------------------------------------


十大人物

James Gosling : Java之父
文/陶文

作为Java之父,James Gosling的名字可谓是耳熟能详。当人们评论一种编程语言时,总喜欢捎带着把下蛋的母鸡一起带上。Java做为中国的编程语言学习者餐桌上有限的那么 几样餐点中的流行款式,自然是让James Gosling风光不已。虽然James Gosling现在已经不是领导Java发展潮流的领军人物了,做为Sun的开发者产品组的CTO,怎么算来也是身居高位了,俗事缠身吧,但是这并不妨碍 其对于Java一如既往的爱护,表达着各式各样鲜明的观点,引发一场又一场的争论。
James Gosling是很爱Java的——是啊,哪有当父母的不爱自己的孩子的呢。James Gosling也是很爱Sun的——是啊,哪有当领导的不爱自己的公司的呢。于是我们在批评.NET的安全性的队伍前头,在褒扬Java性能的队伍前头, 在抨击SWT开倒车的队伍前头,在给NetBeans大唱赞歌的队伍前头,我们都看到了James Gosling的身影。无论对错、偏见或者固执,至少说明了Gosling的鲜明个性丝毫没有受到年龄的影响。也许也只有这种天才而偏执的人物才能创造出 Java这般伟大的语言来吧。


Bill Joy : 软件业的爱迪生
文/徐昊

Joy生于1954年,1982年与Vinod Khosla, Scott McNealy和Andy Bechtolsheim一起创建了Sun Microsystems,并从那时起担任首席科学家,直到2003年离开。他是一位令人崇敬的软件天才,他在软件和硬件的历史上留下了无数令人仰止的传 奇。
在上个世纪80年代早期,DARPA与BBN达成协议,准备将Vinton Cerf和Bob Kahn设计的TCP/IP协议添加到Berkeley UNIX中。Bill Joy被委派来完成这项任务,然而他却拒绝将BBN的TCP/IP协议栈添加到BSD中,因为在他的眼中BBN的TCP/IP实现还远不够好,于是他就写 了一个高性能的TCP/IP协议栈。John Gage回忆道,“BBN和DARPA签署了巨额合同来实现TCP/IP协议,然而他们的员工所编写的代码远没有一个研究生所做的好。于是他们邀请 Bill Joy参加他们的一个会议,这位研究生穿着一件T-Shirt就出现了,他们询问他,‘你是如何做到的呢?’Bill回答说,‘这是非常简单的一件事,你 读一下协议然后就可以编码了’”。除了TCP/IP协议,基于分页的虚拟内存系统最早也是由Bill Joy添加到Berkeley UNIX内核当中的。同时他还是vi、csh、早期Pascal编译器的作者。
关于Bill Joy惊人的软件才能流传最广的一个传奇是,据说他在上研究生的时候,想看看自己能不能写一个操作系统出来,于是就在三天里写了一个非常简陋,但是可以使 用的Unix系统, 传说就是BSD的前身。虽然如此夸张的才情令人难以置信,但是考虑到主角是Bill Joy,还是有一定的可信度的。Bill Joy硕士毕业之后,决定到工业界发展,于是就到了当时只有一间办公室的Sun, 他作为主要设计者参与了SPARC微处理器的设计,负责设计最为关键的一部分电路。这样兼精软硬件的天才实在是让人不得不佩服啊。1995年,Sun发布 了轰动世界的Java语言。当然,Bill Joy对Java也作出了不少的贡献,首先是JINI——一种针对分布式服务的基础连接技术。任何可以内嵌JVM的电子设备都可以通过JINI相互连接; JXTA是基于Java的P2P协议,允许互联网上的软件进行点对点交流和协作。
这个其貌不扬的瘦高个,有着凌乱的亚麻色头发,被《财富》杂志誉为“网络时代的爱迪生”的技术狂人,在短短的二十年间,创造了无数令人心动的软 件。在MIT的BBS上曾有一个帖子,说微软电话面试有一道题,问“Who do you think is the best coder, and why?”虽然回复的帖子中大家都声明列举的best coder排名不分先后,然而大多数人仍把Bill Joy列在第一位,或许可以从一个侧面验证Bill Joy在广大Programmer心目中的地位吧。


Joshua Bloch : Java 2 元勋
文/莫映

早在1996年,适逢Java刚刚崭露头角,年内好事连连。先是1月份发布JDK 1.0,然后是5月底在旧金山召开首届JavaOne大会,年末又是JDK 1.1紧跟其后。正是在Java技术如火如荼、大展拳脚的背景之下,Joshua Bloch来到了Sun,开始了他带领Java社区步入“迦南美地”的漫长历程。
很快,他被从安全组调入核心平台组,从事底层API设计。至此以后,每逢JDK的重大版本发布,总能在其中见到Joshua的“妙笔”。JDK 1.1中的java.math、1.4中的assertions,还有大家所熟识的Collections Framework皆是Joshua一手打造。其中的Collections Framework还获得了当年的Jolt大奖。到了J2SE 5.0研发阶段,身为平台组构架师的Joshua接掌了Tiger大旗,其核心地位已然无人可以替代。作为Tiger的代言人和领路人,没有谁比 Joshua更清楚Tiger。相信大家一定还记得Joshua当年仿效英国诗人William Blake所做的咏Tiger诗八首,优雅的笔调,透出大师深厚底蕴的同时,也道出了Tiger的几大重要特性,这些特性是自JDK 1.1引入Inner Class以来,Java最大的语法改进。
Java风雨十年,从JDK 1.1到J2SE 5.0,Joshua实在功不可没。难怪有人戏言,假如将James Gosling比作Java之父,那么Joshua就是一手将Java “哺育”成人的Java之母。Joshua对Java的贡献还不止于JDK,提起他的大作《Effective Java》(Addison Wesley, 2001),相信Java粉丝们一定耳熟能详。该书荣膺2002年度Jolt大奖,且备受James Gosling推崇。书中57条颇具实用价值的经验规则,来自Joshua多年来在JDK开发工作中,尤其是Collections Framework设计中的实践心得,各个有理有据,剖析深入,也足见其深厚功力。该书对Java社群的影响,犹如C++社群中的《Effective C++》。Joshua对JCP的贡献也不小。他是JSR201和JSR175的领导者,前者包含了Tiger四大语言特性,后者则为Java提供了元数 据支持。此外,他还是JSR166的发起人之一(该JSR由Doug Lea领导),并且是许多其他JSR的参与者。Joshua目前是JCP为数不多的几个执行委员会成员之一。
Joshua Bloch给人的印象是谦逊平和,行事低调而不喜抛头露面,一个典型的技术人员和实干家。不过即便如此,也丝毫不会减弱他对Java技术的卓越贡献和对 Java社区的绝对影响力。有人说,如果他能更彰显一些,就很有可能成为Java开发者中的领军人物,就有如Don Box之于微软社群。
2004年7月初,就在Tiger发布在即之时,就在Jusha Bloch刚刚荣获Sun“杰出工程师(Distinguished Engineer)”的称号之时,他突然离开Sun而去了正值发展态势迅猛的Google。当他离开Sun的消息在TSS发布之后,众多拥趸表达了怀念与 不舍之情。一年过去了,我们还没有获知Joshua的任何近闻,似乎又是他行事低调的一贯作风所致,不知他在Google状况如何。希望Joshua依然 能继续“摩西未尽的事业”,以他的影响力推动Java社群继续前行。据称,《Effective Java》的下一版会加入Java 5.0的部分,让我们翘首以待吧。


Bruce Eckel : 功勋卓著的机会主义分子
文/孟岩

Bruce Eckel原本是一位普通的汇编程序员。不知道是什么因缘际会,他转行去写计算机技术图书,却在此大红大紫。他成功的秘诀不外乎两点:超人的表达能力和捕 捉机会的能力。他最早的一本书是1990年代初期的《C++ Inside & Out》,随后,在1995年他写出了改变自己命运的《Thinking in C++》。如果说这本书充分表现了他作为优秀技术作家的一面,那么随后他写作《Thinking in Java》并因此步入顶级技术作家行列,则体现了他作为优秀的机会主义分子善于捕捉机会的另一面。写作中擅长举浅显直接的小例子来说明问题,语言生动,娓 娓道来,特别适合于缺乏实践经验的初学者。因此《Thinking in Java》俨然成为天字第一号的Java教科书,对Java的普及与发展发挥着不可忽略的作用。不过公允地说,Bruce Eckel的书欠深刻。比如在“Thinking in…”系列中对设计模式的解说就有失大师水准。这一方面是因为书的定位非常清晰,另一方面也是因为Bruce太过分心赶潮流,未能深入之故。TIJ之 后,他预言Python将火,就匆匆跑去写了半本《Thinking in Python》。后来Python并未如期而旺,于是他也就把书稿撂在那里不过问了,机会主义的一面暴露无遗。我们也可以善意的猜测一下,他的下一个投机 对象会是什么呢?Ruby?.NET?MDA?总之,是什么我都不奇怪。


Rickard Oberg :J2EE奇才
文/熊节

Oberg的作品很多,流行的代码生成工具XDoclet和MVC框架WebWork都出自他的手笔。这两个框架有一个共同的特点,即它们的功能 虽然简单,但设计都非常优雅灵活,能够很方便地扩展新功能甚至移植到新环境下使用。优雅的设计源自Oberg的过人才华,简单的功能则折射出他玩世不恭的 人生态度。正是这两种特质的融合,才造就了这个不世出的奇才。
1999年,JDK 1.3发布,其中带来了一个重要的新特性:动态代理(Dynamic Proxy)。当所有人都还在对这项新技术的用途感到迷惑时,Oberg发现用它便可以轻松攻克EJB容器实现中的一些难关。这一发现的产物就是一本 《Mastering RMI》,以及大名鼎鼎的JBoss应用服务器。但Oberg很快又让世人见识了他的玩世不恭。由于和总经理Marc Fleury在经营理念上不合,Oberg抱怨“法国的天空总让我感到压抑”,甩手离开了自己一手打造的JBoss。此后的几年里,他和老友Hani Suleiman不断地对JBoss的“专业开源”模式和Marc Fleury的商人味道冷嘲热讽,让众人为他的孩子气扼腕叹息。
2002年10月,微软推出Petstore示例应用的.NET版本,并宣称其性能比Java Petstore高出数倍。正是Oberg深入分析这个示例应用的源代码,在第一时间指出它大量运用了SQL Server专有的特性,性能对比根本不具参考价值。后来Oberg又先后关注了AOP和IoC容器,两者都成为了J2EE架构的新宠。


Doug Lea : 世界上对Java影响力最大的个人
文/KIT

如果IT的历史,是以人为主体串接起来的话,那么肯定少不了Doug Lea。这个鼻梁挂着眼镜,留着德王威廉二世的胡子,脸上永远挂着谦逊腼腆笑容,服务于纽约州立大学Oswego分校计算器科学系的老大爷。
说他是这个世界上对Java影响力最大的个人,一点也不为过。因为两次Java历史上的大变革,他都间接或直接的扮演了举足轻重的脚色。一次是由 JDK 1.1到JDK 1.2,JDK1.2很重要的一项新创举就是Collections,其Collection的概念可以说承袭自Doug Lea于1995年发布的第一个被广泛应用的collections;一次是2004年所推出的Tiger。Tiger广纳了15项JSRs(Java Specification Requests)的语法及标准,其中一项便是JSR-166。JSR-166是来自于Doug编写的util.concurrent包。
值得一提的是: Doug Lea也是JCP (Java小区项目)中的一员。
Doug是一个无私的人,他深知分享知识和分享苹果是不一样的,苹果会越分越少,而自己的知识并不会因为给了别人就减少了,知识的分享更能激荡出 不一样的火花。《Effective JAVA》这本Java经典之作的作者Joshua Blosh便在书中特别感谢Doug是此书中许多构想的共鸣板,感谢Doug大方分享丰富而又宝贵的知识。这位并发编程的大师级人物的下一步,将会带给 Java怎样的冲击,不禁令人屏息以待。


Scott McNealy :SUN十年来的掌舵者
文/KIT

McNealy,Sun的CEO、总裁兼董事长。他曾经狂傲的说:“摧毁微软是我们每个人的任务。”这位英勇的硅谷英雄,似乎带头起义,试图组织 一个反微软阵线联盟,以对抗微软这股庞大的托拉斯恶势力。他时常口出惊人之语,在公开场合大肆的批评微软,并曾经说微软的.NET是.NOT。
Scott McNealy先后毕业于哈佛大学及史丹佛大学,分别持有经济学学士学位及企管硕士。1982年MBA毕业的他和三个同学共同合伙创建了Sun,并于 1984年成为Sun的执行官。“要么吞了别人,不然就被别人吞了”是Scott McNealy的名言录之一。他擅长以信念带动员工,鼓舞士气。极富自信的他,对于认定的事,总是坚持自己的想法,因此有人形容他是一个刚愎自用的决策 者。
身为Sun这艘船的掌舵者,Scott McNealy能够看多远,Sun就能走多远。Scott McNealy认为将来软件界是一个只有服务,没有产品的世代。他希望打造出Sun不是一个纯靠硬件赚钱的公司。从Open Source到Open Solaris,Sun希望可以成为提供整合性解决方案的服务厂商。Solaris 10 + UltraSPARC是否可以像Scott McNealy希望的是下一匹世纪黑马呢?Sun是否能以股价来证明华尔街分析师及普罗大众的诽短流长?Scott McNealy是否能带领着Sun成为继微软之后的下一个巨人,一场场IT界的争霸战值得我们拭目以待。


Rod Johnson : 用一本书改变了Java世界的人
文/ 刘铁锋

Rod在悉尼大学不仅获得了计算机学位,同时还获得了音乐学位。更令人吃惊的是在回到软件开发领域之前,他还获得了音乐学的博士学位。有着相当丰 富的C/C++技术背景的Rod早在1996年就开始了对Java服务器端技术的研究。他是一个在保险、电子商务和金融行业有着丰富经验的技术顾问,同时 也是JSR-154(Servlet 2.4)和JDO 2.0的规范专家、JCP的积极成员。
真正引起了人们的注意的,是在2002年Rod Johnson根据多年经验撰写的《Expert One-on-One J2EE Design and Development》。其中对正统J2EE架构的臃肿、低效的质疑,引发了人们对正统J2EE的反思。这本书也体现了Rod Johnson对技术的态度,技术的选择应该基于实证或是自身的经验,而不是任何形式的偶像崇拜或者门户之见。正是这本书真正地改变了Java世界。基于 这本书的代码,Rod Johnson创建了轻量级的容器Spring。Spring的出现,使得正统J2EE架构一统天下的局面被打破。基于Struts+Hibernate +Spring的J2EE架构也逐渐得到人们的认可,甚至在大型的项目架构中也逐渐开始应用。
Rod Johnson的新作《Expert One-on-one J2EE Development without JEB》则更让人吃惊,单单“Without EJB”一词就会让大多数J2EE架构师大跌眼镜了。不过Rod Johnson可能仅仅是想通过“Without EJB”一词表明应该放开门户之见。这也是Rod Johnson一贯的作风,。也许正是这种思想,促使得Rod Johnson创建了Spring,真正改变了Java世界。



Alan Kay :Java的精神先锋
文/徐昊

Sun的官方Java教材中有一句话,说Java是“C++的语法与Smalltalk语义的结合”。而Smalltalk的创造者就是Alan Kay。
Alan Kay于1970年加入Xerox公司的Palo Alto研究中心。早在70年代初期,Alan Kay等人开发了世界上第二个面向对象语言Smalltalk,因此,Alan Kay被誉为Smalltalk之父。2003年,Alan Key因为在面向对象程序设计上的杰出贡献,获得了有计算机界的诺贝尔奖之称的ACM Turing Award。
Alan Kay成名于Smapltalk和OOP,而Java虽然在语言上类似于C,但是在语义上非常接近Smalltalk,很多Java中的设计思想在 Alan Kay的文献中找到根源,也有些人将Alan Kay尊为Java思想的先驱。不过遗憾的是似乎Alan Kay老先生对Java并不买账,反倒攻击说Java是存在致命缺陷的编程语言,Java的成功不是由于Java本身的内在价值,而是其商业化的成功。 Alan Kay欣赏的是Lisp,他认为Lisp是软件的麦克斯韦方程,其中的许多想法是软件工程和计算机科学的一部分。看来拥有Alan Kay这样一位重量级的Java先驱仍是我们Java一厢情愿的单恋吧。



Kent Beck : 领导的敏捷潮
文:刘铁锋

Beck全家似乎都弥漫着技术的味道。生长在硅谷, 有着一个对无线电痴迷的祖父,以及一个电器工程师父亲。从小就引导Kent Beck成为了业余无线电爱好者。
在俄勒冈州大学读本科期间,Kent Beck就开始研究起模式。然而在他最终拿到计算机学位之前,他却是在计算机和音乐中交替学习。似乎Java大师都能够有这样的能耐,另一Java大牛Rod Johnson同样也拥有音乐学的博士学位。
Kent Beck一直倡导软件开发的模式定义。早在1993年,他就和Grady Booch(UML之父)发起了一个团队进行这个方面的研究。虽然著有了《Smalltalk Best Practice Patterns》一书,但这可能并不是Kent Beck最大的贡献。他于1996年在DaimlerChrysler启动的关于软件开发的项目,才真正地影响后来的软件开发。这次的杰作就是XP(极限 编程)的方法学。
和软件开发大师Martin Fowler合著的《Planning Extreme Programming》可谓是关于XP的奠基之作。从此,一系列的作品如《Test Driven Development: By Example》,《Extreme Programming Explained: Embrace Change》让更多的人领略到了极限编程的精髓,也逐步导致了极限编程的流行。
Kent Beck的贡献远不仅如此。对于众多的Java程序员来说,他和Erich Gamma共同打造的JUnit,意义更加重大。也许正式这个简单而又强大的工具,让众多的程序员更加认可和信赖极限编程,从而引起了Java敏捷开发的狂潮吧。

------------------------------------------------------------------------------------------

十大产品

Sun JDK :Java的基石
文/莫映

众所周知,流传于市的JDK不单Sun一家,比如IBM的JDK、BEA的JRocket、GNU的GCJ,以及如Kaffe这样的开源实现,不一而足。但是,根正苗红的Sun官方JDK一直以来都是备受瞩目的主流,它对Java社区的影响也是举足轻重。
1996年1月,Sun在成立了JavaSoft部门之后,推出了JDK 1.0,这是Sun JDK(Java Development Kit)的首个正式版本;当年12月,JDK1.1出炉。该版除了对前序版本部分特性做了改进以外,重写了AWT,采用了新的事件模型。1998年12 月,JDK 1.2正式发布。此时的类库日臻完善,API已从当初的200个类发展到了1600个类。在1.2版本中引入了用100%纯Java代码写就的 Swing,同时,Sun将Java更名为Java 2。
1999年,Java 技术形成了J2SE、J2EE和J2ME三大格局。Sun向世人公布了Java HotSpot性能引擎技术的研究成果。HotSpot旨在进一步改善JVM性能,提高Java ByteCode的产生品质,加快Java应用程序的执行速度。J2SE 1.3发布于2000年;2002年2月间,J2SE 1.4问世,这是有JCP参与以来首个J2SE的发行版本。2004年9月30日,代号为“Tiger”的J2SE 5.0终于出笼了,这次发布被誉为Java平台历来发布中特性变动最大的一次。包括泛型在内的若干重大语法改进、元数据支持,包括多线程、JDBC在内的 多项类库改进,都令广大Java程序员激动不已。自此,Sun的官方JDK(J2SE Development Kit)已经步入了一个新的高度。



Eclipse :以架构赢天下
文/恶魔

IBM是在2001年以4000万美元种子基金成立Eclipse联盟,并且捐赠了不少程序代码。如今,该组织有91个会员,包含许多全球最大的软件商。根据Evans Data公司的资料,Eclipse是目前最受欢迎的Java开发工具。
Java厂商若要共同对抗微软,彼此之间就要有共同的开发工具才行。
在Eclipse平台上,程序员可使用好几种不同的语言。在前端方面,用户可整合多种工具来撰写Plug-in程序或Unit Test。Eclipse最大的特色就在于其完全开放的体系结构,这代表任何人都可下载并修改程序代码,给Eclipse写插件,让它做任何你能想到的事 情,即所谓“Design for everything but nothing in particular”。
Eclipse基金会的架构比较特别,反映出企业现今对于开放原始码计划也越来越积极主动。Eclipse不像一般开放源码软件容许个人的捐献程序,该基金会是由厂商主导。不论是董事会成员或者是程序赞助者几乎都来自于独立软件开发商(ISVs)的员工。
Eclipse首席执行官Mike Milinkovich说,这种厂商会员制是特意设计的;他说Eclispe软件开发快速就是因为会员制的关系,同时又加上开放源码开发模式的临门一脚。 这与一般透过标准组织的做法全然不同。 这其实正好验证了一句老话:“开放即标准”。


JUnit/Ant : 让Java自动化的绝代双骄
文/刘铁锋

在Java程序员必备的工具中,共 同拥有且交口称赞的恐怕就非JUnit、Ant莫属了。一个是单元测试的神兵利器,一个是编译部署的不二之选,它们让Java的开发更简单。
JUnit由XP和TDD的创始人、软件大师Kent Back以及Eclipse架构师之一、设计模式之父Erich Gamma共同打造。名家的手笔和理念使得JUnit简单而强大,它将Java程序员代入了测试驱动开发的时代。JUnit连任了2001、2002年 “Java World编辑选择奖”以及2003年“Java World最佳测试工具”和2003年“Java Pro最佳Java测试工具”等众多奖项,深受Java程序员好评。
Ant是开源项目的典范,它让IDE的功能更加强大,从Sun的NetBeans到JBuilder,主流的IDE中处处都有它的身影。 “Another Neat Tool”原是它的本名,但这已经渐渐不为人知。它彻底地让部署自动化,而程序员需要做的仅仅是几条简单的配置命令。和JUnit一样,Ant也荣获了众 多的殊荣:2003年JavaWorld“最有用的Java社区开发的技术编辑选择奖”, 2003年Java Pro“最有价值的Java部署技术读者选择奖”,2003年“JDJ编辑选择奖”,也让Ant受到的多方的认可。
Ant对JUnit的全面集成,则使得一切都变得更加完美。只需简单地配置,从自动测试到报告生成,从编译到打包部署均可自动完成。强大的功能,简单的配置,让Java程序员高枕无忧。实可谓让Java自动化的绝代双骄。

Websphere : 活吞市场的大鲸
文/jini

1999年, IBM与Novell签订合作协议,成功地提供电子商务的解决方案给予原先使用NetWare的用户。同年更是推出了WebSphere Application Server 3.0,并且推出WebSphere Studio与VisualAge for Java让工程师可以快速开发相关的程序。2001年,IBM更是宣布将应用服务器、开发工具整合在一起,与DB2、 Tivoli及Lotus结合成为一套共通解决方案,如今、IBM更是并入了Rational Rose ( UML tools )让开发流程更是完整化。
Sun在Web Services的策略方面远远落后于微软与IBM, 当他们手拉手在研订Web Services规范, 加上IBM买硬件送软件或是买WebSphere送DB2的策略让企业大佬们纷纷转向IBM的阵营, Sun才惊觉大势已去。WebSphere复杂的安装,深奥的设定,难以理解的出错讯息不断地挑战开发者的耐心与毅力。
IBM如今已经不是将WebSphere定义为单一产品,它已经是一个平台的代名词。它里面的产品目前包含了应用服务器、商业整合、电子商务、 数据讯息管理、网络串流、软件开发流程、系统管理、无线语音等等。非常多样化,也让企业界愿意相信WebSphere可以带给他们一套完整的解决方案。同 时, IBM也在推广SOA的概念, 简单来说, 利用Web Service的耦合性与工作流程的整合, 为企业内部打造以服务为导向的架构。
IBM捐献出Eclipse带给Java开发人员对IDE的重新掌握。未来是否会捐献出WebSphere的哪一个部分成为OpenSources, 或许, 又是改写Java世界的时刻了。



WebLogic : 技术人的最爱
文/jini

1995年, BEA成立了, 初期以Tuxedo数据转换的产品为基础, 成长之迅速是历年来最强的企业。 1998年, BEA推出以Java为基础的网络解决方案, 提供了完整的中间层架构, 更同时支持EJB 1.0 及微软的COM组件, 方便的管理接口掳掠了工程师的心。 在IBM和Oracle尚未准备好迎击的时候, BEA已经席卷企业应用平台的市场。 WebLogic无论在市场领先度与技术领导性与策略远观性都优于当年的所有应用服务器厂商。
如今WebLogic不仅仅是应用平台服务器的名称, 而是BEA对于整个企业解决方案的总称, 无论是WebLogic Portal或是WebLogic Integration配合着Workshop开发环境, 来自微软的UI开发团队让Workshop几乎达到所见即所得。 接着, 在下一个版本之中, BEA的BeeHive开放源代码计划将释出中间层控件的开发模块, 并且与Eclipse合作共同打造新一代的开发环境。 如此强而有力的技术支持, 更是让顾客愿意使用WebLogic平台的最大原因。
代号为“Diablo”的 WebLogic Server 9.0小恶魔已经出现了, 目前虽然仅仅是BETA版, 以Portlet 方式打造的管理接口与完整且美妙的WebServices支持, 实在很难找到可以挑剔的地方, 虽然去年被IBM的技术性推销超越了市场占有率, 不过接下来SOA的平台竞争现在才开始, BEA的LOGO也加入“Think liquid”并且推出新的AquaLogic平台做为数据服务平台, 可见, Java的应用服务器的战争, 还会继续进行着。



JBuilder : Java开发工具的王者
文/刘铁锋

Java的开发工具中,最出名的莫过于Borland公司的JBuilder了。对于一些没有弄清楚开发工具与JDK的区别的Java入门者来 说,JBuilder就如同Visual C++之于C++,以为JBuilder就是Java的全部。比起捆绑在服务器上销售的JDeveloper,JBuilder应该是唯一的仅靠自身的实 力而占领了大部分市场的Java商用开发工具了。而JBuilder作为Java 开发工具的王者,其夺冠之路并非一帆风顺。直到Java的天才Blake Stone成为JBuilder的Architect之后,JBuilder 2.0以及3.0才逐渐推出。2000年3月14日,JBuilder 3.5的推出别具意义,它成为了业界第一个用纯Java打造的开发工具,也风靡了整个Java开发工具市场。在同年11月份推出的JBuilder 4.0乘胜追击,冲破了50%的市场占有率,成为了真正Java开发工具的王者。
Borland以每半年左右推出一个新版本的速度,让众多的对手倒在了沙场。而Microsoft因为与Sun的官司,也使得一个强大的对手退 出了战争。2001年,加入了对企业协作支持的JBuilder 5以及强化了团队开发工具的JBuilder 6打败了最后一个对手Visual Age For Java。2002年JBuilder 7推出之后,再也没有其他厂商与JBuilder竞争。
孤独的王者并没有停下脚步,在2003年到2005年间,JBuilder也仍然延续了其半年一个版本的速度,推出了8、9、10、2005四 个版本。强大的功能以及持续的改进,也让Java程序员多了一分对能够在开发工具市场上与Microsoft血拼十数年的Borland的敬仰。



Oracle : Java人永远的情结
文/熊节

在林林总总的数据库之中,有一种尤其令人又爱又恨、印象深刻,那就是关系型数据库市场的“大佬”——Oracle。
从公司的角度,Oracle和Sun有着诸多相似之处,例如:两家公司都拥有一位个性鲜明的CEO。早在Java诞生之初的1995年, Oracle就紧随NetScape从而第二个获得了Java许可证。从那以后,Oracle对Java的鼎力支持是Java能够在企业应用领域大获成功 的重要原因之一。
所有J2EE程序员都知道,Oracle的JDBC驱动虽然与Oracle数据库配合良好,但在不少地方使用了专有特性。其中最为著名的就是 “CLOB/BLOB问题”,诸如此类的问题给开发者带来了很多麻烦。为了同时兼顾不同的数据库,他们不得不经常把自己的一个DAO(数据访问对象)写成 两份版本:针对Oracle的版本和针对其他数据库的版本。有不少人为了开发便利,舍弃了数据库之间的可移植性,将自己的产品绑定在Oracle的专有特 性上。
Oracle提供的Java开发工具也与此大同小异。不管是数据库内置的Java支持还是JDeveloper IDE, Oracle的Java工具都和Oracle数据库有着千丝万缕的联系。看起来,只要Oracle还是数据库市场上的“头牌”,了解、学习Oracle的 专有特性,周旋于Oracle特有的问题和解决方案之中,就将仍旧是J2EE程序员在数据库基础和SQL之外的必修功课。对Oracle的爱与恨,也将仍 旧是Java人心头一个难解的情结。



Struts、Hibernate : 让官方框架相形失色的产品
文/刘铁锋

好的框架能够让项目的开发和维护更加便捷和顺利。相比Sun官方标准的迟钝以及固执,开源框架也更得到Java程序员的共鸣。Struts以及Hibernate就是这样一类产品,它们简单、优雅,更让官方的产品相形失色。
谈起Struts,不可避免地就要提及MVC(Model-View-Controller)的理念。而准确地讲,MVC的提出却最早源于JSP 的标准。在1998年10月7号,Sun发布的JSP的0.92的规范中提出的Model 2就是MVC的原型。在1999年12月Java World的大会中,Gavind Seshadri的文章最早阐述了Model 2就是一种MVC的架构,同时也提及了MVC架构是一种最好的开发方法。2000年3月,由Craig McClanahan发布的Struts成为了最早支持MVC的框架。Struts在设计上虽然存在一些诟病,但是不可否认的是,它使得Java Web应用的开发更加简洁和清晰,也让更多的程序员爱上了Java,并开始遗忘官方的JSP。时至今日,比起如WebWork、Tapestry以及 Sun官方的JSF,Struts或多或少存在些不足,但是众多成功项目的实施,仍然使其牢牢占据的Java Web应用框架的首位。
Hibernate则在某种程度上改变了人们对构建J2EE的思路。相比其EJB的Entity Bean的映射技术,Hibernate则显得更加简洁和强大。五分钟就能把Hibernate跑起来,让更多的Java程序员享受到了开发的乐趣。第 15届Jolt大奖中,最优秀数据库、框架以及组件的奖项中,Hibernate当仁不让获得头筹;不仅如此, Hibernate甚至还影响了官方的标准。在众多Java程序员翘首以待的EJB 3.0的规范中,Hibernate得到了支持。
Java开源的繁荣不仅让众多Java的开发者享受到了更多的便利,甚至影响了官方的标准。恐怕这也是作为Java人独有的乐趣之一吧。



PetStore : J2EE人的必修课
文/陶文

很少有一个例子项目如PetStore这 般广为人知,而这很大程度上要归功于Sun很“英明”地把PetStore做成一个只展示架构而在性能调优上留下了大大余地的例子。围绕着性能话题,产生 了颇为有趣的厂商之间以及平台之间的Pet Wars。除去这些关于性能的流言蜚语乃至中伤,PetStore在展示J2EE1.3平台的架构、演示什么叫分层方面还是有着很大的功劳的。而且 PetStore在架构方面的丰富性使得其成为J2EE的那些轻量级小兄弟们展示自身的一个必选科目。
不谈那些围绕PetStore的口水,那些数不尽的盗版,PetStore给开发新手带来的最重大的影响,我想应该是架构的观念而不是性能,也 不是业务。做为一种技术的Demo,这无可非议。但是如果你是一个新手,跟着PetStore亦步亦趋地学习J2EE开发,难免会陷入过度设计、华而不实 之类的困境。围绕着.NET的PetStore的克隆PetShop展开的架构与性能的大讨论,是不是也在促使我们学习新技术时应该以解决问题为导向呢? 特别是当你想把一个如PetStore这般的Sample Project的技术照搬到你的现实世界的Real Project来时。
------------------------------------------------------------------------------------------

十大组织

Sun : 因为Java而永被荣光
文/孟岩

Sun是1980年代初期由斯坦福大学三位年轻学生创立的公司。与一般人的印象不同,“SUN”的本意并不是企图剽窃天上那颗温暖的恒星的威名,而是“斯 坦福大学网络”的意思。Sun在“前Java”时代就因为SPARC芯片、Solaris操作系统和“网络就是计算机”的口号而为人所知。1990年12 月,Sun启动了一个看上去没什么意思的嵌入式软件项目。然而,基于C++的开发很快遇到了麻烦。一个创新型技术公司的特色立刻显示出来,一群天才不是去 深入C++,而是另辟蹊径,发明了Java。这个传奇故事已经尽人皆知,但是其中所包含的精神却始终令人望空凝思。
Java的发明,使得Sun真正有机会在软件的历史天空中放射出太阳的光芒。Sun发明了Java,并且在长达十年的时间里始终走在Java大 潮的最前端。Sun是Java的老家,是Java慈爱的母亲,这一切任何人都改变不了。虽然Sun似乎没能够从Java中获得应有的金钱回报,但这丝毫没 有挫伤Sun对于Java的母爱,还有对于Java大潮的舍我其谁的领导气概。
所有人都迷恋富有的感觉,但是也迟早会意识到钱不是世上最宝贵的东西。这个世界并不缺少会赚钱的公司,但是能够靠着创新型技术推动整个世界进步的公司却是凤毛麟角。Sun应该感到骄傲,他们将因为Java而在历史的天空里发射出太阳的光芒。



IBM : Java经济的最大受益人
文/恶魔

Sun公司是Java的发明人,但IBM却是Java最大的受益者。是IBM抢占了利润丰厚的应用服务器市场的头把交椅,是IBM在Java技术 上投入最多的金钱,拥有最大的影响力和最好的开发者社区。可以毫不夸张地说,Java使IBM的软件体系得到复兴,在某种意义上,甚至可以说,是Java 创造了这种复兴。Java之后又来了Linux,这种建造在不属于自己的平台上以获得成功的理念更是变得非常有影响力。正是这种理念铸就了今天IBM “按需计算,服务为王”的王者风范。
2004年三月,IBM以Java的解放者的姿态借机向Sun发难。IBM公司负责新兴技术的副总裁史密斯在一封公开信中表示,IBM愿意与Sun合作成立一个项目,意在通过开放源代码开发模式管理Java的开发工作。
墙内开花,墙外香。面对IBM的成功,到底是谁妒嫉呢?或许去程序的社区中逛逛聊聊,明眼人是不难发现事实真相的。也许Sun应该好好向IBM学 习经营之道。尽管利润额不如硬件及服务部门,但IBM软件部门的利润率是最高的——高达85%的利润率足以令人惊叹。在最近的一个季度里,IBM软件部的 利润率上升了8%,其中WebSphere产品组的利润率上升了14%。
正是IBM在开源和Java上的全身心地投入又秉承开放性的原则,今日的Java才能以日进千里的速度将许多竞争对手远远抛在后面。Java 10年,IBM功不可没。



BEA : 用AppServer影响Java阵营
文/霍泰稳

十年前诞生的Java并不是一开始 就那么引人注目的,虽然用Applet也曾为互联网络带来一抹亮色,但毕竟只是Toy。在企业级应用市场上,Java一直没有什么起色,虽然Java的支 持者一直在鼓吹它有着大型企业级应用的强悍功能。过高的期望与低能的产品,一时间颇让人怀疑Java的路是否已经走到了尽头?可以说是WebLogic Server的出现逐渐打消了人们的顾虑,BEA公司慧眼独具在2001年收购的这个产品将人们的目光吸引到电信、金融、政府等Java企业级应用方面, WebLogic Server以其优良的性能让人们看到Java应用广阔的未来。虽然随后在Java应用服务器方面出现了像IBM公司的WebSpere、开源软件 JBoss等Java应用服务器,但WebLogic Server几乎占领世界前500强所有企业的应用服务器市场地位依然无法撼动。
Java现在已经不单纯是一个语言,从另一方面它也代表着开放与创新。很多以Java产品为基础的公司或者从事Java开发的程序员骨子里都有 着开放与创新的烙印,BEA公司的发展深深地印证了这一点。与合作伙伴的密切合作向Java社区贡献产品基础源代码、加入权威开源组织参与Java标准的 制定等证实着BEA的开放,而其产品从WebLogic Server一种拓展到WebLogic Platform、WebLogic Portal、WebLogic Workshop等其它领域又证实着它的创新能力。



Oracle : 早起的鸟儿有虫吃
文/孟岩
Oracle的老板拉里?艾利森是有名的混世魔王和花花公子,所以尽管他也是软件产业成功人士的代表,却绝不是程序员们心目中的英雄,程序员们毕 竟不是央视《对话》节目里群众演员,没必要为了节目需要而对权贵财阀们做出一副贱骨头状。但是,任何人都不能不钦佩Oracle在技术上的前瞻性和坚决 性。Oracle是1996年获得Java许可证的,紧接着就大胆地将Java作为战略性的发展方向而予以全面支持。要知道当时Java的前景并不是十分 确定的,而Oracle的坚决投入,使得它在后来的Java世界中抢得一席之地。1998年9月发布的Oracle 8i为数据库用户提供了全方位的Java支持。Oracle 8i成为第一个完全整合了本地Java运行时环境的数据库,开发者用Java就可以编写Oracle的存储过程,这意味着可以仅在Oracle数据库中就 完成几乎全部的应用开发。J2EE兴起后,Oracle更是有心进入开发工具市场,因而购买了JBuilder的源码,并在此基础上开发出 JDeveloper。如今Oracle除了数据库稳居第一之外,在Java开发工具世界里也自成一派。这一切不能不归功于当初的眼光远大。


Apache : 开源软件的品牌保证
文/陶文

Java程序员的日常工具箱中,我们可以发现Ant、Tomcat、Log4、Lucene这些鼎鼎大名的开源产品。而它们的共同点在于,都是由 Apache Software Foundation社群中杰出的开发者开发的开源项目。Apache这个名字在Java的世界中实在太出名了,以至于“Apache”这六个字母成为开 源项目品质保证的代名词。Apache是自由开源的一面旗帜,其Apache License更是成为商业友好的License的首选,只SourceForge上就有1000多个以Apache License授权的项目,其流行程度可见一斑。
但是,如我们所知,Apache最早闻名IT界是靠高性能的Web服务器,其历史甚至和Java一样长。Apache对于Java的偏爱,以及 其发展的速度也映射出了Java繁荣的一角。现在去它的主页上看看,满目望去全部都是Java的开源项目,早就不光是其C服务器的老本行了。Apache 对Java最大的贡献就是提供了这么一个精品的开放舞台,让杰出的开发者和成熟的开源项目走到一起,共同给Java语言提供一个丰富的工具仓库。对于一种 语言、一个平台来说,其库的丰富程度对于开发者来说的重要性再怎么强调也不为过。勿庸置疑,Aapache上会出现越来越多的Java开源项目,而我们开 发者也将更多地得益于这令人目不暇接的繁荣。



TheServerSide : 论坛的专业精神
文/刘天北

成立于2000年5月,TSS最初以一本书而广为人知。它的创始人Ed Roman同时也是J2EE名著《Mastering EJB》的作者;Roman运营着一个J2EE咨询/培训公司TheMiddlewareCompany(简称TMC),TSS当时是TMC的下属部门; 为了扩大企业的影响,Roman在TSS网站上免费发布了那本书的电子版。J2EE程序员要吃下这个香饵,就得在论坛中注册;注册的同时,多半也会看一眼 论坛的内容;一看之下,大部分人都被吸引住,成了社区的忠实成员。
TSS究竟有什么吸引人的秘诀?首先,它有一支能力过人的运营团队,除了Roman本人之外,其中还有好几人都是J2EE领域的顶尖专家;第 二,TSS和TMC定期会推出专家研讨会/视频访谈、技术白皮书、评测报告,通读TSS提供的这些内容,基本上就可以把握技术的当前趋势。但这还不是全 部。最可贵的还是TSS的社区风格:他们深谙技术,但不盛气凌人;思想敏锐,但不因此缺乏审慎和大局感。其中大多数人都已在自己的开发领域颇有建树,在 TSS上的活动既给他们提供了与同行进行深度交流的机会。一个新成员进入社区,就像参加了一个起点很高的专业俱乐部,这不是一个求解“怎样设置 JAVA_HOME环境变量”之类问题的地方。事实上,在J2EE技术发展的若干转折点上,TSS都起到了关键的推动作用。
几经易主之后,J2EE咨询培训公司TMC在2004年关闭;TSS则被IT媒体集团TechTarget收购。我们期待着它更加繁荣的未来。

JBoss : 职业开源软件组织
文/刘天北

J2EE的婴儿期,“应用服务器”原本是“昂贵”的代名词。但从1999年起,Marc Fleury和Rickard Oberg等人就已经着手改变这种状况。他们开发的开源EJB容器当时叫做“EJBoss”,在Sun公司的干预下(注意,“EJB”是注册商标), JBoss获得了今天的名字。虽然从问世起就一直受到关注,但JBoss第一个达到产品化标准的版本可能是它的2.2版。它的易用让人一见难忘:除了标准 部署描述符,无需编写专用的xml配置文件。Oberg自豪地说,“我们的架构并不是按照EJB规范指定的路线设计的,因此也没有走大多数应用服务器走过 的弯路。”
Jboss 3.x版本保持了一贯的创新精神,在用户中间获得了更广泛的认可。但是,文档要收费下载、在邮件列表上提问常常会遭到Fleury等人的斥责。无疑, JBoss的创始者也意识到了自己的幼稚:开源软件只能靠服务盈利,卖文档赚钱有限、骂用户当然更损害企业形象。
虽然以Oberg为首的许多程序员退出了开发队伍(其中很多人成了JBoss的死敌),在开源软件领域也面临JOnAS Geronimo等新老对手的竞争,但JBoss还是以不断推出的新版本站稳了脚跟。在技术上,它是策动J2EE演进的重要力量:拟议中的EJB 3也要追随Jboss 4倡导的开发范式,以至于二者的代码样本之间的差别几乎难以分辨;在商业上,JBoss与Sun公司言和修好,甚至还获得了数量可观的风险投资。 JBoss已经像拥护者预期的那样,成为了应用服务器领域的Linux。



Borland : 深度介入Java
文/左轻候


除了Sun以外,也许没有一家公司 像Borland这样深层地介入Java。Borland开发了最早的Java编译器之一,Borland的工程师参与了早期JDK的设计, Borland的JBCL(JavaBeans Component Library) 技术也成为后来Java Bean规范的基础。但是Borland对Java世界最大的影响还是JBuilder。
1997年11月,Borland JBuilder 1.0发布。虽然第一个版本相对于竞争对手并没有表现出明显的优势,但是Borland凭借深厚的技术实力和正确的市场策略,不断地超越了对手。 JBuilder 3.5成为业界第一个100%基于Java架构的开发工具,并且市场份额很快超过了50%。在随后的版本中,JBuilder持续改进对团队开发、 J2EE架构、Mobile技术等方面的支持,最终成为了Java开发工具市场,特别是大型企业级Java开发市场中的霸主。JBuilder的成功,很 大一个原因来自于Borland坚持的平台中立性,即对不同厂商的解决方案提供一视同仁的支持。
2005年初,随着Eclipse社区的迅速崛起,Borland进入了Eclipse的董事会,成为战略开发者(Strategy Developer) ,并宣布将推动Borland的其它产品与Eclipse的集成。在随后发布的一份文件中,Borland宣称JBuilder的未来版本将放弃原有的 PrimeTime架构,而基于Eclipse架构。这个代号为“Peloton”的版本预计于2006年下半年发布。
Borland对Java的另外两个主要贡献来自Together和BES(Borland Enterprise Server)。Together是著名的建模工具,能够与包括JBuilder在内的许多开发工具进行集成,全球市场份额占有率排名第二。BES AppServer是一种J2EE服务器,在全球市场份额占有率上次于WebLogic和WebSphere,排名第三。



JCP : Java世界的联合国
文/黄海波


当联合国正在为安理会改革问题 吵得如火如荼时,Java世界的“联合国安理会”已经成功地运作了七个年头。JCP(Java Community Process)在1998年由Sun发起成立,目标是通过一个开放、合作和鼓励参与的非盈利组织来发展和推进Java和相关的技术。正是由于JCP计划 的推出可以让所有对Java感兴趣的软硬件厂商,个人和组织都能参与到技术规范的制定和发展过程中,协调各方的兴趣和利益、集思广益,才可以让Java在 短短的几年内异军突起,成为可以和微软开发平台抗衡的一个主流开发语言。JCP计划既然是一个组织,自然也有一定的架构。JCP组织架构主要包括PMO (Program Management Office)、JCP成员、EC、EG。事实上,JCP的架构就好像一个Java世界的联合国。虽然也有不少人批评JCP成为各派利益的角力场,因而效 率低下;但是,它毕竟为Java的顺利发展很好地掌握了方向。



微软与Java : 不得不说的故事
文/孟岩


微软跟Java不对付,地球人都知 道。跟Sun和解了又怎么样? .NET跟Java就是竞争对手,没什么说的。但是有点IT掌故的人都知道,微软并非一开始就跟Java过不去。当年比尔?盖茨盛赞Java是“长期以来 最好的程序设计语言”,而且很早就购买了Java许可证。但是微软作为村里的老大,看着人家的儿子茁壮呈长,不由得生了私心杂念,搞起了小动作,在 Visual J++中加入了一些破坏纯洁性的东西。单独来看,Visual J++是COM时代微软最棒的开发工具,用WFC写Windows应用程序和COM组件实在是一种享受。但是放在Java大家庭里,这个家伙就显得多少有 点不怀好意。一场官司下来,微软被逐出Java大家庭,Visual J++无疾而终。以后的事情尽人皆知,.NET出笼,利齿直指Java,几年撕咬下来,没占着便宜也没吃大亏,如今也算是南北朝对峙,二分天下有其一。设 想如果当时微软能够摒弃帝国主义心态,正确对待Java,与其他人一起共建美好的Java“共产主义社会”,那么今天我们的软件开发世界应该会美好得多。 可惜黄粱一梦,终究是蚂蚁的喜事。2004年,微软与Sun实现了和解,但愿到Java 20周年的时候,我们能更正面地描述微软对Java发挥的作用。

posted @ 2006-08-13 21:35 Alex 阅读(303) | 评论 (0)编辑 收藏

一、软件开发技术

1)服务器端

在最近5年内,Java还是主流,不光是因为当前的普及程度和遗留系统问题,而且除Microsoft几乎所有大公司都投资到Java上面的原因,此外开 源也是一股无法忽略的力量:除了Java方面的开源框架在推动Java,也有Linux在带动java企业应用在普及(别忘记dotnet只能在 Windows Server上面运行)

dotnet有自己的优势,但是在五年内无法和Java取得均势,不光是因为Java普及带来的优势,也不光因为开源界对java的推动,也不光 因为其他大公司在java上面的投资,而是很多公司的行业性质决定了dotnet的出局,例如电信行业,金融行业,电子政务行业等等,是根本没有可能采用 dotnet的。

Python和Ruby算不上后起,但是很有竞争实力,不过基于上面的原因,仍然不能成为主流。

在Java服务器端技术中,清晰的分为两条路线:高端的商业路线,这条路线是EJB3,J2EE5.0;低端的开源路线,这条路线是 Hibernate, Spring。这两条路线也有重叠的地方,例如开源的Struts几乎成为J2EE Web层的标准,开源的Hibernate奠定了EJB3的基础。但是划分路线不是基于技术上的区别,而是基于商业运作上的区别。注重技术支持和商业服务 的公司会选择前者,注重成本控制和选择自由的公司会选择后者。

商业路线的技术方案是:EJB3+Struts;
开源路线的技术方案是:Spring+Hibernate+Struts/Webwork

Struts是一个很成功的开源框架,它的地位短期内还无法动摇,JavaEye有一项使命,就是动摇Struts在Java Web领域的地位,把它赶下王座,把Webwork扶上位!

商业的Web层技术,JSTL算是一个不错的东西,但是和灵活的模板语言如FreeMarker相比,却有很大的差距。JSF基本上是一个没有前途的东西。商业Web层技术因为一直没有出现好的应用,这样也导致了Struts的上位。

服务器端业务层和持久层框架,我非常看好EJB3,原因也不用多谈了,从商业上来说,需要这样一个东西,跨国公司们也需要这样一个产品来卖,来取 代糟糕的 EJB2。开源的方案里面,Spring+Hibenrate是一个很好的商业方案的开源替代,他们不存在很直接的竞争,而是一个互补的关系。这里比较尴 尬的反而是JDO:JDO是商业产品(目前没有好的开源实现),造成开源应用不会对它感兴趣,JDO没有一个像EJB容器那样的脱管环境,造成商业方案对 它不感兴趣。不过有了JDO,我觉得是对EJB3,对Hibernate形成一个良好的竞争环境,这一点是非常有利的。

2)客户端技术

准确的说是RIA应用。虽然我前面对XAML进行了正面的评价,但是我认为我前面有些结论给错了。经过这段时间,我觉得,XAML即时在多年之后,也未必能够成为一个非常成功的解决方案。道理很二:

1、XAML会带来比ActiveX更严重的安全性问题。
XAML本质上就是一个本地应用程序,虽然号称可以在IE浏览器里面运行,但IE就是一个皮而已,XAML应用具备对本地资源完全的访问能力(就 算IE限制也没有用,IE限制就丧失功能,那样的话,功能并不会比Javascript来得更多;不限制的话,就为所欲为了),因此只要IE具备了运行 XAML的能力,黑客将可以非常轻易的通过IE进行入侵,这仅仅需要引导用户在不知不觉中访问一个恶意的网页就搞定了!用户必须面临选择:要么禁止IE对 XAML的运行能力,要么接受随时被攻击的危险。

2、XAML应用本质上也是RIA应用,因此必须进行大量的RPC调用
当前XAML采用XML Web Services进行通讯,这是一种低效的RPC。当前的XAML案例中并没有注意到RPC领域,实际上根据我现在做RIA的体验来说,RPC绝对不是一个简单的事情,要考虑的问题非常多。

从当前的阶段来说,最实际可用的方案有两个:

1、AJAX
实际上就是基于XMLHTTP的JS异步交互,这个东西已经出现很多年了,最近随着Google应用和Sun Blueprint的推出开始火热。我原来对这个东西持否定态度,但是后来转变了。我原来否定态度的一个前提就是:XMLHTTP缺乏成熟的组件库!但是 没有想到的是,现在XMLHTTP从去年下半年开始,如雨后春笋般冒出来。AJAX应用最大的好处就是充分利用现有资源,我认为应成为RIA应用的首选。

2、Flash
Flash的优势也很明显,强大的AS支持,强大的组件可视化设计,强大的交互能力和很炫的用户体验,并且Flash Remoting也已经非常成熟了。Flash的缺点就是Flash虽然嵌入网页,但是和网页没有数据交互能力,Flash另一个缺点就是不适合处理大量 文本内容(HTML最适合)。现在有些人开始滥用Flash了。

因此比较好的方式可能是两种混用,一般不过度复杂的交互交给AJAX,非常复杂,甚至需要托拽操作的,交给Flash。

总结一下:

软件开发领域服务器端技术Java是主流,两个技术路线,一个是EJB3,一个是Spring+Hibernate,此外iBATIS也有一席之地;客户端技术就是AJAX和Flash。

二、数据库技术

基本上格局不会发生多大变化,Oracle还是高高在上,SQL Server进一步蚕食NT平台其他数据库的领地。开源方面,MySQL将一枝独秀,但是开源数据库在很多方面还是和商业数据库有无法拉近的巨大差距。这 也使得商业数据库的地位不可替代。我会比较关注Oracle,MySQL这两个数据库。面向对象数据库仍然不会有什么起色。

三、桌面编程技术

我还是相信一点,对于桌面应用来说,本地代码的位置永远无法被取代,所以我总觉得XAML那样的东西效率实在很成问题。Longhorn要像成 熟,也不是第一个版本就可以达到的。当前桌面应用开发技术,还是首推Delphi,不过我觉得Python是后起之秀,非常有可能在未来取代Delphi

初探在下一代 Windows 中编写和部署应用程序
http://www.microsoft.com/china/MSDN/library/windev/longhorn/DevelopAppLonghorn.mspx

首先,以Microsoft公司的实力和Windows操作系统的占有率来说,Longhorn迟早会被普及,而XAML的开发方式也有可能普及的。记得 当初WindowsXP刚出来的时候,因为资源占用率和新的激活制度招致一片骂声,但是慢慢的,现在也都接受了下来。由此可以推断,Longhorn以其 更加丰富的桌面功能和诱人的外观,会在将来成为主流。

但是Longhorn什么时候才会全面普及,这是很值得琢磨的问题。WindowsXP是2001年推出的,在随后的几年,Microsoft采 用了一些商业手段来迫使用户升级,例如企图取消Windows98的技术支持,不再提供WindowsNT技术支持,不再销售 WindowsNT/Windows98,将Windows2000保持在一个比较高的售价的同时,对WindowsXP推出优惠价格,让 WindowsXP的售价低于Windows2000等等手段。但是直到现在,Windows2000仍然占据了非常高的份额,据我个人的观察是比 WindowsXP略高。按照这种情况来推断,Longhorn要普及,恐怕难度更大,非常多的用户现在仍然是Windows2000的死忠派, WindowsXP推广了四年还未能超过Windows2000,那么Longhorn究竟要几年才能超过WindowsXP呢?我估计四年以上是起码 的。

XAML应用程序不同以往,它只能跑在Longhorn上面,甚至比Java和dotnet要求更严格,后者仅仅下载安装一个运行环境就可以了, 但是前者要求你必须更新操作系统。XAML在IE浏览器中运行虽然肯定是下一代RIA的主流,但是不可忽视的问题是,只要Longhorn没有彻底淘汰 Windows2000/XP,软件开发商和网站开发商就不敢大面积采用XAML。而根据我的观察,现在企业中,Windows98仍有少部分市场份额。 因此Longhorn必须要等待到彻底的,毫不残留的淘汰Windows98,Windows2000,WindowsXP之后,才会全面普及,而在此之 前,不得不经历一个漫长的过渡期。

就好像现在,假设你开发桌面应用程序,你敢只针对WindowsXP开发吗?而彻底不支持98和2000吗?我想,没有哪个软件开发商敢这样做。 除非 Windows2000几乎被彻底淘汰了,你才敢这样做,但是WindowsXP已经推出四年了,还没有Windows2000占用率高,哪全面淘汰究竟 要几年呢?再看看现在dotnet winforms应用,推出也已经五年时间了,但是到现在仍然没有普及开来,根本的原因就是Windows2000/WindowsXP没有预装 dotnet framework。仅仅是需要打包安装一个运行环境就使得winforms五年都推广不了,更何况要求你升级操作系统呢?

我个人的估计是,假设2006年Longhorn如期上市,那么将需要7-9年时间来彻底淘汰Windows2000/WindowsXP。 Longhorm上面XAML应用的初步普及也至少需要4-5年时间以后才会有软件开发商大量去做(想向dotnet是2000年开始宣传和推广的,到 2004年开始普及,今年和明年才会全面普及)。因此,基于XAML应用的普及可能是在2010年以后!上面的估计中还没有包括MacOS 和Linux在桌面会否有什么表现。

先说说服务器端吧:

从可预见的未来来看,服务器和客户端TCP通讯的主流方式一定是HTTP协议(即时通讯软件走UDP端口,不在讨论范围)。在基于HTTP协议之 上,又分为两类:一类是SOAP协议,异构系统支持良好,但是性能很差,目前Microsoft很喜欢用这种方式;一类是轻量级二进制协议,例如 Flash的 AMF协议,Resin的Hessian协议。值得一提的是,不管哪种方式,他们都支持异构的系统,所以完全可用在客户端采用dotnet,在服务器端采 用Java或者Python。因此,XAML的流行不会对服务器端技术产生致命的影响(肯定会提高dotnet的服务器的市场份额)。所以我们可用抛开客 户端影响,单独来看服务器端技术:

1、Java
Java是当前服务器端技术当之无愧的王者,在未来五年内,也不会有任何动摇(受到dotnet和python的影响,市场份额会下降一些)。 Java特别有利的一点是,现在有太多的现存系统基于Java,这些系统都不会轻易迁移到其他平台上。另外还有一个决定因素是除了Microsoft之外 的几乎全部 IT大公司都在Java方面的投资巨大,放弃Java对他们来说也意味着沉重的打击,甚至毁灭性的打击。这些公司可以列很长很长,IBM,HP, Oracle,SAP,Sun,BEA,Macromedia等等。

2、dotnet
由于Microsoft的影响力,dotnet会成为为仅次于Java的第二大服务器端技术,但是Microsoft有一个隐忧,就是Linux 操作系统在服务器端的高速成长。虽然现在Linux在整个服务器端市场的出货量只有13%左右,但是成长率惊人,根据我看到的资料显示,到2008年,将 占据 25%以上的市场份额。考虑到很多公司是自己安装Linux,因此不会被硬件服务器厂商统计进来,因此Linux的服务器端的市场份额应该比25%高一 些。并且现在主要的服务器厂商都对Linux有非常巨大的投入和支持,这些公司包括IBM,HP,Dell(只有Sun不支持),因此Linux在未来会 对Windows在服务器端的市场构成最严重的威胁。

不要忘记dotnet只能在Windows平台上面跑,虽然有mono,但是你不可能移植MTS,COM+,SQL Server etc。所以只要Linux在服务器市场对Windows构成持续的威胁,dotnet就不可能超过Java,Java的地位还是稳稳的老大。从某种程度 上来说,Java的命运是和Linux联系在一起的,只要Linux在服务器端不输于Windows,Java就稳稳压制dotnet。

BTW:从未来来看,Linux和Windows会在低端和中端服务器市场成为主要竞争对手,由于各自都有其不可替代性,所以双方都不可能彻底消灭对方,最大的可能性是Linux和Windows平分市场,或者Windows市场份额略高一点。

3、Python
我个人认为Python会成长为第三大服务器端技术,Python成长于开源,但是又有商业公司来商业运作,并且背后还有大公司的支持,在欧洲普 及的非常好。当然最重要的原因是我觉得Python在技术上非常先进,并且技术发展方向上比较统一,不会出现Java那种吵架的事情。

4、PHP
PHP这东西是不错,Yahoo也在用,IBM现在也对他感兴趣,但是我还是要说PHP没有太广阔的前途,原因很简单,PHP没有服务端中间件, 例如 Java有App Server,dotnet有IIS/MTS,Python有Zope,但是PHP他就是一个脚本,没有自己的中间件就是致命问题。Yahoo用PHP有 其特定的原因,主要是从原先自己的技术迁移到PHP很方便,而IBM支持PHP,显然醉翁之意不在酒,IBM意不在推广PHP,而在于争取到那些使用 PHP的商业大客户们,向他们卖服务。

BTW:感觉欧洲用Python/PHP的很多,似乎开源在欧洲非常深入人心。

从服务器端技术来说,Java还是我们最需要下功夫去学习和掌握的,此外,我会比较倾向于钻研和应用Python,而不是dotnet。原因也很 简单,跟随Micorsoft的技术会很辛苦,Microsoft产生的新概念多,他总是会猛的推出n多种技术,然后让他们在市场上自己生存,最后根据市 场反馈,无情的抛弃某些东西,大力推进有市场前景的东西,这样的例子太多了,举不胜举了。我的感觉就是这种方式会让Microsft经过市场尝试在技术竞 争中筛选最优秀的技术,但是对于Microsoft技术的跟随者来说,未免有点太不公平,整天吭哧吭哧被Microsoft拿来当免费的试验品来用。我特 别不理解的是MSDN宇宙版,Microsoft总是把无穷无尽的文档灌给你,让你永远学不完,但实际上我真的不需要那么多概念,我只需要能够很好的完成 我工作的技术,并且这个技术可以持续的完善就好了。而不是今天给我这样一个东西,明天灌给我无穷的文档,后天当我用顺手以后,又告诉我这东西作废了,你给 我重新学习新东西,然后又是无穷的文档,总之很恼火。

所以就是:重点学习Java,有时间去学习Python,保持对dotnet的关注即可。


客户端:

前面说了那么多XAML的东西,都是和这有关,七年以后肯定是XAML的天下,但是五到七年之内还不是:

1、Java
Java在客户端真的是扶不起的阿斗,这都怪Sun。Sun造就了Java的成功,又一手毁了Java在客户端的市场。那些个Swing和SWT 的死忠团也不要和我争什么,我也懒得和你们争,你们觉得好就好吧,道不同不相与谋,你觉得好你就用你的,我觉得不好我就用别的。用不着缠着我非逼我说 Java做客户端好,没必要,况且就算你逼我承认又怎样?我就是玉皇大帝金口玉言了?得到我的承认,Java就有前途了?我好像还没有那么大本领吧?就是 IBM, Sun也没有那么大本领,所以好不好也不是我说了算,用不着逼我。

2、dotnet winforms
由于Windows2000/WindowsXP不带dotnet CLR,所以winforms一直没有能够普及得很好,等Longhorn一出来,又变成了XAML了,winforms又被淘汰了,所以 winforms的地位特别尴尬,但是在这5-7年中,你想开发既能够在Windows2000/WindowsXP,又能够在Longhorn上面跑的 桌面程序,winforms好像又是Microsoft技术中最好的选择。所以只好一直尴尬下去。

3、VC,VB
dotnet出来以后就开始尴尬了,说用吧,好像很落伍了,都dotnet时代了,说不用吧,又没有好的替代品,现阶段开发桌面程序,还真得不得不用,而且还挺好用的。所以VC6SP5,VB6的死忠团也比较多。

4、Delphi
dotnet出来以后Borland就开始跟风了,这一跟风,连老本都跟没有了。未来的XAML时代,我也不知道Borland怎样找自己的定 位,但不管怎么说,从历史来看,本地代码的应用程序永远有它一席之地!就算XAML又如何如何做得漂亮了,关键的地方,和特定资源处理相关的部分,还是本 地代码的程序管用。你看VB出来多少年了,用VB开发的都是一些上层的项目级别的应用软件,一旦涉及产品领域,还是VC和Delphi管用。所以现在大家 还是不得不用Delphi7阿。

BTW:XAML应用致力于快速开发项目级别的应用,特别是可以跑在IE浏览器里面的,因此是RIA的首选。但是毕竟也有很多不适合用RIA的场 所,特别是例如我要备份某些文件,你用XAML?那性能就不用提了。所以Delphi如果好好发展VCL,封装Windows32 API,我觉得也是一条路,未必比现在跟随dotnet差。

5、Flash RIA
其实我觉得Flash不适合做RIA的,但是Flash普及率太高,XAML又离普及太遥远,而Flash现在就可以用了,所以是当前RIA的首 选。不过我对Macromedia公司比较失望,如果Macromedia能够公布Flash实现细节,作为一个公开的标准向ISO提交,同时免费开源 Flex,我敢说,Flash RIA会迅速普及的。等5-7年XAML的时代,由于Flash的市场占有率,XAML就未必能拼得过Flash。可惜的是Macromedia公司目光 过于短浅,只知道赚眼前的小钱。

6、Python
这5-7年内,RIA应用和RCP应用不会统一,XAML才具备将RIA和RCP统一的实力。从这5-7年来看,Flash是RIA的首选,而RCP的首选,我要推荐Python。原因前面已经提过,简单总结一下:
1)wxWidgets是一个比MFC优雅的库,TortoiseCVS用wxWidges而不用MFC,就是因为wxWidgets好用,而不是为了可以移植。
2)Python的面向对象脚本语言编程适合快速界面开发
3)Python在服务器端和客户端都非常有前途,可以形成一个统一的解决方案,这一点明显比Java有优势
4)Python桌面应用程序可以完全编译为本地代码,脱离Python运行环境,这一点比dotnet winforms都有优势
5)Python可以不受限制的任意调用Windows32 API,所以凡是VC6可以做的事情,Python就可以做

试想一下,现在我们开发桌面应用程序有什么要求?
一、不要附带一个JRE或者CLR的累赘
二、可以快速开发
三、性能要有保证
四、方便的远程方法调用支持
此外如果能够跨平台就最好了

Java前三点都不符合;dotnet winforms不符合一;VC6不符合二和四,VB6不符合三和四;Delphi7符合前四点;Flash RIA不符合三;Python全部都符合!并且请记住Python是一个完全开源免费的方案!

客户端技术在这5-7年中,在RIA领域我会学习一下Flash,在RCP领域我会重点学习Python,此外会观望一下XAML。

posted @ 2006-08-13 19:24 Alex 阅读(377) | 评论 (0)编辑 收藏

一.  概述

企 业在进行业务处理时,政府在进行公文审批时,都是以流程形式而进行的,在信息化的过程中,企业、政府也将这些业务处理、公文审批的过程信息化了,早期通常 是通过程序硬编码的方式来处理这些业务、公文的流转,随着业务、公文的复杂的处理情况不断出现以及需求的不断变更,这种硬编码的方式显然已无法应对,这个 时候工作流管理系统应运而生,掀起了一股工作流管理系统的热潮。

那么到底工作流管理系统能够带来什么好处?工作流管理系统通过对业务、公文流转进行分析以及抽象,将不变和变化的部分进行划分,用户可轻松的通过可视化的工具对事项的流程、流程环节涉及的人员 ( 角色 ) 、流程环节的表单、流程环节的操作进行修改,从而到达了应对不断变化的需求的目的,而工作流管理系统通常提供的流程监控、查询统计模块更是极大程度的为用户优化流程提供支持,以提高企业、政府的工作效率。

本文主要描述工作流管理系统通常的结构、参考模型以及通常使用的调度算法。

二.  构成

工作流管理系统,简称 WFMS , 经过对业务、公文流转过程的分析以及抽象,工作流管理系统围绕业务交互逻辑、业务处理逻辑以及参与者三个问题进行解决,业务交互逻辑对应的为业务的流转过 程,在工作流管理系统中对应的提出了工作流引擎、工作流设计器、流程操作来解决业务交互逻辑的问题,业务处理逻辑对应业务流转过程中的表单、文档等的处 理,在工作流管理系统中对应的提出了表单设计器、与表单的集成来解决业务处理逻辑的问题,参与者对应到的为流转过程中环节对应的人或程序,在工作流管理系 统中通过与应用程序的集成来解决参与者的问题。

工作流管理系统为方便业务交互逻辑、业务处理逻辑以及参与者的修改,多数通过提供可视化的流程设计器以及表单设计器来实现,为实现工作流管理系统的扩展性,多数提供了一系列的 API

一个完整的工作流管理系统通常由工作流引擎、工作流设计器、流程操作、工作流客户端程序、流程监控、表单设计器、与表单的集成以及与应用程序的集成八个部分组成。

2.1.       工作流引擎

工 作流引擎作为工作流管理系统的核心部分,主要提供了对于工作流定义的解析以及流程流转的支持。工作流定义文件描述了业务的交互逻辑,工作流引擎通过解析此 工作流定义文件按照业务的交互逻辑进行业务的流转,工作流引擎通常通过参考某种模型来进行设计,通过调度算法来进行流程的流转 ( 流程的启动、终止、挂起、恢复等 ) ,通过各种环节调度算法 (SPLIT AND OR ) 来实现对于环节的流转 ( 环节的合并、分叉、选择、条件性的选择等 )

2.2.       工作流设计器

工作流设计器为可视化的流程设计工具,用户通过拖放等方式来绘制流程,并通过对于环节的配置来实现环节操作、环节表单、环节参与者的配置。

工作流设计器为用户以及开发商提供了快速绘制、修改流程的方式,工作流设计器的好坏决定到工作流管理系统的易用性。

2.3.       流程操作

流程操作指所支持的对于流程环节的操作,如启动流程、终止流程、挂起流程、直流、分流 ( 单人办理 ) 、并流 ( 多人同时办理 ) 、联审等,象这些流程操作都是可直接基于引擎所提供的环节调度算法来直接支持的,而在实际的需求中,通常需要自由的对于流程进行干涉,如取回、回退、跳转、追加、传阅、传阅办理等,而这些流程操作对于工作流引擎来说是不合理的,因此必须单独的去实现。

流程操作支持的好坏直接决定到一个工作流管理系统的实用性。

2.4.       工作流客户端程序

工作流客户端程序为工作流系统的表现形式,通常使用 Web 方式进行展现,通过提供待办列表、已办列表、执行流程操作、查看流程历史信息等来展现工作流系统的功能。

2.5.       流程监控

流程监控通过提供图形化的方式来对流程执行过程进行监控,包括流程运转状况,每个环节所耗费的时间等等,而通过这些可相应的进行流程的优化,以提高工作效率。

2.6.       表单设计器

表单设计器为可视化的表单设计工具,用户通过拖放的方式来绘制业务所需的表单,并可相应的进行表单数据的绑定。

表单设计器为客户以及开发商提供了快速修改表单的方法,表单设计器的易用与否以及功能的完善与否影响到工作流管理系统的易用性。

2.7.       与表单的集成

通常业务流转需要表单来表达实际的业务,因此需要与表单进行集成来实现业务意义,与表单的集成通常包括表单数据的自动获取、存储、修改,表单域的权限控制、流程相关数据的维护以及流程环节表单的绑定。

与表单的集成的好坏影响到工作流管理系统是否能提高开发效率。

2.8.       与应用程序的集成

通过与应用程序的集成来完善工作流管理系统的业务意义,主要涉及到的是与权限系统以及组织机构的集成。流程环节需要相应的绑定不同的执行角色,而流程操作通常需要与权限系统、组织机构进行关联。

三.  参考模型

工作流系统通常通过参考一些标准的模型来进行设计,主要的有 WFMC OMG ,在这里主要介绍一下 WFMC

3.1.       WFMC

WFMC 是国际工作流管理联盟,它于 1993 年成立,发布了一系列的工作流定义、软件接口的草案文本,是目前世界上公认的最具权威性的工作流标准制定机构,得到了广泛的支持和应用。

2002 10 25 WFMC 发布了基于 XML 的流程定义语言 1.0 版的最终文本( Workflow Process Definition Interface----XML Process Definition Language  文档编号: WFMC-TC-1025 ),以及此前发布的工作流应用软件接口规范 WFMC-TC-1009, WFMC-TC-1013 等系列文件,构成了工作流定义及系统的设计标准。

为了实现不同工作流产品之间的互操作, WfMC 在 工作流管理系统的相关术语、体系结构及应用编程接口等方面制定了一系列标准。工作流管理联盟给出的工作流定义是:工作流是指整个或部分经营过程在计算机支 持下的全自动或半自动化。在实际情况中可以更广泛地把凡是由计算机软件系统(工作流管理系统)控制其执行的过程都称为工作流。

一 个工作流包括一组活动及它们的相互顺序关系,还包括过程及活动的启动和终止条件,以及对每个活动的描述。工作流管理系统指运行在一个或多个工作流引擎上用 于定义、实现和管理工作流运行的一套软件系统,它与工作流执行者(人、应用)交互,推进工作流实例的执行,并监控工作流的运行状态。

WFMC 主要提出了五个接口与工作流执行服务一起共同组成了工作流系统:

l         接口一 ( 工作流定义交换 ) ,用于在建模和定义工具与执行服务之间交换工作流定义。主要是数据交换格式和 API 。数据交换通过 XPDL API 通过 WAPI

l         接口二 ( 工作流客户端应用接口 ) ,用于工作流客户端应用访问工作流引擎和工作列表,通过 WAPI 完成。

l         接口三 ( 被调用的应用接口 ) ,用于调用不同的应用系统。

l         接口四 ( 工作流系统互操作接口 ) ,用于不同工作流系统之间的互操作。

l         接口五 ( 系统管理和监控 ) ,用于系统管理应用访问工作流执行服务。

四.  核心调度算法

通常流程引擎采用的核心调度算法主要有 FSM 以及 PetriNet 两种,基于调度算法来完成流程的流转。

4.1.       FSM( 有限状态机 )

FSM 的定义为包含一组状态集( states )、一个起始状态( start state )、一组输入符号集( alphabet )、一个映射输入符号和当前状态到下一状态的转换函数( transition function )的计算模型。当输入符号串,模型随即进入起始状态。它要改变到新的状态,依赖于转换函数。在有限状态机中,会有有许多变量,例如,状态机有很多与动作( actions )转换 (Mealy ) 或状态(摩尔机)关联的动作,多重起始状态,基于没有输入符号的转换,或者指定符号和状态(非定有限状态机)的多个转换,指派给接收状态(识别者)的一个或多个状态,等等。

遵循 FSM 流程引擎通过状态的切换来完成流程的流转。

4.2.       PetriNet

信息流的一个抽象的、形式的模型。指出一系统的静态和动态性质。 petrinet 通常表示成图。图中有两类用弧彼此相连的结点(称为地点和变换)和指示其动态性能的标记(称为记号)。

遵循 PetriNet 流程引擎通过令牌来决定流程的流转。

posted @ 2006-08-11 18:26 Alex 阅读(503) | 评论 (0)编辑 收藏

1. 从奴隶社会到封建后期

工作流(WorkFlow)的概念是在现代信息系统的建设中逐步形成的,它有一个从局部到整体、从初级到高级、从简单到复杂、从奴隶社会到封建盛世的发展过程,按其发展历程,我们一般把它分为三个阶段:

﹡ EDF(电子数据流)阶段

EDF(电子数据流)阶段是工作流的奴隶社会阶段。此时的工作流在信息技术中的应用,仅着眼于利用信息技术减轻人们在流程中的计算强度,如设计一个流程用来协调多个会计统计帐目。所以,EDF最主要的特点是仅对企业单项业务进行处理,基本不涉及管理的内容。

﹡ TPF(事务处理流)阶段

TPF(事务处理流)阶段是工作流的封建初期。TPF并没有形成对企业的全局业务的管理,而着眼于对企业局部业务的管理,比如,设计一套工作流程,来管理物资的采购和供应。

﹡ IMF(信息管理流)阶段

当 今的工作流已经发展到封建后期-------IMF(信息管理流)阶段, IMF强调对企业业务的全局的整体性的管理。在这个阶段,工作流就是为了完成同一目标而相互衔接、自动进行的一系列业务活动或任务。目前,工作流技术与信 息技术以及企业管理紧密结合,已经悄悄渗入MIS系统、ERP系统和CRM系统等企业级关键系统中,并迅速成为这些系统的核心。在这个阶段,保皇派工作流 经历了大发展,革新派工作流也风涌而现。

2. 保皇派与革新派

与其它信息技术相比,工作流技术属于较新的 一个, 它现在仍处于标准的制定阶段,目前已有的标准按采用的技术分为两大派别,第一派是保皇派,基于纯XML技术;第二派是革新派,基于Web服务技术。保皇派 与革新派打得难分难解,所以,现在仍有一些工作流引擎没有采用任何标准而独立实现,也就是说,它们不依靠保皇派,也不依靠革新派。

2.1 保皇派分支

﹡ XPDL(Xml Process Definition Language)

XPDL 是保皇派最得人心的一派,因为它是太子。在工作流领域第一个致力于标准化工作的是Workflow Management Coalition (WfMC),它成立于1993年。1994年11月,wfmc发布了工作流管理系统的参考模型。参考模型提出了五类接口,有关过程模型的定义则构成了接 口一的核心内容。接口一早期的标准为WPDL(Workflow Process Definition Language),后来,这一接口的规范变更为XPDL。XPDL是至今工作流领域最为重要的一个标准,目前大多数工作流引擎是依据该标准设计开发的。

﹡ BPML(Business Process Model Language)

因为对太子派的工作方式不满意,BPMI发布BPML规范,成立新的八爷党。由于八爷党发展的非常之快,WfMC和BPMI在2002年6月26日宣布将合作制定业务流程和工作流标准,即采用BPML来描述工作流过程,同时采用XPDL所定义的工作流模型。

﹡ OMG的Workflow Management Facility

四 爷OMG是支持太子的,不过四爷这个人很有报负,在其他领域也做的有声有色。四爷OMG的Workflow Management Facility联合太子的WfMC规范,定义如何将工作流向CORBA转换---要知道, CORBA可是四爷的强项。现在很多老百姓支持四爷OMG的Workflow Management Facility。四爷这招,发展了自己的势力,又不惹太子生气,真是妙啊!

保皇派其它分支势力很小,这里就不多说了。

2.2 革新派分支

﹡ WSCI

2002 年6月26日,BEA,Intalio,SAP,Sun四家公司提出了基于xml的WSCI规范,推动Web服务进入了一个全新的阶段。这个规范主要描述 了一个参与和其它服务进行协作交互的Web服务所交换的消息流。WSCI是第一个革新派,后来又发展了几个新的革新派,

如WSFL(属IBM),Xlang(属MS),因有天生缺陷,均没有很大起色。

﹡ ebXML

ebXML 是一组支持模块化电子商务框架的规范。ebXML支持一个全球化的电子市场,它使得任意规模的企业通过交换基于XML的信息,不受地域限制地接洽和处理生 意。ebXML是联合国(UN/CEFACT,贸易促进和电子商务中心)和OASIS(结构化信息标准发展组织)共同倡导、全球参与开发和使用的规范。由 于现在老百姓都不喜欢抬着羊去换米,而喜欢在网上来个B2C,所以革新派ebXML最近发展很快。

﹡ BPEL

2002 年8月9日,Microsoft, BEA, IBM, SAP & Siebel联合提交发布了BPEL规范。 BPEL联合了一系列革新派/保皇派力量( XLANG, WSFL, BPML)。此规范描述如何处理输入的消息,它不是一个关于业务流程规格化定义的规范。简单的说,可以将它看作XML形式的编程语言,提供将WSDL- Services组合成控制流的能力。顾名思义,此规范重点在(也不只限于)Web Service。

还有其它的革新派如RosettaNet等,因为势力很小,这里也不多说了。

3. 大户人家

这里所谈的大户人家指工作流领域的商业软件供应商,他们都背靠靠山,或穷或富。我们这里按地区来划分他们。

3.1中国之外的大户

﹡ BEA 的WLI

﹡ Fujitsu的 i-Flow

﹡ IBM的 Holosofx

﹡ SAP 的NetWeaver

﹡ Sonic 的Orchestration Server

﹡ Ultimus

﹡ Versata

这些人家大都非常富有;如果需要,请自己搜索他们的信息。

3.2国内的大户人家

﹡ 信雅达的SunFlow 这个公司留给我的印象很好,包括他们的总经理石总。

﹡ 西安协同的协同工作流

﹡ 上海东兰的DLFlo

这里对公司就不多介绍了,否则有做广告的嫌疑J。本人有国内工作流产品的比较报告,大家需要可以给我发邮件索取。

4. 寒门傲骨

这里的寒门傲骨指的是开源工作流引擎的实现,寒门子弟也是有政治取向的,我们还是按保皇派和革新派来区分他们,而自由派指没有按固定的标准来实现的工作流门派。

4.1保皇派寒门

﹡ OFBiz

OFBiz 最主要的特点是OFBiz提供了一整套的开发基于Java的web应用程序的组件和工具。其中包括实体引擎, 服务引擎, 消息引擎, 工作流引擎, 规则引擎等。OFBiz先前的工作流引擎基于WfMC和OMG的规范,使用XPDL作为流程定义语言,也就是说,它是支持太子XPDL的,而且和十三爷 OMG的关系非常之好。OFBiz新版的工作流引擎采用Shark工作流引擎,我们不建议再去学习OFBiz自身的工作流引擎。

﹡ OBE

OBE 是由Adrian Price主持开发的一个开放源码的Java工作流引擎,支持WfMC规范,包括接口1(XPDL)、接口2/3(WAPI)和接口5。OBE主要基于 J2EE实现。OBE的接口1实现得非常好,可惜,OBE的载体公司Zaplet已经于前不久被合并,合并后的公司没有继续发展OBE的打算。 Adrian Price离开了原来的公司,投奔我们前面说过的大户Versata。Versata也不打算继续OBE。OBE至今没有release版,很是可惜。

﹡ Shark

Shark 是完全根据WFMC规范实施的,可扩展功能的工作流引擎,它利用xpdl来定义流程,同时还包括服务器端的用于活动节点执行的WFMC工具代理API。 Shark中的每个组件例如持久层,事物管理器,脚本引擎,流程库,都是可以按照标准实施运用的,而且还可以被具体项目的模块扩展和替换。Shark和 XPDL定义工具的事实标准JAWE同出名门,市场前景被很多人看好。OFBiz新版的工作流引擎采用Shark工作流引擎,OBE的载体公司 Zaplet被合并,对Shark的发展将很有利。2004年9月9日,shark发布1.0版本,对它的发展无疑是一剂强心针。笔者从Shark发展的 早期就在国内力推它,有幸成为Shark工作流引擎在国内的主要推广者之一(http://blog.csdn.net/hongbo781202/), 感到十分荣幸。Shark的讨论请看http://211.95.124.238:22/cgi-bin/forums.cgi?forum=24。

4.2 革新派寒门

﹡ OpenebXML

OpenebXML项目致力于提供一个ebXML框架,主要支持 UN/CEFACT和OASIS发布的ebXML规范2.0版。

﹡ Bonita

Bonita是一个符合WfMC规范、灵活的协同工作流系统。Bonita基于浏览器、使用SOAP和XML数据绑定技术的Web Services封装了已有的工作流业务方法并将它们以基于J2EE的Web Service形式发布。

﹡ Twister

Twister的目标是提供新一代、易集成、应用Java领域中最新成果、面向B2B的工作流解决方案。流程引擎基于BPEL业务流程规范和Web Service标准。

﹡ ActiveBpel

ActiveBPEL 引擎是一个于今年7月发布的健壮的运行时环境,它能执行用户按BPWL4WS规范编写的业务流程。ActiveBPEL引擎由Active Endpoints公司开发和维护,该公司同时在它的多个商业产品中使用了该技术。本人将密切观注ActiveBPEL引擎的技术发展和产品状态。

4.3 自由派寒门

﹡ OSWorkflow

OSWorkflow的最大特点是灵活

﹡ OpenWFE

OpenWFE是一个开放源码的Java工作流引擎。 它的思想来源于 Scheme,包括可升级的三个组件:引擎、工作列表和Web界面。

﹡jBpm

jBpm 是tom baeyens编写的一个灵活可扩展的工作流管理系统。jBmp将工作流应用开发的便利性和杰出的企业应用集成(EAI)能力结合了起来。jBmp包括一 个Web应用程序和一个日程安排程序。jBmp是一组J2SE组件,可以作为J2EE应用集群部署。国内目前有部分人研究jBpm。

5 大局势

目前是封建社会后期,以太子党XPDL为首的保皇派还将辉煌一段时间。我个人认为,在Ofbiz投靠Shark,强势派OBE倒台,自由派不得人心的情况下,Shark工作流引擎依靠与XPDL定义工具JAWE的兄弟关系,将坐上保皇派头把交椅。

目 前,革新派和保皇派的争夺并不激烈。因为在现在的情况下, 革新派的根基Web服务并不劳靠,在老百姓中的影响不太大,所以革新派只求从保皇派嘴边分口食就行了。但随着社会的发展, Web服务将越来越流行,现在,MS/IBM/BEA等跨国巨头越来越主推BPEL4WS标准,并且已经发布基于BPEL4WS标准的系列产品,而且,他 们还主推Integration/Portal的概念,这些概念将把工作流带入资本主义阶段。
posted @ 2006-08-11 18:25 Alex 阅读(622) | 评论 (0)编辑 收藏

Osworkflow完全用java语言编写的开放源代码的工作流引擎,具有显著的灵活性及完全面向有技术 背景的用户的特点。用户可以根据自身的需求利用这款开源软件设计简单或是复杂的工作流。通过使用,用户就可以把工作中心放在业务和规则的定义上,而不需通 过硬编码的方式实现一个Petri网或是一个有穷自动机。用户可以以最小的代价把osworkflow整合到自己的程序中来。Osworkflow几乎提 供了所有用户可能在实际流程定义中需要用到的工作流构成元素,如:环节(step)、条件(conditions)、循环(loops)、分支 (spilts)、合并(joins)、角色(roles)等等。(假如读者对这些概念还不熟悉,笔者将在Osworkflow基本概念一节中进行简单描 述。)

但是,这款开源软件的文档十分匮乏,而且在大多数现实情形中并不适用。本文将尝试为读者填平实际的用例需求与十分简单的说明文档间的鸿沟。

用户可以在OpenSymphony的网站上下载osworkflow的发布。当前的最高版本是2.7(译者注:最新版本为2.8). 解压缩发布的软件包,即得到二进制程序、源代码、API文档、说明文档等。用户可以在软件的论坛和维基上获得进一步的帮助。

版权声明:任何获得Matrix授权的网站,转载时请务必保留以下作者信息和链接
作者:Diego Naya;bugaboo(作者的blog:http://blog.matrix.org.cn/page/bugaboo)
Matrix原文:http://www.matrix.org.cn/resource/article/44/44467_osworkflow.html
关键字:osworkflow;business

什么是工作流?

维基百科(Wikipedia,WP)把工作流定义为“一份工作的操作过程”:任务如何组成、如何操作、相关顺序如何、如何同步、信息如何流动以支持这些任务、以及任务如何被跟踪等。
一个工作流引擎实现了业务的流程处理。用户应可以自动跟踪过程,这将使得引擎更具效率。同时用户可以对工作流进行建模,监控及统计引擎数据等。

示例业务过程:贷款程序

本 文的示例业务过程研究一个贷款应用程序的实例。我们将通过一个利用osworkflow工作流引擎的工作流来实现它。这个过程会在每家银行及金融机构中出 现, 其区别仅仅体现为有更过的部门或更多地文档需要处理. 在本示例中, 我们会用尽量简单的方法来实现这个业务流程以便于用户理解。图一描述了这个业务流程

image
图一 贷款业务流程

过程非常简单,分为如下4步,如下所示:
1)        填写表格:银行客户填写表格申请贷款。
2)        风险分析:一位风险分析家评估不良贷款的风险。
3)        财务历史审查:财务管理官员负责检查客户历史贷款、应付账单、信用卡历史纪录等信息。
4)        最终决定(同意/拒绝):银行部门主管根据风险分析情况及财务历史审查情况最终决定是否贷款给该客户。

正如我们之前看到的,每个工作流都包含角色,每个角色都包含被分配的任务。下文说明了业务流程中涉及到的角色:
1)        前台职员:在某个银行部门向顾客提供信贷申请表的雇员。
2)        财务官员:负责检查申请者历史财务情况(往期贷款、未支付帐单等等)的职员。
3)        风险分析家:负责分析将钱给予借贷申请者的外部因素(比如社会经济情况等)及借贷者本人的个人情况。
4)        银行部门经理:负责最终决定是否给予借贷者贷款的经理。
请记住,“信贷申请表”是一个重要的概念(我们将在系统实现一节看到其重要性)因为它是流经整个工作流的业务数据。

基本工作流概念

笔者在开篇曾介绍osworkflow提供了一些特有的构造,现在笔者将逐一介绍它们。

首 先,在osworkflow中读者需要了解得最重要的概念是环节,每个工作流包含了多个环节,读者可以把环节想象成工作流中每一个重要的活动。每个环节可 以有一些诸如“已完成”、“正在处理”、“已添加至处理队列”、“未处理”等的状态,设计工作流的人可以根据需要自己定义状态。

在每个环节,动作被用户指定为自动或手动地执行。每个动作执行后,都有一个结果(result)。结果决定了工作流的流转方向:可以停留在同一环节,跳转到另一环节,跳转到一个分支,或者汇集到一个合并等。
最后两个概念涉及用户对业务流程的并发执行,分支把工作流分解为两个并行的环节,合并则在用户满足一定条件后,把两个并行的环节合并成一个。

动 作的执行代表了业务流程的执行,每个动作都有一组预处理功能(pre-functions)和一组后处理功能(post-functions)。其作用正 如读者想象的那样,一个在动作触发之前执行,一个在动作触发之后执行。一个简单的例子是:可以在预处理功能中检验申请表格数据的正确性,而后在后处理贡功 能中把经检验的数据保存至数据库。

动作的执行结果可以是有条件的(conditional)或无条件的(unconditional)。 对于有条件的结果,引擎将首先检查是否条件被满足,然后再交给工作流来处理。如果条件不满足的话,引擎将进一步判断下一个有条件结果是否得到满足,以此类 推,直到系统最终执行到无条件结果进行处理。

读者可能会问,如果所有的条件结果都没有得到满足会如何呢?事实上,每个动作都强制要求具有唯一一个无条件结果。与此对应的,可以有多个有条件的结果。

业务规则常常在最终结果中带有条件判断,比如,“如果申请来自于一个老客户,则流转到环节1”或者“如果当前系统的用户的角色是经理的话,直接流转道最后一个环节”。

最 后一个重要的概念是步骤状态(process state),在osworkflow中,当前步骤状态是所有当前环节状态的集合。读者可能会认为工作流在运行过程中只能有一个状态,但现实的情况是:因 为对分支和合并的支持,引擎能够做到对环节的并发控制,因此工作流的当前状态就可能出现:“等待风险分析及已核查财务历史”的情况。
激活动作的用户被顺理成章地称为触发者(caller),每个环节都有一个所有者(owner),以代表在当前环节中负责执行动作的角色或用户。

当用户在环节中运转流程的时候,已完成的环节被保存至历史表中(history),用户当前所处的环节成为当前环节(current steps)。

最 后,读者可能注意到,在osworkflow中并不存在其他工作流引擎中所包含的工作项(workitem)的概念。这是因为osworkflow是“十 分底层”的工作流实现,怎样实现或定义工作项完全交由用户来决定。笔者认为工作项的概念太过抽象,用业务数据来称呼它或许更为贴切一些。

Osworkflow 的文档中介绍了更多的构造元素,如寄存器(Registers),共用方法(common functions)等,但笔者建议在建立好第一个工作流以后再去研究它们。它们是osworkflow基本元素外的高级特性,而我们前面所认识的元素则 是osworkflow的根本所在。


Osworkflow体系结构

我们将在本节分析控制osworkflow的体系结构,我们需要理解它是怎样适用到我们的程序中来的。如我们所猜想的,Osworkflow最主要的接口是Workflow,这个接口也是整个工作流引擎的入口点。是整个系统的门面(facade)。

接口的实现主要关注具体的业务操作能力,这个接口定义了工作流查询,获取当前的可执行动作,执行动作,显示历史环节等。
工作流被持久化在工作流存储体(Workflow Store)中,osworkflow提供了几种持久化的方法,包括Hibernate持久化集成,JDBC持久化集成等。一个存储体包含了环节信息,变量,工作流自身的描述信息等等。

用户可能遇到的最常见的应用模式如下所示:
1)通过给定的状态在工作流存储体中查询工作流信息,通常还根据某一个工作流程中具有需执行动作的用户来进行查询。这种查询时通过WorkflowQuery对象中的Workflow.query()方法实现的。
2)通过getAvailableActions()方法列出所有在满足条件查询结果中可执行的操作。
3)通过doAction()方法执行用户选择的动作。在执行动作的时候一些执行参数可以以java.util.Map的形式传递,以实现在工作流定义的运行期进行信息的传递。
4)用户可以有选择地通过调用initialize()实例化一个工作流。

在理想情况下,由业务逻辑层负责调用osworkflow中的方法,如图二所示:

image
图二 在业务逻辑中集成工作流

在osworkflow 中,业务逻辑描述在一个XML文件中,称为工作流描述符(workflow descriptor.)。我们将在实现小节中建立一个简单的描述符。在工作流描述符中的功能(functions)和条件(conditions)中, 用户可以定义自己的业务逻辑。笔者将在把工作流集成到应用程序中一节中进行论述。

实现

本小节介绍如何把一个业务逻辑抽象成一个工作流。首先我们要在业务流程图中识别出工作流的环节。如图一所示,显然,我们共有四个环节,同时包含一个分支及一个合并。在下面的bank.xml文件中,读者将看到它们在描述符中是如何被表示的。

建立好环节以后,必须在每个环节中添加一些动作以便于工作流运转。每个动作有唯一的无条件结果,条件结果由读者有选择地来实现。
<step id="1" name="Form Filling">
<actions>
  <action id="2" name="Fill Form">
   <results>
        <unconditional-result old-status="Finished" split="1"/>
   </results>
  </action>
</actions>
</step>


接下来要并行地执行风险分析和财务历史核查,这里是放置分支的最理想地点。
<splits>
<split id="1">
  <unconditional-result old-status="Finished"
    status="Underway" owner="Risk Analyst" step="2"/>
  <unconditional-result old-status="Finished"
    status="Underway" owner="Financial Officer" step="3"/>
</split>
</splits>


在 部门经理最终确认以前,并发的工作流环节必须得到合并。我们可以通过应用一个合并(join)来实现它,合并通过一个条件告诉工作流引擎,是否可以合并并 进行到下一环节。在本例中,我们假设这个条件为:前面两个环节都已具有“Finished”的结束状态。即当风险分析或财务审核任何一个未完成前,不能进 行到下一步:
<joins>
<join id="1">
  <conditions type="AND">
   <condition type="beanshell">
    <arg name="script"><![CDATA[
     "Finished".equals(jn.getStep(2).getStatus()) &&
        "Finished".equals(jn.getStep(3).getStatus())
      ]]></arg>
    </condition>
   </conditions>
  <unconditional-result old-status="Finished"
    status="Underway" owner="Manager" step="4"/>
</join>
</joins>


下面在描述符中加入每个环节的所有者,正如我们在基本概念一节看到的那样,所有者通常代表了环节间交互的角色,角色的引入默认情况下通过osuser框架来实现。
用户既可以手写XML描述符文件,也可以通过osworkflow提供的设计器来实现。读者可以在OpenSymphony的网站上试用这个工具。

测试实现
测试时,我们可以应用osworkflow提供的例子,把bank.xml放到WEB-INF/classes文件夹下,在文件workflows.xml中添加一行以使引擎能够识别这个工作流。

把工作流集成到应用程序

在建模及测试工作流之后,我们即可以通过下面的几行代码把osworkflow集成到我们的程序中。
orkflow wf = new BasicWorkflow(username); 
HashMap inputs = new HashMap();
inputs.put("docTitle", request.getParameter("title"));
wf.initialize("workflowName", 1, inputs);


inputs 哈希表包含了初始工作流动作中需要传出的参数,有几个实现了Workflow接口的类,其中BasicWorkflow是不支持事务的简单实现。在工作流 执行过程中可以在流程中调用外部的方法,这种方法应该是实现了FunctionProvider接口的方法类。然后我们就可以用以下的方式调用它:

<action id="1" name="Execute business rule">
<pre-functions>
  <function type="class">
   <arg name="class.name">java.net.DroolsExecutorFunction</arg>
   <arg name="ruleBaseName">BusinessRules.drl</arg>
  </function>
</pre-functions>
...


用户可以通过实现Condition接口,添加自己的条件控制。FunctionProvider及Condition接口可以调用工作流中的已知方法,这两个接口都可以接受来自于XML描述符文件中的参数。

结论

把 一个业务流程抽象成一个工作流的任务并不容易,需要好的方法和合适的工具,osworkflow是一个为我们提供了许多可重用结构的理想工具。希望通过对 本文的阅读,读者能够理解最基本的osworkflow概念。本文论述过程中所采用的方法非常基础和简单,但却值得借鉴。
posted @ 2006-08-11 18:16 Alex 阅读(963) | 评论 (1)编辑 收藏

key words: decorator 装饰模式 jdk中的装饰模式

JDK为程序员提供了大量的类库,而为了保持类库的可重用性,可扩展性和灵活性,其中使用到了大量的设计模式,本文将介绍JDK的I/O包中使用到的Decorator模式,并运用此模式,实现一个新的输出流类。

  Decorator模式简介

  Decorator模式又名包装器(Wrapper),它的主要用途在于给一个对象动态的添加一些额外的职责。与生成子类相比,它更具有灵活性。
有 时候,我们需要为一个对象而不是整个类添加一些新的功能,比如,给一个文本区添加一个滚动条的功能。我们可以使用继承机制来实现这一功能,但是这种方法不 够灵活,我们无法控制文本区加滚动条的方式和时机。而且当文本区需要添加更多的功能时,比如边框等,需要创建新的类,而当需要组合使用这些功能时无疑将会 引起类的爆炸。

  我们可以使用一种更为灵活的方法,就是把文本区嵌入到滚动条中。而这个滚动条的类就相当于对文本区的一个装饰。 这个装饰(滚动条)必须与被装饰的组件(文本区)继承自同一个接口,这样,用户就不必关心装饰的实现,因为这对他们来说是透明的。装饰会将用户的请求转发 给相应的组件(即调用相关的方法),并可能在转发的前后做一些额外的动作(如添加滚动条)。通过这种方法,我们可以根据组合对文本区嵌套不同的装饰,从而 添加任意多的功能。这种动态的对对象添加功能的方法不会引起类的爆炸,也具有了更多的灵活性。

  以上的方法就是Decorator模式,它通过给对象添加装饰来动态的添加新的功能。如下是Decorator模式的UML图:



  Component为组件和装饰的公共父类,它定义了子类必须实现的方法。

  ConcreteComponent是一个具体的组件类,可以通过给它添加装饰来增加新的功能。

  Decorator是所有装饰的公共父类,它定义了所有装饰必须实现的方法,同时,它还保存了一个对于Component的引用,以便将用户的请求转发给Component,并可能在转发请求前后执行一些附加的动作。

  ConcreteDecoratorA和ConcreteDecoratorB是具体的装饰,可以使用它们来装饰具体的Component。

  Java IO包中的Decorator模式

  JDK提供的java.io包中使用了Decorator模式来实现对各种输入输出流的封装。以下将以java.io.OutputStream及其子类为例,讨论一下Decorator模式在IO中的使用。

  首先来看一段用来创建IO流的代码:

以下是代码片段:
try {
 OutputStream out = new DataOutputStream(new FileOutputStream("test.txt"));
} catch (FileNotFoundException e) {
 e.printStackTrace();
}

   这段代码对于使用过JAVA输入输出流的人来说再熟悉不过了,我们使用DataOutputStream封装了一个FileOutputStream。 这是一个典型的Decorator模式的使用,FileOutputStream相当于Component,DataOutputStream就是一个 Decorator。将代码改成如下,将会更容易理解:

以下是代码片段:
try {
 OutputStream out = new FileOutputStream("test.txt");
 out = new DataOutputStream(out);
} catch(FileNotFoundException e) {
 e.printStatckTrace();
}

  由于FileOutputStream和DataOutputStream有公共的父类OutputStream,因此对对象的装饰对于用户来说几乎是透明的。下面就来看看OutputStream及其子类是如何构成Decorator模式的:



OutputStream是一个抽象类,它是所有输出流的公共父类,其源代码如下:

以下是代码片段:
public abstract class OutputStream implements Closeable, Flushable {
public abstract void write(int b) throws IOException;
...
}

它定义了write(int b)的抽象方法。这相当于Decorator模式中的Component类。

ByteArrayOutputStream,FileOutputStream 和 PipedOutputStream 三个类都直接从OutputStream继承,以ByteArrayOutputStream为例:

以下是代码片段:
public class ByteArrayOutputStream extends OutputStream {
protected byte buf[];
protected int count;
public ByteArrayOutputStream() {
this(32);
}
public ByteArrayOutputStream(int size) {
if (size 〈 0) {
throw new IllegalArgumentException("Negative initial size: " + size);
}
buf = new byte[size];
}
public synchronized void write(int b) {
int newcount = count + 1;
if (newcount 〉 buf.length) {
byte newbuf[] = new byte[Math.max(buf.length 〈〈 1, newcount)];
System.arraycopy(buf, 0, newbuf, 0, count);
buf = newbuf;
}
buf[count] = (byte)b;
count = newcount;
}
...
}

它实现了OutputStream中的write(int b)方法,因此我们可以用来创建输出流的对象,并完成特定格式的输出。它相当于Decorator模式中的ConcreteComponent类。

接着来看一下FilterOutputStream,代码如下:

以下是代码片段:
public class FilterOutputStream extends OutputStream {
protected OutputStream out;
public FilterOutputStream(OutputStream out) {
this.out = out;
}
public void write(int b) throws IOException {
out.write(b);
}
...
}

同 样,它也是从OutputStream继承。

但是,它的构造函数很特别,需要传递一个OutputStream的引用给它,并且它将保存对此对象的引用。 而如果没有具体的OutputStream对象存在,我们将无法创建FilterOutputStream。由于out既可以是指向 FilterOutputStream类型的引用,也可以是指向ByteArrayOutputStream等具体输出流类的引用,因此使用多层嵌套的方 式,我们可以为ByteArrayOutputStream添加多种装饰。这个FilterOutputStream类相当于Decorator模式中的 Decorator类,它的write(int b)方法只是简单的调用了传入的流的write(int b)方法,而没有做更多的处理,因此它本质上没有对流进行装饰,所以继承它的子类必须覆盖此方法,以达到装饰的目的。

BufferedOutputStream 和 DataOutputStream是FilterOutputStream的两个子类,它们相当于Decorator模式中的 ConcreteDecorator,并对传入的输出流做了不同的装饰。以BufferedOutputStream类为例:

以下是代码片段:
public class BufferedOutputStream extends FilterOutputStream {
...
private void flushBuffer() throws IOException {
if (count 〉 0) {
out.write(buf, 0, count);
count = 0;
}
}
public synchronized void write(int b) throws IOException {
if (count 〉= buf.length) {
flushBuffer();
}
buf[count++] = (byte)b;
}
...
}


   这个类提供了一个缓存机制,等到缓存的容量达到一定的字节数时才写入输出流。首先它继承了FilterOutputStream,并且覆盖了父类的 write(int b)方法,在调用输出流写出数据前都会检查缓存是否已满,如果未满,则不写。这样就实现了对输出流对象动态的添加新功能的目的。

  下面,将使用Decorator模式,为IO写一个新的输出流。

  自己写一个新的输出流

   了解了OutputStream及其子类的结构原理后,我们可以写一个新的输出流,来添加新的功能。这部分中将给出一个新的输出流的例子,它将过滤待输 出语句中的空格符号。比如需要输出"java io OutputStream",则过滤后的输出为"javaioOutputStream"。以下为SkipSpaceOutputStream类的代码:

以下是代码片段:
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* A new output stream, which will check the space character
* and won’t write it to the output stream.
* @author Magic
*
*/
public class SkipSpaceOutputStream extends FilterOutputStream {
 public SkipSpaceOutputStream(OutputStream out) {
  super(out);
 }
 /**
 * Rewrite the method in the parent class, and
 * skip the space character.
 */
 public void write(int b) throws IOException{
  if(b!=’ ’){
   super.write(b);
  }
 }
}

  它从FilterOutputStream继承,并且重写了它的write(int b)方法。在write(int b)方法中首先对输入字符进行了检查,如果不是空格,则输出。

  以下是一个测试程序:

以下是代码片段:
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Test the SkipSpaceOutputStream.
* @author Magic
*
*/
public class Test {
 public static void main(String[] args){
  byte[] buffer = new byte[1024];

  /**
  * Create input stream from the standard input.
  */
  InputStream in = new BufferedInputStream(new DataInputStream(System.in));

  /**
  * write to the standard output.
  */
  OutputStream out = new SkipSpaceOutputStream(new DataOutputStream(System.out));

  try {
   System.out.println("Please input your words: ");
   int n = in.read(buffer,0,buffer.length);
   for(int i=0;i〈n;i++){
    out.write(buffer[i]);
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}

  执行以上测试程序,将要求用户在console窗口中输入信息,程序将过滤掉信息中的空格,并将最后的结果输出到console窗口。比如:

以下是引用片段:
Please input your words:
a b c d e f
abcdef

  总 结

   在java.io包中,不仅OutputStream用到了Decorator设计模式,InputStream,Reader,Writer等都用到 了此模式。而作为一个灵活的,可扩展的类库,JDK中使用了大量的设计模式,比如在Swing包中的MVC模式,RMI中的Proxy模式等等。对于 JDK中模式的研究不仅能加深对于模式的理解,而且还有利于更透彻的了解类库的结构和组成

(转载文章请保留出处:Java家(www.javajia.com))

posted @ 2006-08-10 21:04 Alex 阅读(693) | 评论 (0)编辑 收藏

key words : POI java读取Excel  java.io.IOException Unable to read entire block

版本:2.5.1final
错误提示:
java.io.IOException Unable to read entire block

出这个问题具有随机性,有时候没问题,有时候将Excel里的CellType改一下好像就没问题,但也不总是这样,真是莫名其妙.

Google了一下是一个bug,重新下载src文件,将RawDataBlock.java文件的RawDataBlock(final InputStream stream)constructor覆盖:

public RawDataBlock(final InputStream stream) throws IOException
    {
        _data 
= new byte[ POIFSConstants.BIG_BLOCK_SIZE ];
        
int count = 0;
        
int totalBytesRead = 0;
        
while ((totalBytesRead < POIFSConstants.BIG_BLOCK_SIZE) &&
(count 
!= -1)) {
                count 
= stream.read(_data, totalBytesRead,
POIFSConstants.BIG_BLOCK_SIZE 
- totalBytesRead);
                
if (count != -1) {
                        totalBytesRead 
+= count;
                }
        }
          
if (count == -1) {
                _eof 
= true;
          } 
else {
            _eof 
= false;
        } 
          
if ((totalBytesRead != POIFSConstants.BIG_BLOCK_SIZE) && (totalBytesRead != 0)) {
            String type 
= " byte" + ((totalBytesRead == 1? (""): ("s"));
            
throw new IOException("Unable to read entire block; " +
totalBytesRead 
+ type + " read; expected " + POIFSConstants.BIG_BLOCK_SIZE + "bytes");
        }
    }


打包:
ant jar

重启app,OK!

说明:
主要问题出在 InputStream的read上,原来的实现用ReadFully方法:
public static int readFully(InputStream in, byte[] b, int off, int len)
    
throws IOException
    {
        
int total = 0;
        
for (;;) {
            
int got = in.read(b, off + total, len - total);
            
if (got < 0) {
                
return (total == 0? -1 : total;
            } 
else {
                total 
+= got;
                
if (total == len)
                    
return total;
            }
        }
    }

InputStream的read不能确保返回的是最大字节数,但是另一个实现却可以:
ByteInputStream
所以,下面的方法也可以修改这个问题:
 // read entire stream into byte array:
    ByteArrayOutputStream byteOS = new ByteArrayOutputStream();
    
byte[] buffer = new byte[1024];
    
int count;
    
while (count = inputStream.read(buffer)) != -1)
        byteOS.append(buffer, 
0, count);
    byteOS.close();
    
byte[] allBytes = byteOS.betByteArray();

// create workbook from array:
InputStream byteIS = new ByteArrayInputStream(allBytes);
HSSFWorkbook wb 
= new HSSFWorkbook(byteIS);

posted @ 2006-08-10 17:09 Alex 阅读(3584) | 评论 (1)编辑 收藏

By: Wu Yin
Date: 2006-06-30
Email: lazy_fox#msn.com
Link: http://blog.csdn.net/wooin/archive/2006/07/11/903974.aspx
版权信息: 该文章版权由Wu Yin所有。可在非商业目的下任意传播和复制。
对于商业目的下对本文的任何行为需经作者同意。
联系方式:lazy_fox#msn.com

1. 本文需要两个文件,httpd和subversion。
·httpd是web服务器,用来通过web访问subversion,这里是官方网站,这里是它的下载网页,
  这里可以下载到httpd-2.2.2.tar.bz2。
·subversion就是本文的主角,这里是他的官方网站,这里是它的下载网页,
  这里可以下载到subversion-1.3.1.tar.bz2
2. 新建一个用户:svnroot
最好不要让root用户参与到svn的权限管理和日常的运行和维护工作中来,但是下面的一些安装和配置操作还是 需要root用户来完成的,因为有些操作只有root才能做。
3. 编译安装httpd (root用户操作):
//解压apache2安装包
# tar xvzf httpd-2.2.2.tar.gz
//进入解压后的目录
# cd httpd-2.2.2
//配置apache安装,前两个参数是必须要加的,你还可以根据您的需要添加其他的参数。
//后面的参数制定你要把apache安装哪里
# ./configure --enable-dav --enable-so --prefix=/usr/local/apache2/
# make
//安装
# make install
# cd /usr/local/apache2/bin
//启动apache服务
# ./apachectl start
//打开浏览器http://localhost/如果有测试页"It works!"出现则证明已经安装成功。
3. 安装Subversion
//解压SubVersion安装包 (root用户进行下面的操作)
# tar xvzf Subversion-1.3.1.tar.gz
//进入解压后的目录
# cd Subversion-1.3.1
//配置subversion安装
#./configure --with-apxs=/usr/local/apache2/bin/apxs --prefix=/usr/local/subversion
--with-apr=/usr/local/apache2 --with-apr-util=/usr/local/apache2 --with-ssl --with-zlib
--enable-maintainer-mode
# make
//安装
# make install
//创建库文件所在的目录 (svnroot用户进行下面的操作)
# mkdir /home/svnroot/repository
//进入subversion的bin目录
# cd /usr/local/subversion/bin
//创建仓库"test"
# ./svnadmin create /home/svnroot/repository/test
# cd /home/svnroot/repository/test
//看看是不是多了些文件,如果是则说明Subversion安装成功了
# ls –l
# cd /usr/local/subversion/bin
//这条语句将把路径/home/user/import下找到的文件导入到你创建的Subversion 仓库中去,
//提交后的修订版为1。
# ./svn import /home/user/import file:///home/svnroot/repository/test –m "注释"
//不让其他人有该目录的权限
# chmod 700 /home/svnroot/repository
4. 修改Apache配置文件
# cd /usr/local/apadche2/bin
//启动Apache
# ./apachect1 start
# vi /usr/local/apache2/conf/httpd.conf
   //在最下面添加
   LoadModule dav_svn_module modules/mod_dav_svn.so
   LoadModule authz_svn_module modules/mod_authz_svn.so
   <Location /svn>
   DAV svn
   SVNParentPath /home/svnroot/repository/ //svn父目录
   AuthzSVNAccessFile /home/svnroot/repository/authz.conf //权限配置文件
   AuthType Basic //连接类型设置
   AuthName "Subversion.zoneyump" //连接框提示
   AuthUserFile /home/svnroot/repository/authfile //用户配置文件
   Require valid-user //采用何种认证
   </Location>
   //其中authfile是通过"htpasswd [–c] /home/svnroot/repository/authfile username password"来创建的
   //"Require valid-user"告诉apache在authfile中所有的用户都可以访问。如果没有它,
   //则只能第一个用户可以访问新建库

5. 重启apache
# ./usr/local/apache2/bin/apachectl restart
//打开浏览器访问http://localhost/svn/test/,如果有东西显示就说明成功。
6. 权限管理
1)增加用户
# htpasswd [-c] /home/svnroot/repository/authfile wooin
//第一次设置用户时使用-c表示新建一个用户文件。回车后输入用户密码,完成对用户的增加
# htpasswd authfile 用户名(加入新的用户)
2)权限分配
# vi /home/svnroot/repository/authz.conf
   [test:/] //这表示,仓库test的根目录下的访问权限
   wooin = rw //test仓库wooin用户具有读和写权限
   bao = r //test仓库bao用户具有读权限
   [test2:/] //test2仓库根目录下的访问权限
   wooin = r //wooin用户在test2仓库根目录下只有读权限
   bao = //bao用户在 test2仓库根目录下无任何权限
   [/] //这个表示在所有仓库的根目录下
   * = r //这个表示对所有的用户都具有读权限
   #[groups] //这个表示群组设置
   #svn1-developers = wooin, bao //这个表示某群组里的成员
   #svn2-developers = wooin
   #[svn1:/]
   #@svn1-developers = rw //如果在前面加上@符号,则表示这是个群组权限设置
将这个设置完成后。重启Apache,就可以通过
http://localhost/svn/test
这个URL来访问仓库了,当然,受权限的限制,必须是合法用户才能访问且具有相应的权限
7. 一些备忘:
1. svn checkout http://localhost/svn/hello.world

2. svn commit 时的默认编辑器的环境变量$SVN_EDITOR=vi需要手动设定,用kate好像有问题

3. 如果linux的登录用户名密码都和svn的其中一个用户名密码相同时,在checkout的时候不会要求输 入用户名密码直接就可以checkout出来。比如:linux有个用户wooin,svn也有一个用户wooin,并且密码 都是一样的,当用wooin登录linux后,执行checkout,可以直接提取出源码文件,不用输入认证信息。

4. 在svn使用过程中牵扯到几种权限:文件系统的权限,linux系统权限,svn用户的权限,apache进程的权限。

文件系统的权限,linux系统权限:这里相同的意思,就是平时大家使用linux时文件夹和文件的访问权限。在 svn建立仓库,文件夹,配置文件的时候用svnroot用户,并将仓库权限设置为700,不允许其他用户直接通过 文件系统查看,只能由svnroot进行管理。

apache进程的权限:因为所有跟仓库传输的操作都是通过apache进程进行的,所以即使你给svn用户设置了 很大的权限,但是apache进程没有访问仓库或者相关文件的权限也没有用,apache进程的权限设置在 /usr/local/apache2/conf/httpd.conf 文件中配置,找到文件中的这两行:
User daemon # 将daemon改为svnroot,让apache进程以svnroot的身份运行
Group daemon

svn用户的权限:就是在repository/authz.conf文件中设置的权限信息,是svn用来管理仓库访问权限的。

5. svn服务器设置有两种方式:http 和 svnserve。这里介绍的是http方法

6. 在/etc/profile的结尾设置一些svn启动时要做的工作
# start apache server for svn
/usr/sbin/apachectl start
export SVN_EDITOR=vi

7. APR libraries 安装 SVN 的时候最好指定 --with-apr= 和 --with-apr-util= 参数到 Apache 安装的根目录
(ServerRoot)下,而不是使用缺省的 SVN 安装包中自带的 apr 。否则如果你安装的 Apache
版本不同有可能导致 APR 库不匹配,出现类似:
Can't set position pointer in file '/svn/test/db/revs/1': Invalid argument 的错误。
Updated 2006-04-20 16:30 -- 比如说如果你安装的是apache 2.2.0版本,就需要在编译安装svn的时候指定
--with-apxs和--with-apr参数到你的apache2.2.0安装目录下:
./configure --prefix=${subversionInstallFolder} /
--with-apxs=${apacheInstallFolder}/bin/apxs /
--with-apr=${apacheInstallFolder} /
--with-apr-util=${apacheInstallFolder} /
--with-ssl /
--with-zlib /
--enable-maintainer-mode
   
   
   

参考资料:
1. SVN學習筆記
2. Subversion版本管理器简单配置说明
3. 关于Subversion的安装、配置和权限管理
posted @ 2006-08-10 11:07 Alex 阅读(420) | 评论 (0)编辑 收藏

key words: svn subversion安装

一、Subversion的下载与安装
Subversion的官方网站:http://subversion.tigris.org/
可以在官方网站上下载Subversion的最新版本。本说明使用的是1.1.4的Win32版。
下载下来Subversion安装文件后,直接安装就可以了。这里假设系统上已经安装好了Apache了,这样,Subversion安装的时候选择Apache方式,它就会自动的配置相关的模块到Apache里。

二、Subversion的建立与使用仓库使用。
$svnadmin create /path/to/repos
在这里,我们假设设置D盘svn目录下的svn1和svn2两个目录为仓库。
svnadmin create d:/svn/svn1
svnadmin create d:/svn/svn2
这样,我们使用的时候,就可以向里面提交文件。
仓库的使用,必须先把服务搭建起来才行。我们等后面的服务器配置后再讲。

三、Subversion服务器的搭建
我们使用与Apache模块的方式运行。
首先,把我们需要的SVN模块加载上,修改Apache的配置文件httpd.conf:

LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule dav_module modules/mod_dav.so
LoadModule authz_svn_module modules/mod_authz_svn.so

然后配置仓库:

<Location /svn>
  DAV svn
  SVNParentPath d:/svn
</Location>
然后,配置验证方式:
这里使用旦Apache的验证方式:

htpasswd -cm d:/svn/svn-auth-file user1
然后,会提示输入密码,这里就加入了一个用户了。然后再加一个用户:
htpasswd -m d:/svn/svn-auth-file user2

然后修改配置:
<Location /svn>
DAV svn
SVNParentPath d:/svn
AuthType Basic
AuthName “Subversion repository”
AuthUserFile d:/svn/svn-auth-file
Require valid-user
AuthzSVNAccessFile d:/svn/svn-access-file
</Location>
下面,就要写这个svn-access-file文件了,它是用来控制用户访问仓库的权限的,我们把说明写在后面
[svn1:/]               //这表示,仓库svn1的根目录下的访问权限
harry = rw             // svn1仓库harry用户具有读和写权限
sally = r               // svn1仓库sally用户具有读权限
[svn2:/]               //svn2仓库根目录下的访问权限
harry = r               // harry用户在svn2仓库根目录下只有读权限
sally =               // sally用户在 svn2仓库根目录下无任何权限
#[/]               // 这个表示在所有仓库的根目录下
#* = r               // 这个表示对所有的用户都具有读权限
#[groups]               // 这个表示群组设置
#svn1-developers = harry, sally           // 这个表示某群组里的成员
#svn2-developers = sally
#[svn1:/]            
#@svn1-developers = rw       // 如果在前面加上@符号,则表示这是个群组权限设置

将这个设置完成后。重启Apache,就可以通过
http://localhost/svn/svn1
http://localhost/svn/svn2
这两个URL来访问仓库了,当然,要受权限的限制,必须是合法用户才能访问且具有相应的权限
客户端的使用,可以通过许多客户端GUI软件来用。比如TortoiseSVN就很好用。
官方网址:http://tortoisesvn.tigris.org/
posted @ 2006-08-10 11:05 Alex 阅读(372) | 评论 (0)编辑 收藏

key words : openldap ldap

发布时间:2004年04月07日

最近更新:2005年08月08日

Abstract

LDAP (轻量级目录服务访问协议,Lightweight Directory Access Protocol)基于X.500标准,支持TCP/IP,使用简单方便。现在越来越多的网络应用系统都支持LDAP。OpenLDAP是LDAP的一种 开源实现,本笔记基于OpenLDAP2.1.29。


Chapter 1. 目录服务简介

目 录是一个为查询、浏览和搜索而优化的专业分布式数据库,它成树状结构组织数据,就好象Linux/Unix系统中的文件目录一样。目录数据库和关系数据库 不同,它有优异的读性能,但写性能差,并且没有事务处理、回滚等复杂功能,不适于存储修改频繁的数据。所以目录天生是用来查询的,就好象它的名字一样。目 录服务是由目录数据库和一套访问协议组成的系统。类似以下的信息适合储存在目录中:

  • 企业员工和企业客户之类人员信息;

  • 公用证书和安全密钥;

  • 邮件地址、网址、IP等电脑信息;

  • 电脑配置信息。

  • ...

1.1. X.500和LDAP

现在国际上的目录服务标准有两个,一个是较早的X.500标准,一个是较新的LDAP标准。

  • X.500是一个协议族,由一系列的概念和协议组成,包括:

    • X.501是模型定义,定义目录服务的基本模型和概念;

    • X.509是认证框架,定义如何处理目录服务中客户和服务器认证;

    • X.511是抽象服务定义,定义X.500提供的功能性服务;

    • X.518是分布式操作过程定义,定义如何跨平台处理目录服务;

    • X.519 是协议规范,定义了X.500协议,包括DAP(Directory Access Protocol,目录访问协议)、DSP(Directory System Protocol,目录系统协议)、DOP(Directory Operator Protocol,目录操作绑定协议)、DISP(Directory Information Shadowing Protocol,目录信息阴影协议 );

    • X.520定义属性类型要求;

    • X.521定义对象类型;

    • X.525定义如果在目录服务器间复制内容。

    X.500标准中定义了很多内容,包括:

    • 定义了信息模型,确定目录中信息的格式和字符集,如何在项中表示目录信息(定义对象类、属性等模式);

    • 定义命名空间,确定对信息进行的组织和引用,如何组织和命名项-目录信息树DIT和层次命名模型;

    • 定义功能模型,确定可以在信息上执行的操作;

    • 定义认证框架,保证目录中信息的安全,如何实现目录中信息的授权保护-访问控制模型;

    • 定义分布操作模型,确定数据如何分布和如何对分布数据执行操作,如何将全局目录树划分为管理域,以便管理。

    • 定义客户端与服务器之间的通信的各种协议。

    由于X.500较复杂,且需严格遵照OSI七层协议模型。造成应用开发较困难。所以开发了LDAP,以便在INTERNET上使用。

  • LDAP协议于1993年获批准,产生LDAPv1版,1997年发布最新的LDAPv3版,该版本是LDAP协议发展的一个里程碑,它作为X.500的简化版提供了很多自有的特性,使LDAP功能更为完备,具有更强大的生命力。

    LDAP也是一个协议族,包含以下内容:

    • RFC 2251--LDAPv3核心协议,定义了LDAPv3协议的基本模型和基本操作;

    • RFC 2252--定义LDAPv3基本数据模式(Schema)(包括语法、匹配规则、属性类型和对象类)以及标准的系统数据模式;

    • RFC 2253--定义LDAPv3中的分辩名(DN)表达式;

    • RFC 2254--定义了LDAPv3中的过滤表达式;

    • RFC 2255--定义LDAPv3统一资源地址的格式;

    • RFC 2256--定义LDAPv3中使用X.500的Schema列表;

    • RFC 2829--定义了LDAPv3中的认证方式;

    • RFC 2830--定义了如何通过扩展使用TLS服务;

    • RFC 1823--定义了C的LDAP客户端API开发接口;

    • RFC 2847--定义了LDAP数据导入、导出文件接口LDIF。

    这些协议定义了LDAP的内容,包括:

    • 定义了一个信息模型,确定了LDAP目录中信息的格式和字符集,如何表示目录信息(定义对象类、属性、匹配规则和语法等模式);

    • 定义了命名空间,确定信息的组织方式--目录树DIT,以DN和RDN为基础的命名方式,以及LDAP信息的Internet表示方式;

    • 定义了功能模型,确定在可以在信息上执行的操作及API。

    • 定义了安全框架,保证目录中信息的安全,定义匿名、用户名/密码、SASL等多种认证方式,以及与TLS结合的通讯保护框架;

    • 定义分布式操作模型,基于指引方式的分布式操作框架;

    • 定义了LDAP扩展框架。

1.2. LDAP产品

现 在市场上有关LDAP的产品已有很多,各大软件公司都在他们的产品中集成了LDAP服务,如Microsoft的ActiveDirectory、 Lotus的Domino Directory、IBM的WebSphere中也集成了LDAP服务。LDAP的开源实现是OpenLDAP,它比商业产品一点也不差,而且源码开 放。

Chapter 2. OpenLDAP安装笔记

2.1. 源码安装

我的安装方法是以源码编译的方式进行的,以root用户进行安装。安装所需软件如下:

具体的安装步骤如下:

  1. 由于openldap需要Berkeley DB来存放数据,所以需先安装Berkeley DB 4.2.52,可到它的网站下载,网址见上面。运行下面的命令解压:

    # tar -zxvf db-4.2.52.tar.gz

    解完压后,会生成一个db-4.2.52目录,进行该目录下的build_unix目录。执行以下命令进行配置安装。

    # ../dist/configure
    # make
    # make install

    也是按linux源码安装的三步曲完成,没有什么好说的了。该软件默认是安装在/usr/local/BerkeleyDB.4.2目 录下。安装完成后,要把/usr/local/BerkeleyDB.4.2/lib的库路径加到/etc/ld.so.conf文件内,添加完成后执行 一次ldconfig,使配置文件生效。这样编译openldap时才能找到相应的库文件。这样资料库就安装完成了,接下来可以安装openldap了。 ld.so.conf是什么东西?它就是系统动态链接库的配置文件。此文件内,存放着可被LINUX共享的动态链接库所在目录的名字(系统目录/lib, /usr/lib除外),各个目录名间以空白字符(空格,换行等)或冒号或逗号分隔。一般的LINUX发行版中,此文件均含一个共享目录 /usr/X11R6/lib,为X window窗口系统的动态链接库所在的目录。 ldconfig是它的管理命令,具体操作方法可查询man手册,这里就不细讲了。

  2. 到openldap官方网站下载最新 的稳定版源码,并解压。查看INSTALLT 和README文档,这个很重要,因为安装方法和一些注意事项都在里面有介绍。认真弄明白文档内容能节省你不少的安装调试时间。这也是开源软件的一个特 点,给用户提供了最大的灵活性和可配置性。但也增加了系统安装配置的难度,需要有相关的文档配置说明和指导。在官方网站上还有详细的帮助文件,在整个系统 配置中需要经常查询。

    # tar -zxvf openldap-stable-20040329.tgz

    解压完成后,会生成一个openldap-2.1.29目录。进行该目录,执行以下命令进行配置安装。

    # env CPPFLAGS="-I/usr/local/BerkeleyDB.4.2/include" 
    LDFLAGS="-L/usr/local/BerkeleyDB.4.2/lib" ./configure --prefix=/usr/local/openldap
    --enable-ldbm

    注意以上配置语句,要设置资料库的include和lib路径,否则在配置到资料库相关内容时会提示Berkeley DB版本不兼容,并中断配置。如果没有--enable-ldbm选项,在make test时会提示ldbm找不到。为了减少出错,还是加上为好。

    #make depens
    #make
    #make test

    在make test阶段要花费较长时间进行测试,好像有16项吧。你可以放松一下,上上网,聊聊天,听听歌,呵呵,开玩笑了,这个时间应该是最紧张的了。成与不成就看这下的了,如果没问题就可安装了。

    #make install

    通过配置命令可以看出,我们把openldap安装到/usr/local/openldap目录下。建议以源码安装的软件都放到独立的目录下,不要放到软件默认的目录。好处是方便管理和控制,所有文件在统一的目录下,卸载软件只要删除整个目录就可以了。

  3. 安 装完相关软件后就可以着手配置了。Berkeley DB资料库没什么好配置的。主要是配置openldap 服务。配置文件在软件的安装目录的etc/openldap下,有四个文件,主要的是slapd.conf and ldap.conf,其它两个是backup文件。首先,我们先来配置slapd.conf文档。系统默认的slapd.conf文件如下:

    # $OpenLDAP: pkg/ldap/servers/slapd/slapd.conf,v 1.23.2.8 2003/05/24 23:19:14 kurt Exp $
    #
    # See slapd.conf(5) for details on configuration options.
    # This file should NOT be world readable.
    #
    include /usr/local/openldap/etc/openldap/schema/core.schema
    #设置schema配置文档包含

    # Define global ACLs to disable default read access.

    # Do not enable referrals until AFTER you have a working directory
    # service AND an understanding of referrals.
    #referral ldap://root.openldap.org

    pidfile /usr/local/openldap/var/slapd.pid
    #设置pid和args文档位置
    argsfile /usr/local/openldap/var/slapd.args

    # Load dynamic backend modules:
    # modulepath /usr/local/openldap/libexec/openldap
    # moduleload back_bdb.la
    # moduleload back_ldap.la
    # moduleload back_ldbm.la
    # moduleload back_passwd.la
    # moduleload back_shell.la

    # Sample security restrictions
    # Require integrity protection (prevent hijacking)
    # Require 112-bit (3DES or better) encryption for updates
    # Require 63-bit encryption for simple bind
    # security ssf=1 update_ssf=112 simple_bind=64

    # Sample access control policy:
    # Root DSE: allow anyone to read it
    # Subschema (sub)entry DSE: allow anyone to read it
    # Other DSEs:
    # Subschema (sub)entry DSE: allow anyone to read it
    # Other DSEs:
    # Allow self write access
    # Allow authenticated users read access
    # Allow anonymous users to authenticate
    # Directives needed to implement policy:
    # access to dn.base="" by * read
    # access to dn.base="cn=Subschema" by * read
    # access to *
    # by self write
    # by users read
    # by anonymous auth
    #
    # if no access controls are present, the default policy is:
    # Allow read by all
    #
    # rootdn can always write!

    #######################################################################
    # ldbm database definitions
    #######################################################################

    database bdb
    #设置使用的资料库,也可用lbdm。
    suffix "dc=my-domain,dc=com"
    #设置目录后缀
    rootdn "cn=Manager,dc=my-domain,dc=com"
    #设置目录管理员
    # Cleartext passwords, especially for the rootdn, should
    # be avoid. See slappasswd(8) and slapd.conf(5) for details.
    # Use of strong authentication encouraged.
    rootpw secret
    #设置管理密码,这里用了明文的“secret”密码。这样设置不安全,需使用加密的密码,下面会讲到如何设置加密密码。
    # The database directory MUST exist prior to running slapd AND
    # should only be accessible by the slapd and slap tools.
    # Mode 700 recommended.
    directory /usr/local/openldap/var/openldap-data
    #设置资料库路径
    # Indices to maintain
    index objectClass eq
    #设置目录项索引

    要服务器正常动作,要修改一些始初参数和设置,修改后的配置文档如下:

    # $OpenLDAP: pkg/ldap/servers/slapd/slapd.conf,v 1.23.2.8 2003/05/24 23:19:14 kurt Exp $
    #
    # See slapd.conf(5) for details on configuration options.
    # This file should NOT be world readable.
    #
    #为了有效使用目录服务,包含相关的文件。注意,在包含文件时是要按一定顺序的,因为
    #文件里的属性存在依赖关系。如果顺序不对,服务器启动不了,文档间的依赖关系在文档
    #中都有说明,请仔细查看一下。如果懒得看也可以按我的顺序。
    include /usr/local/openldap/etc/openldap/schema/core.schema
    include /usr/local/openldap/etc/openldap/schema/corba.schema
    include /usr/local/openldap/etc/openldap/schema/cosine.schema
    include /usr/local/openldap/etc/openldap/schema/inetorgperson.schema
    include /usr/local/openldap/etc/openldap/schema/misc.schema
    include /usr/local/openldap/etc/openldap/schema/openldap.schema
    include /usr/local/openldap/etc/openldap/schema/nis.schema
    include /usr/local/openldap/etc/openldap/schema/samba.schema
    # Define global ACLs to disable default read access.

    # Do not enable referrals until AFTER you have a working directory
    # service AND an understanding of referrals.
    #referral ldap://root.openldap.org

    pidfile /usr/local/openldap/var/slapd.pid
    argsfile /usr/local/openldap/var/slapd.args

    loglevel 1
    #增加了日志功能,需修改syslog配置文件,在文件中增加一项:local4.* /var/log/ldap.log日志级别定义可查相官方网站的文档。
    #1级记录的信息很多,可用于调试。
    # Load dynamic backend modules:
    # modulepath /usr/local/openldap/libexec/openldap
    # moduleload back_bdb.la
    # moduleload back_ldap.la
    # moduleload back_ldbm.la
    # moduleload back_passwd.la
    # moduleload back_shell.la

    # Sample security restrictions
    # Require integrity protection (prevent hijacking)
    # Require 112-bit (3DES or better) encryption for updates
    # Require 63-bit encryption for simple bind
    # security ssf=1 update_ssf=112 simple_bind=64

    # Sample access control policy:
    # Root DSE: allow anyone to read it
    # Subschema (sub)entry DSE: allow anyone to read it
    # Other DSEs:
    # Allow self write access
    # Allow authenticated users read access
    # Allow anonymous users to authenticate
    # Directives needed to implement policy:
    # access to dn.base="" by * read
    # access to dn.base="cn=Subschema" by * read
    # access to *
    # by self write
    # by users read
    # by anonymous auth
    #
    # if no access controls are present, the default policy is:
    # Allow read by all
    #
    # rootdn can always write!

    #######################################################################
    # ldbm database definitions
    #######################################################################

    database bdb
    suffix "dc=it,dc=com"
    #改成你自已的目录后缀,
    rootdn "cn=root,dc=it,dc=com"
    #设置root为管理员,与linux的root没有什么关系。
    # Cleartext passwords, especially for the rootdn, should
    # be avoid. See slappasswd(8) and slapd.conf(5) for details.
    # Use of strong authentication encouraged.
    rootpw {MD5}mjkiuPt0wXhpxxkdiOOO+0000000AKq0by
    #设置root密码,用MD5加密。密码串用slappasswd -h {MD5}指令生成
    # The database directory MUST exist prior to running slapd AND
    # should only be accessible by the slapd and slap tools.
    # Mode 700 recommended.
    directory /usr/local/openldap/var/openldap-data
    # Indices to maintain
    index objectClass eq
    #这里可根据你的需要设置相关索引,以加快查询速度。具体内容可查询官方网站管理手册。

    #ACL configure以下内容定义访问控制
    access to attr=userPassworduserPassword
    #只能由自已修改,有效验证用户查询。
    by self write
    by anonymous auth
    access to attr=mail
    by dn="cn=root,dc=it,dc=tigerhead" writemail
    #只能由自已修改,有效验证用户查询。
    by self write
    by anonymous auth
    access to dn=".*,dc=it,dc=tigerhead"
    #允许所有人查询没受控制访问限制的信息。
    by self write
    by * read

    到现在为止,服务器基本就配置完成了,可以启动了,服务器程序是位于安装目录的libexec下的slapd程序。注意,不是 sldap哦。ok,到现在为止,服务器基本就配置完成了,可以启动了,服务器程序是位于安装目录的libexec下的slapd程序。注意,不是 sldap哦。启动服务器执行以下命令:

    # ./slapd

    如果没有提示什么出错信息,直接返回shell状态,就说明服务器正常启动了,你可以查询日志或用ps -aux查看。或用以下命令查询服务器:

    ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts

    如果命令执行成功,返回一些信息,则说明服务器正常运行了。如果启动不成功,它会提示一些出错信息,多数是slapd.conf配置出错。回头仔细核查一下配置文档。

  4. 客户端配置文档是ldap.conf。该文档相当简单,其实不用配置也能正常操作。

    # $OpenLDAP: pkg/ldap/libraries/libldap/ldap.conf,v 1.9 2000/09/04 19:57:01 kurt Exp $
    #
    # LDAP Defaults
    #

    # See ldap.conf(5) for details
    # This file should be world readable but not world writable.

    BASE dc=it, dc=com设置目录起点
    #URI ldap://ldap.example.com ldap://ldap-master.example.com:666

    #SIZELIMIT 12
    #TIMELIMIT 15
    #DEREF never

2.2. 数据录入

服 务器正常运作后,就可以录入信息了。信息的录入有三种方法,一种是手工录入,一种是.ldif文件格式录入,一种是脚本自动录入。我们先从最基础的手工录 入方式开始介绍,了解录入信息的格式。明白了手工录入的格式,其它两种方式都很容易明白。信息录入用到ldapadd这个程序。可在安装目录的bin目录 下找到。

2.2.1. 手动录入方法

  • 第一步是要建立DN:

    # ldapadd -x -D 'cn=root,dc=it,dc=com' -W
    dn: dc=it,dc=com
    objectClass: dcObject
    objectClass: organization
    dc: it
    o: Corporation
    description: d Corporation
    注意:如果你用复制/粘贴功能把以上内容拷贝过去,一定要注意每行后面不要有空格,建议还是手工输入,按Ctrl+d存盘。
  • 第二步是建立RDN:

    # ldapadd -x -D 'cn=root,dc=it,dc=com' -W        
    #-x表示用简单验证,-D表示指定目录,-W表示弹出密码输入提示

    输入密码,这里的密码是在配置文件中rootpw项设置的密码,不是操作系统中root用户的密码。验证通过后就可输入以下内容:

    dn: uid=qq,dc=it,dc=com
    objectClass: person
    objectClass: organizationalPerson
    objectClass: inetOrgPerson
    uid: qq
    cn: qq
    sn: qq
    telephoneNumber: 138888888
    description: openldap test
    telexNumber: tex-8888888
    street: my street
    postOfficeBox: postofficebox
    displayName: qqdisplay
    homePhone: home1111111
    mobile: mobile99999
    mail:qq@qq.com

    输入完所有信息后,按Ctrl+d结束存盘。如果出现出错信息,请查一下对象类和属性的对应关系有没有错或输入失误。初学者就容易出错 的地方是对象类和属性的对应关系没有处理好。对象类和属性是在schema文档中定义的。它们之间的关系是这样的,对象类中有些属性是必选的,有些属性是 可选的。录入信息的属性必须在对象类中有定义才能用。

输入以下命令可查询到刚才输入的信息。

# ldapsearch -x -b 'dc=it,dc=com'            
-b选项是设置目录起点,如果设置了客户端的BASE配置参数,该项可不用。

如果按以上配置文件设置了acl,用上面的查询命令是查询不到受保护的内容的。如上面的userPassword and mail。要查询到这些受限内容,需要通过验证才可以:

# ldapsearch -x -LLL -h it.com -b 'dc=it,dc=com' -D 'uid=qq,dc=it,dc=com' -W 'uid=qq'
接着提示输入密码。输入userPassword的密码回车,所有信息就都出来了。

2.2.2. 文件方式

.ldif文件方式也就是把以上手工输入的内容先写入一个.ldif文件中,然后,用ldapadd命令的-f参数导入。

# ldapadd -x -D "cn=root,dc=it,dc=com" -W -f test.ldif

一个完整的global.ldif文件例子:

dn: dc=info, dc=net
objectClass: top
objectClass: organization
o: info.net

dn: ou=People, dc=info, dc=net
objectClass: top
objectClass: organizationalUnit
ou: People
description: User Info

dn: cn=Admin, dc=info, dc=net
objectClass: top
objectClass: person
objectClass: organizationalPerson
cn: Admin
sn: Admin
userPassword: Admin
description: Administrator for info.net

dn: id=1, ou=People, dc=info, dc=net
objectclass: top
objectclass: InfoPerson
id: 1
username: 张三
tel:021-63138990
card_id:ABC001

我们也可用slapadd命令来导入数据。该命令可以导入包含一些系统信息的ldif文件,如:

dn: dc=it,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
dc: it
structuralObjectClass: organization
entryUUID: d97b06da-d77e-1028-9866-d4ec7ac00d12
creatorsName: cn=anonymous #系统信息
createTimestamp: 20041201005115Z #系统信息
o:: 5bm/5bee5biC6JmO5aS055S15rGg6ZuG5Zui5pyJ6ZmQ5YWs5Y+4
userPassword:: e01ENX14TXBDT0tDNUk0SU56RkNhYjNXRW13PT0=
entryCSN: 2004120603:50:08Z#0x0001#0#0000 #系统信息
modifiersName: cn=admin,dc=it,dc=com #系统信息
modifyTimestamp: 20041206035008Z #系统信息
[Note]
再次提醒,注意每行后面不要留有空格。

2.2.3. 脚本方式

脚本录入方式需要自已编写脚本,或到网上下载。有一个用PHP写的LDAP管理工具不错,叫phpLDAPadmin。可以到以下网址下载:http://phpldapadmin.sourceforge.net。安装方法也很简单,只要解压出来,拷贝到apache的web目录下,按说明配置一下设定文档,就ok了。

2.3. 常用命令介绍

接着为大家介绍一下几个常用的ldap命令,如果你用了phpLDAPadmin程序,其实它已经有一个很好的图形介面帮你完成这些命令了。但了解一下还是对你还是很有益的,因为命令方法才是最根本的。

  • 删除命令ldapdelete

    # ldapdelete -x -D 'cn=root,dc=it,dc=com' -W 'uid=qq1,dc=it,dc=com'
  • 重新索引ldap数据库命令slapindex

    # slapindex -f slapd.conf
  • 设置使用者密码,当然了,你的用户需要有userPassword项了。

    #ldappasswd -x -D "cn=root,dc=it,dc=com" -W "uid=qq1,dc=it,dc=com" -S 
    New password:
    Re-enter new password:
    Enter bind password:
    Result: Success (0)
    [Note]
    "Enter bind password" 是 "cn=root,dc=it,dc=com"管理员的密码。
  • 管理员密码更改

    #slappasswd 
    New password
    Re-enter new password
    {SSHA}83DJ4KVwqlk1uh9k2uDb8+NT1U4RgkEs

    接下再拷贝到 path/to/sldap.conf 的 rootpw 即可,重启使用配置文件生效

  • 通过ldapmodify修改目录内容

    # ldapmodify -x -D "cn=root,dc=it,dc=com" -W -f modify.ldif

    通过ldif文件修改ldap数据,ldif文件格式如下:

    dn: cn=qq,dc=it,dc=com
    changetype: modify
    replace: mail
    mail: modme@example.com
    -
    add: title
    title: Grand Poobah
    -
    add: jpegPhoto
    jpegPhoto:< file:///tmp/modme.jpeg
    -
    delete: description
    -

2.4. 启用sasl验证

前提是你在系统中安装了sasl认证库,并在编译openldap时支持它,默认就支持了。到http://asg.web.cmu.edu/cyrus下载。安装方法见我写的sendmail安装笔记。安装好之后,需要在sasl中建立相应的帐号,用以下命令可完成。

# saslpasswd2 -c test

接着配置slapd.conf文件,加入以下内容。

sasl-regexp
uid=(.*),cn=.*,cn=auth
uid=$1,dc=it,dc=com

重启服务器使配置文件生效。这个配置是最大权限的配置,如果要细化请查阅相关文档。用以下命令测试。

# ldapsearch -U qq  -b 'uid=qq,dc=it,dc=com' -D 'dc=it,dc=com' -Y DIGEST-MD5

采用digest-md5验证,提示密码,输入saslpasswd2的密码。

2.5. 配置服务器复制

在 一些关键的应用场合,我们需设置多个ldap服务器实例,且数据要保持同步。当一台服务器出现故障或被黑客攻击时,我们就能继续保持应用的正常运行。通过 DNS的轮流查询功能,还能实现服务器的负载均衡,提高响应速度。在openldap中有一个slurpd进程,利用slurpd进程可帮助我们实现多台 ldap服务器数据的同步功能。下面简单介绍一下主、从ldap服务器的配置。

slurpd运行在主服务器上,它能把主服务器上的变化通过 LDAP协议传送到从服务器上。从服务器上的变化不能传送到主服务器上,也就是说是单向同步的。主从服务器的版本最好一样,以减少兼容性问题。主从服务器 的安装方法是一样的,关键是配置文件有所不同。我的操作系统是debian sarge,在确保主从服务器能正常运行的前提下进行以下配置:

  • 首先,把主从服务器关闭。通过以下三步操作静态同步主从服务器上的数据:

    1. 把主服务器上/var/lib/ldap目录下的所有数据库文件全部拷贝到从服务器的同目录中,覆盖原有文件。

    2. 把主服务器上的/etc/ldap/schema目录下的所有schema文件拷贝到从服务器的同目录中,覆盖原有文件。

    3. 把主服务器上/etc/ldap/slapd.conf文件拷贝到从服务器的同目录中,覆盖原有文件。

  • 配置主服务器上的slapd.conf文件,取消replogfile指令前的注释符号,取消后的结果如下:

    # Where to store the replica logs for database #1
    replogfile /var/lib/ldap/replog

    增加replica指令,如:

    #replace config
    replica uri=ldap://192.168.6.195:389 #指定从服务器主机名和端口号
    binddn="cn=admin,dc=com" #指定需同步的DN的管理员
    bindmethod=simple credentials=1 #指定验证方式和需同步的DN的管理员密码
  • 配置从服务器上的slapd.conf文件,增加updatedn指令,如:

    updatedn "cn=admin,dc=com"          #与主服务器的binddn对应

    在从服务器的配置文件中,不要包含replica和replogfile指令。

  • 先启动主服务器的slapd和slurpd,再启动从服务器的slapd。

配置完成后,我们可测试一下,在主服务器上修改一个目录项,在从服务器上可查看目录项的数据已同步。

Chapter 3. 管理工具

开源的目录服务管理工具有很多,包括phpldapadmin,gq,CPU,JXplore等。这些工具可帮助我们方便维护目录服务器上的数据。这些工具各有优缺点,下面简要介绍一下,详细的内容可参考相关的官方网站。

3.1. phpldapadmin

3.2. gq

3.3. CPU

3.4. JXplore

3.5. LAM

官方网站:http://lam.sourceforge.net/index.htm

Chapter 4. HowTo

4.1. 禁止整个服务器的匿名访问

在slapd.conf配置文件中加入disallow bind_anon即可。


posted @ 2006-08-10 09:33 Alex 阅读(1513) | 评论 (0)编辑 收藏

key words : openldap ldap


2006 年 6 月 26 日

使用轻量级目录访问协议(LDAP)构建集中的身份验证系统可以减少管理成 本,增强安全性,避免数据复制的问题,并提高数据的一致性。随着 Linux® 的不断成熟,已经出现了很多工具用来简化用户帐号信息到 LDAP 目录的迁移。还开发了一些工具用来在客户机和目录服务器之间启用加密通信配置,并通过复制提供容错性。本文将向您展示如何配置服务器和客户机在 Red Hat Linux 上使用 OpenLDAP。

简介

Linux 发行版中提供的 OpenLDAP 软件按照一个客户机/服务器模型实现了轻量级目录访问协议(LDAP)。LDAP 的设计目的是提供一种有效的方法来查找和管理信息。OpenLDAP 软件和包提供了创建目录信息树(一个主要进行读操作的数据库)的工具。本文向您展示如何存储用户的帐号信息,并修改身份验证服务来使用 LDAP 获取所需要的信息。内部细节并不重要,因为这些工具可以将数据库的内容以文本格式(LDAP 数据交换格式,LDIF)呈现在您的面前。

LDAP 信息被组织成属性和值的组合,称为 条目(entry)。条目可能会具有必须的属性或可选属性。一个条目的属性必须要遵循 /etc/openldap/schema/ 模式文件中定义的规则。规则包含在条目的 objectclass 属性中。看一下下面的关系,我们可以看出 posixAccount objectclass 中包含了密码文件条目的信息(posixAccount userPassword 是文件条目的 base64 编码)。


图 1. LDAP 目录条目和 Linux 密码文件之间的关系
LDAP 目录条目和 Linux 密码文件之间的关系

文件 /etc/openldap/schema/nis.schema 为 posixAccount 对象类中的条目定义了所有的属性和 objectclass。例如,下面是对 uidNumber 属性的描述:

attributetype ( 1.3.6.1.1.1.1.0 NAME 'uidNumber'
DESC 'An integer uniquely identifying a user in an administrative domain'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )

所有的属性类型都已经定义了,它们被收集到 posixAccount objectclass 中。例如:

objectclass ( 1.3.6.1.1.1.2.0 NAME 'posixAccount' SUP top AUXILIARY
DESC 'Abstraction of an account with POSIX attributes'
MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory )
MAY ( userPassword $ loginShell $ gecos $ description ) )

ldapuser 条目具有一个识别名属性 dn,它用作用户名,并与 userPassword 一起用来在 LDAP 目录中记录信息,或与 LDAP 目录绑定在一起使用。

LDAP 为作为容器使用的特殊条目提供了将这些条目组织成树结构的功能。在这个例子中,我们将使用一个容器 People 保存用户帐号信息,使用另外一个容器 Groups 保存组帐号信息。所生成的目录信息树如图 2 所示。


图 2. 用户帐号信息使用的目录信息树
用户帐号信息使用的目录信息树

让我们来看一下如何配置 OpenLDAP 服务器,如何将信息从系统文件迁移到 LDAP 目录中,如何配置 OpenLDAP 客户机通过 LDAP 对用户进行身份验证。在使用一个集中的身份验证数据库时,应该通过使用复制技术采用第二个 LDAP 服务器提供高可用性,这样在主服务器出现问题时,就可以使用第二个 LDAP 服务器响应客户机的请求。由于诸如密码之类的身份验证数据会通过网络进行传输,因此希望使用 TSL 协议建立加密通信连接。

我们的 OpenLDAP 服务器和客户机都是虚拟机,上面运行的是 Red Hat Enterprise Linux AS release 4(Nahant Update 1)。在我们的例子中使用了 表 1 所列出的系统。如果想模仿这些例子,请使用适合您自己的设置。


表 1. 系统网络信息
角色主机名IP 地址
OpenLDAP 主服务器dhcp64-233.ibm.com9.47.64.233
OpenLDAP 从服务器dhcp64-253.ibm.com9.47.64.253
OpenLDAP 客户机dhcp64-251.ibm.com9.47.64.251





回页首


配置 LDAP 服务器

我们使用 Red Hat Enterprise Linux release 4 Update 1 上的包来构建服务器:

  • openldap-2.2.13-2:包含 OpenLDAP 配置文件、库和文档
  • openldap-servers-2.2.13-2:包含 slapd 和 slurpd 服务器、迁移脚本和相关文件
  • openldap-clients-2.2.13-2:包含客户机程序,用来访问和修改 OpenLDAP 目录

OpenLDAP 包在服务器上安装了很多程序:

  • 守护进程:
    • slapd:主 LDAP 服务器
    • slurpd:负责与复制 LDAP 服务器保持同步的服务器
  • 对网络上的目录进行操作的客户机程序。下面这两个程序是一对儿:
    • ldapadd:打开一个到 LDAP 服务器的连接,绑定、修改或增加条目
    • ldapsearch:打开一个到 LDAP 服务器的连接,绑定并使用指定的参数进行搜索
  • 对本地系统上的数据库进行操作的几个程序:
    • slapadd:将以 LDAP 目录交换格式(LDIF)指定的条目添加到 LDAP 数据库中
    • slapcat:打开 LDAP 数据库,并将对应的条目输出为 LDIF 格式

OpenLDAP 的主要服务器配置文件是 /etc/openldap/slapd.conf。本例所使用的完整 slapd.conf 文件如 清单 18 所示。slapd.conf 文件中包括一系列全局配置选项,它们作为一个整体应用到 slapd 上面,后面是包含数据库特有信息的数据库后端定义。如果一行内容是以空格开始的,就认为它是上一行的延续。空行和以 “#” 字符开头的注释行都会被忽略。

如果您正把本文当作练习来做,那就可以按照下面指定的方式进行修改,从而启动 LDAP 服务器。一旦确认服务器正常工作之后,就可以添加复制功能,然后再添加安全性支持。首先是全局配置信息段的设置。其中每个选项的值都是我们想要的。

正如上面介绍的一样,信息被组织成属性和值的组合,称为条目。条目属性必须遵循的规则是使用 objectclass 专用属性进行组织的,这可以在 /etc/openldap/schema/ 模式文件中找到。对于身份验证来说,需要使用在 nis.schema 中定义的 posixAccountshadowAccount objectclasses:

include /etc/openldap/schema/nis.schema

loglevel 行设置的是日志选项。可以将其设置为这样的级别:调试语句和操作统计信息都会被记录到 /var/log/slapd.log 中。日志级别是累加的:296 = 256 日志连接/操作/结果 + 32 搜索过滤器处理 + 8 连接管理:

loglevel 296

日志信息会被记录到 syslogd LOG_LOCAL4 机制中。还需要将下面的内容添加到 /etc/syslog.conf 中,并让 syslogd 重新读取自己的配置文件:

local4.debug /var/log/slapd.log

access 行定义了谁可以访问目录中的内容。我们希望用户可以修改自己的密码,并更新自己的 shadow 信息来反映密码的变化。希望身份验证程序能够检索用户的密码。还希望用户能够读取所有其他条目。注意密码条目是不可读的,shadow 属性的惟一用处就是管理密码的过期问题。

access to attrs=shadowLastChange,userPassword
by self write
by * auth

access to *
by * read

接下来,在 database 部分,要定义下面的内容。

使用新的 bdb 后端数据库:

database bdb

指定后端数据库需要响应的查询的 DN 前缀。为了确保惟一性,根前缀应该从自己的网络域名构建出来。在本例的情况中,它是 .dc=svc,dc=beaverton,dc=ibm,dc=com.,但是在下面的例子中我们对其进行了简化:

suffix "dc=ibm,dc=com"

指定管理 DN,它不用于访问控制或限制数据库的操作。也不需要在目录中为这个 DN 指定一个条目。为具有 rootpw 密码的管理员使用 DN 可以跳过 ACL 规则中的所有访问控制:

rootdn "cn=Manager,dc=ibm,dc=com"
rootpw {MD5}ijFYNcSNctBYg

这就是我们现在想要设置的选项。稍后将返回 slapd.conf 文件来配置复制,然后在配置安全性。

现在,我们希望将数据添加到目录中,并确认可以访问这些信息。要实现这种功能,需要配置服务器来使用 ldap 客户机工具,例如 ldapadd 和 ldapsearch。ldap 客户机工具的配置文件是 /etc/openldap/ldap.conf。我们使用的这个文件的完整列表如本文末尾的 清单 19 所示。要在 ldap 服务器上运行这些工具,只需要将该行修改成下面的内容:

BASE dc=ibm,dc=com

设置启动脚本在级别 2、3 和 5 时启动 LDAP:


清单 1. 设置启动运行级别
# chkconfig --levels 235 ldap on

从命令行中启动服务:


清单 2. 启动服务
# service ldap start
Starting slapd: [ OK ]

OpenLDAP 守护进程 slapd 应该已经运行了:


清单 3. 检查服务正在运行
# ps -ef | grep slap
ldap 13521 1 0 Oct24 ? 00:00:00 /usr/sbin/slapd -u ldap -h ldap:/// ldaps:///

ldapsearch -x 命令应该可以成功完成,但不会返回任何数据。





回页首


迁移密码和 shadow 信息

Red Hat 所提供的 openldap-servers 包包含 PADL Software Pty Ltd. 公司的 MigrationTools 工具。我们将使用这些工具将数据从 Linux 系统文件(例如 /etc/group 和 /etc/password)转换成 LDAP LDIF 格式,这是数据库信息的一种文本格式的表示。这种格式是行界定、冒号分隔的属性-值对。

有一组 Perl 脚本被安装到 /usr/share/openldap/migration/ 中执行迁移。这些 Perl 脚本的配置信息包含在 migrate_common.ph 文件的开头。对于我们的目的来说,只需要修改命名前缀的变量来使用条目的识别名就足够了,如下所示:

$DEFAULT_BASE = "dc=ibm,dc=com"

在进行这些修改之后,请运行脚本 migrate_base.pl,它会创建根项,并为 Hosts、Networks、Group 和 People 等创建低一级的组织单元:


清单 4. 运行 migrate_base.pl
# migrate_base.pl > base.ldif

编辑 base.ldif,删除除下面之外的所有条目:


清单 5. base.ldif 条目
# cat base.ldif
dn: dc=ibm,dc=com
dc: ibm
objectClass: top
objectClass: domain

dn: ou=People,dc=ibm,dc=com
ou: People
objectClass: top
objectClass: organizationalUnit

dn: ou=Group,dc=ibm,dc=com
ou: Group
objectClass: top
objectClass: organizationalUnit

在 LDAP 服务器上,使用 OpenLDAP 客户机工具 ldapadd 将以下条目插入到数据库中。简单身份验证必须要使用 -x 选项指定。在 slapd.conf 中定义的 rootdn 身份验证识别名是 “cn=Manager,dc=ibm,dc=com”。对于简单身份验证来说,必须使用密码。选项 -W 强制提示输入密码。这个密码就是在 slapd.conf 文件中指定的 rootpw 参数的值。包含这些条目的 LDIF 文件是使用 -f 选项指定的:


清单 6. 使用 ldapadd 插入条目
# ldapadd -x -D "cn=Manager,dc=ibm,dc=com" -W -f base.ldif

接下来,从 /etc/group 中迁移 ldapuser 组:


清单 7. 迁移 ldapuser 组
# grep ldapuser /etc/group > group.in
# ./migrate_group.pl group.in > group.ldif

# cat group.ldif
dn: cn=ldapuser,ou=Group,dc=ibm,dc=com
objectClass: posixGroup
objectClass: top
cn: ldapuser
userPassword: {crypt}x
gidNumber: 500

# ldapadd -x -D "cn=Manager,dc=ibm,dc=com" -W -f group.ldif

最后,从 /etc/passwd 和 /etc/shadow 中迁移 ldapuser 的信息:


清单 8. 迁移 ldapuser 信息
# grep ldapuser /etc/passwd > passwd.in
# ./migrate_passwd.pl passwd.in > passwd.ldif

# cat passwd.ldif
dn: uid=ldapuser,ou=People,dc=ibm,dc=com
uid: ldapuser
cn: ldapuser
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
userPassword: {crypt$1$TeOlOcMc$cpQaa0WpLSFRC1HIHW5bt1
shadowLastChange: 13048
shadowMax: 99999
shadowWarning: 7
loginShell: /bin/bash
uidNumber: 500
gidNumber: 500
homeDirectory: /home/ldapuser
gecos: ldapuser

# ldapadd -x -D "cn=Manager,dc=ibm,dc=com" -W -f passwd.ldif

现在检查已经添加到数据库中的信息。清单 9 给出了全部输出结果:


清单 9. 以 LDIF 格式填充的 OpenLDAP 数据库
# ldapsearch -x

# extended LDIF
#
# LDAPv3
# base <> with scope sub
# filter: (objectclass=*)
# requesting: ALL
#

# ibm.com
dn: dc=ibm,dc=com
dc: ibm
objectClass: top
objectClass: domain

# People, ibm.com
dn: ou=People,dc=ibm,dc=com
ou: People
objectClass: top
objectClass: organizationalUnit

# Group, ibm.com
dn: ou=Group,dc=ibm,dc=com
ou: Group
objectClass: top
objectClass: organizationalUnit

# ldapuser, Group, ibm.com
dn: cn=ldapuser,ou=Group,dc=ibm,dc=com
objectClass: posixGroup
objectClass: top
cn: ldapuser
gidNumber: 500

# ldapuser, People, ibm.com
dn: uid=ldapuser,ou=People,dc=ibm,dc=com
uid: ldapuser
cn: ldapuser
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
shadowMax: 99999
shadowWarning: 7
loginShell: /bin/bash
uidNumber: 500
gidNumber: 500
homeDirectory: /home/ldapuser
gecos: test2

# search result
search: 2
result: 0 Success

# numResponses: 6
# numEntries: 5





回页首


配置 LDAP 客户机

用来设置客户机的 Red Hat Enterprise Linux release 4 Update 1 包包括:

  • nss_ldap-226-6:包括两个 LDAP 访问客户机:nss_ldap 和 pam_ldap
    • nss_ldap 是一组 C 库扩展,它允许 LDAP 目录服务器用作一个用户和组信息的主源
    • pam_ldap 是一个 Linux-PAM 模块,它支持身份验证功能

LDAP 身份验证要想正确地工作,需要配置两个服务:系统命名服务和身份验证服务。

系统命名服务(NSS)需要配置为使用 LDAP 来解析诸如用户和组帐号之类的资源。例如,在运行命令 ls -l 时,如果某个文件 inode 给出文件的所有者是 “user 501”,那么命名服务就需要将 “uid 501” 解析成用户名,并在 ls 命令输出结果中输出。通常来说,这是通过查找 /etc/passwd 文件中的所有用户帐号实现的。由于用户现在都存储在 LDAP 目录中,因此系统需要配置成同时对 passwd 文件和 LDAP 目录中的帐号进行解析。这种功能是通过 /usr/lib/libnss_ldap.so 库提供的。

身份验证服务是实际向 LDAP 验证用户身份的服务。可插入身份验证模块(PAM)提供了本地 Linux 身份验证服务。下面我们将配置 PAM 先对本地的 /etc/passwd 文件检查用户帐号,然后再对 LDAP 服务器进行检查。PAM LDAP 模块可以用来将身份验证重定向到 LDAP 目录上。/lib/security/pam_ldap.so PAM 模块提供了 LDAP 身份验证功能。

身份验证本身是由 PAM 程序执行的,它从身份验证候选机制中获取用户名,将其绑定到 OpenLDAP 服务器上,检索与这个 uid 条目(用户名条目)相关的 DN;从身份验证候选机制中获取密码,然后使用这个 DN 和密码试图将其绑定到 OpenLDAP 服务器上。如果绑定成功,PAM 会报告说这个用户已经成功通过了 pam_ldap.so 提供的身份验证测试。根据 PAM 的配置不同,在用户看到命令行提示符之前可能会执行其他测试。

我们可以采用两种方法来配置 LDAP 客户机。一种快速而简单的方法是运行 /usr/sbin/authconfig,并在两个屏幕中输入信息。另外一种方法是通过编辑客户机 LDAP 配置文件 /etc/ldap.conf,然后修改 /etc/nsswitch.conf、/etc/sysconfig/authconfig 和 /etc/pam.d/system-auth。首先让我们来看一下如何运行 authconfig。

如图 3 所示进行选择,然后点击 Next


图 3. 执行 authconfig 命令的第一个页面
执行 authconfig 命令的第一个页面

在如图 4 所示的第二个屏幕中输入对应的信息,然后点击 OK


图 4. 执行 authconfig 命令的第二个页面
执行 authconfig 命令的第二个页面

要手工配置 OpenLDAP 客户机,请遵循下面的步骤。

用来跟踪特定身份验证机制是否已经启用的文件是 /etc/sysconfig/。我们可以希望以下条目的值都是 “yes”:

USELDAP=yes
USELDAPAUTH=yes
USEMD5=yes
USESHADOW=yes
USELOCAUTHORIZE=yes

PAM 和 NSS 模块使用的基本配置文件是 /etc/ldap.conf。host 选项指定 LDAP 服务器,base 选项指定这个目录使用的 DN,最初我们希望关闭加密功能:

host dhcp64-233.ibm.com
base dc=ibm,dc=com
ssl off

要让 NSS 服务使用 OpenLDAP 服务器,需要将 “ldap” 添加到 /etc/nsswitch.conf 文件的 passwd、shadow 和 group 行中,如下所示:

passwd: files ldap
shadow: files ldap
group: files ldap

要让 PAM 身份验证服务使用 OpenLDAP 服务器,请将 pam_ldap 行加入到 /etc/pam.d/system-auth 中,位置在对应的标准 pam_unix.so 条目之后。尽管其他设置也可以实现相同的结果,但是我使用下面的文件设置:

auth required /lib/security/$ISA/pam_env.so
auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok
auth sufficient /lib/security/$ISA/pam_ldap.so use_first_pass
auth required /lib/security/$ISA/pam_deny.so

account required /lib/security/$ISA/pam_unix.so broken_shadow
account sufficient /lib/security/$ISA/pam_localuser.so
account sufficient /lib/security/$ISA/pam_succeed_if.so uid %lt; 100 quiet
account [default=bad success=ok user_unknown=ignore] /lib/security/$ISA/pam_ldap.so
account required /lib/security/$ISA/pam_permit.so

password requisite /lib/security/$ISA/pam_cracklib.so retry=3
password sufficient /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow
password sufficient /lib/security/$ISA/pam_ldap.so use_authtok
password required /lib/security/$ISA/pam_deny.so

session required /lib/security/$ISA/pam_limits.so
session required /lib/security/$ISA/pam_unix.so
session optional /lib/security/$ISA/pam_ldap.so

现在,用户帐号信息可以从客户机系统中删除并从 LDAP 目录中进行获取了。当用户试图登录客户机系统时,PAM 身份验证服务就会从用户那里获取用户名,在我们的例子中是 ldapuser。PAM 会从 LDAP 服务器中检索识别名(DN)条目 .dn: uid=ldapuser, ou=People, dc=ibm, dc=com.。PAM 然后会从用户那里获取密码。然后 PAM 试图使用这个 DN 和密码与 LDAP 服务器进行绑定。DN 和密码都以正文文本的格式发送给 LDAP 服务器。在对密码进行散列操作之后,如果服务器可以让用户登录,就会向 PAM 报告说已经成功进行了绑定。成功绑定可以完全满足 PAM 对 pam_ldap 模块汇报成功的标准,如果所有其他 PAM 标准都已经满足了,那么就允许用户登录到系统中。

当 LDAP 服务器对身份验证进行处理时,需要解决另外两个问题才能满足提供可靠安全的身份验证的目标。现在,任何客户机系统不能成功地与 LDAP 服务器进行通信都会阻止用户登录客户机系统。在下一节中我们将看到如何消除这种单点故障,这将显示客户机如何从备份服务器上访问 LDAP 目录。由于用户密码是在网络上以正文文本格式传输的,因此这并不能满足安全身份验证的需求。配置 TLS 安全性 将解决这个问题。





回页首


配置复制

为了防止出现客户机由于 LDAP 服务器的问题而不能登录的情况,我们需要采用复制技术来实现可靠性目标。复制是通过 OpenLDAP 复制进程 slurpd 提供的,它会周期性地唤醒,并检查主服务器上的日志文件,从而确定是否有任何更新。这些更新然后会传播到从服务器上。读请求可以由任何一个服务器进行解 析,而更新请求则只能由主服务器进行解析。客户机需要负责在推荐地址上重试更新操作。

要配置复制,需要停止 OpenLDAP 服务器的 slapd 守护进程:


清单 10. 停止服务
# service ldap stop

将以下内容添加到服务器的 /etc/openldap/slapd.conf 文件中,从而启用对新从服务器的复制。replogfile 行的内容指定类 LDIF 变化应该写入的文件。replica 原语定义了变化应该传播到的主机:

#Replicas of this database
replogfile /var/lib/ldap/replog
replica host=dhcp64-253.ibm.com:389
binddn="cn=Manager,dc=ibm,dc=com"
credentials=secret
bindmethod=simple

在运行从 OpenLDAP 服务器的系统上,请遵循 配置 LDAP 服务器 一节给出的步骤。然后通过将信息导出到一个 ldif 文件中并将其添加到从服务器数据库上,从而将数据库从主服务器拷贝到复制服务器上。

在主服务器上:


清单 11. 将数据导出到 LDIF 文件中
# ldapsearch -x > database.ldif

在复制服务器上:


清单 12. 将数据添加到从服务器数据库中
# ldapadd -x -D "cn=Manager,dc=ibm,dc=com" -W -f database.ldif

将以下内容添加到复制服务器的 /etc/openldap/slapd.conf 文件中。updatedn 指定了在更新从目录时主 slurpd 守护进程使用的 DN。updateref 指定的是主目录服务器。当一个 LDAP 客户机请求从服务器进行更新时,从服务器就将客户机重定向到这个主服务器上。

updatedn "cn=Manager,dc=ibm,dc=com"
updateref ldap://dhcp64-233.ibm.com:389/

启动复制 OpenLDAP 服务器,当它运行之后,再启动主 OpenLDAP 服务器。在主服务器上,slapd 和 slurpd 都会启动。

现在,可以让 OpenLDAP 客户机除了主服务器之外还可以使用复制服务器,这可以通过运行 authconfig 并将复制主机名添加到第二个屏幕中的 Server 行中实现,也可以通过在 /etc/ldap.conf 中修改 host 实现:

host dhcp64-253.ibm.com dhcp64-233.ibm.com

为了确认复制可以正常工作,需要研究一下在更新 gecos 属性时到底发生了什么。复制日志使用了与 LDIF 类似的格式。在读取 replogfile 之后,slurpd 会将这个条目拷贝到自己的重做日志中。实际的变化都以 LDIF 格式保存在主 LDAP 服务器上 /var/lib/ldap/replica/ 中的 slurpd.replog 文件中。

使用文件 user_mod 中的变化,客户机程序 ldapmodify 应用这些变化:


清单 13. 应用 user_mod 的变化
# cat user_mod
dn: uid=ldapuser,ou=People,dc=ibm,dc=com
changetype: modify
replace: gecos
gecos: test2

# tail -f /var/lib/ldap/replog &

# ldapmodify -x -r -f /home/ldapuser/user_mod -D'cn=Manager,dc=ibm,dc=com' -W
Enter LDAP Password:
modifying entry "uid=ldapuser,ou=People,dc=ibm,dc=com"

replica: dhcp64-253.ibm.com:389
time: 1130111686
dn: uid=ldapuser,ou=People,dc=ibm,dc=com
changetype: modify
replace: gecos
gecos: test2
-
replace: entryCSN
entryCSN: 20051023235446Z#000001#00#000000
-
replace: modifiersName
modifiersName: cn=Manager,dc=ibm,dc=com
-
replace: modifyTimestamp
modifyTimestamp: 20051023235446Z
-





回页首


配置 TLS 安全性

LDAP 是以明文的格式通过网络来发送所有信息的,包括密码。我们将采用 TLS 所提供的加密机制(SSL 的后继者)来解决这个问题。在传输层,数据使用 TLS 协议进行加密和封装,然后通过网络进行传输。用来配置加密的工具都是由 OpenSSL 包提供的。

虽然加密是一个复杂的主题,但是要使用 OpenSSL 包,我们依然需要简要介绍一下 TLS 是如何工作的。数据块使用一个对称密钥算法进行加密,它使用一个密钥来实现对数据的加密和解密。我们还有一个问题:如何防止出现以正文文本格式将密钥从 LDAP 服务器发送到 LDAP 客户机上的情况。我们使用公钥算法来解决这个问题,其中客户机可以使用一个自由获取的公钥对自己的密钥进行加密,而只有服务器才可以对这个密钥进行解密。

公钥是作为证书的一部分来创建和分发的,其中包含了一些支持信息,例如 ID、过期日期、提供这个证书的 LDAP 服务器的完整域名(FQDN)。在 LDAP 客户机使用证书进行加密之前,它会验证自己正在与之进行交谈的服务器拥有这个证书,这是通过加密一个挑战并验证服务器可以对其进行解密实现的。

要验证发行这个证书的服务器是一个已经批准过的 LDAP 服务器,客户机被配置为只接受本地证书机构(CA)所签署的证书。它使用 CA 所生成的证书中的公钥,这个公钥保存到客户机中以验证这个 LDAP 所产生的证书是有效的。

在这个例子中,我们将自己的 LDAP 服务器设置为证书机构,并创建一个自签署的证书供 LDAP 客户机和服务器在加密信息中使用。

用来构建 TLS 服务器的 Red Hat Enterprise Linux release 4 Update 1 包是:

  • openssl-0.9.7a-43.1:包括一个证书管理工具和提供各种加密算法和协议的共享库

要构建证书机构的工作环境并生成自己的自签署证书,需要运行 /usr/share/ssl/misc/CA shell 脚本,这是一个对 openssl 命令的封装程序。私密性增强邮件(PEM)是一种用来对数据进行加密和编码的格式:


清单 14. 运行 CA shell 脚本
# cd /usr/share/ssl/misc
# ./CA -newca
CA certificate filename (or enter to create)

Making CA certificate ...
Generating a 1024 bit RSA private key
.........++++++
......++++++
writing new private key to './demoCA/private/./cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated into
your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:US
State or Province Name (full name) [Berkshire]:Oregon
Locality Name (eg, city) [Newbury]:Beaverton
Organization Name (eg, company) [My Company Ltd]:IBM
Organizational Unit Name (eg, section) []:its
Common Name (eg, your name or your server's hostname) []:dhcp64-233.ibm.com
Email Address []:root@dhcp64-233.ibm.com

接下来,要生成由证书机构进行签署的服务器证书。其余的步骤只会对主 LDAP 服务器执行一次,此时指定的是 CN=dhcp64-233.ibm.com;然后对从服务器执行一次,此时指定的是 CN=dhcp64-253.ibm.com。还要使用 nodes 选项,这样就不用在每次启动 OpenLDAP 服务器守护进程 slapd 时都需要输入密码了。签署后的公钥被嵌入到证书请求 slapd-req.pem 中,与之匹配的私钥嵌入在 slapd-key.pem 中:


清单 15. 生成服务器证书
# openssl req -new -nodes -subj
'/CN=dhcp64-233.ibm.com/O=IBM/C=US/ST=Oregon/L=Beaverton'
-keyout slapd-key.pem -out slapd-req.pem -days 365
Generating a 1024 bit RSA private key
...............++++++
.....................................++++++
writing new private key to 'slapd-key.pem'
-----

使用在第一个步骤中创建的 CA 证书对这个证书进行签署:


清单 16. 对证书进行签署
# openssl ca -out slapd-cert.pem -infiles slapd-req.pem
Using configuration from /usr/share/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Oct 25 02:50:05 2005 GMT
Not After : Oct 25 02:50:05 2006 GMT
Subject:
countryName = US
stateOrProvinceName = Oregon
organizationName = IBM
commonName = dhcp64-233.ibm.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
11:A2:FB:59:42:A4:B3:26:73:1D:6D:F5:4D:2F:80:F0:FA:10:38:F5
X509v3 Authority Key Identifier:
keyid:F7:6A:25:F5:76:BE:20:E7:8D:0F:51:EF:D8:86:7B:AF:2C:74:2F:80
DirName:/C=US/ST=Oregon/L=Beaverton/O=IBM/OU=its/CN=dhcp64-233.ibm.com
/emailAddress=root@dhcp64-233.ibm.com
serial:00

Certificate is to be certified until Oct 25 02:50:05 2006 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

下一个步骤将所有需要的证书拷贝到 slapd 可以找到的地方。另外,还要对每个文件强制采用正确的权限:


清单 17. 拷贝证书并强制设置权限
# cp -p slapd-key.pem /etc/openldap/slapdkey.pem
# cp -p slapd-cert.pem /etc/openldap/slapdcert.pem
# chown ldap:ldap /etc/openldap/slapdcert.pem
# chmod 644 /etc/openldap/slapdcert.pem
# chown ldap:ldap /etc/openldap/slapdkey.pem
# chmod 400 /etc/openldap/slapdkey.pem

# mkdir /etc/openldap/cacerts/
# cp /usr/share/ssl/misc/demoCA/cacert.pem /etc/openldap/cacerts/cacert.pem
# chown ldap:ldap /etc/openldap/cacerts cacert.pem
# chmod 644 /etc/openldap/cacerts cacert.pem

在 OpenLDAP 服务器上,将以下内容添加到 /etc/openldap/slapd.conf 文件的 global 段下面。TLSCertificateFileTLSCertificateKeyFile 指定了证书文件和私钥文件的路径。TLSCipherSuite 指定了一个 OpenSSL 密码的列表,slapd 在与 TLS 协商建立连接时可以从中按照降序顺序依次选择。HIGH 的意思是 “所有密钥的长度都大于 128 位”;MEDIUM 表示 “所有密钥的长度都等于 128 位”;+SSLv2 表示 “不管密钥强度如何,所有密码都是以 SSL 协议版本 2 的形式指定的”。

TLSCipherSuite HIGH:MEDIUM:+SSLv2
TLSCACertificateFile /etc/openldap/cacerts/cacert.pem
TLSCertificateFile /etc/openldap/slapdcert.pem
TLSCertificateKeyFile /etc/openldap/slapdkey.pem

将以下内容添加到 LDAP 服务器的第二个配置文件 /etc/openldap/ldap.conf 中:

TLS_CACERTDIR /etc/openldap/cacerts
TLS_REQCERT allow

为了允许从 OpenLDAP 客户机上使用安全连接,需要将以下内容添加到 /etc/openldap/ldap.conf 文件中:

ssl start_tls
tls_checkpeer yes
tls_cacertfile /etc/openldap/cacerts/cacert.pem





回页首


结束语

按照本文给出的提示,我们现在已经使用轻量级目录访问协议(LDAP)构建了一个集中的身份验证系统。我们最初是通过配置 LDAP 服务器来响应对 “dc=ibm,dc=com” 的基本请求开始入手的。我们使用了一组 Perl 脚本来将用户帐号信息迁移到 LDAP 目录中。我们对 Linux 用户帐号服务、PAM 和 NSS 服务进行了修改,从而可以从 LDAP 服务器中检索用户信息。还设置了一个 LDAP 服务器副本作为备用服务器来响应客户机的请求。然后,使用 TLS 协议在 LDAP 客户机和服务器之间对通信进行安全加密。恭喜!

为了参考方便,下面给出了本文中使用的配置文件的完整清单。


清单 18. 本文例子中使用的服务器 /etc/openldap/slapd.conf 文件
#
# See slapd.conf (5) for details on configuration options.
#
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/inetorgperson.schema
include /etc/openldap/schema/nis.schema

loglevel 256
pidfile /var/run/slapd.pid
argsfile /var/run/slapd.args

# The next three lines allow use of TLS for encrypting connections.
TLSCipherSuite HIGH:MEDIUM:+SSLv2
TLSCACertificateFile /etc/openldap/cacerts/cacert.pem
TLSCertificateFile /etc/openldap/slapdcert.pem
TLSCertificateKeyFile /etc/openldap/slapdkey.pem

# access control policy:
# Restrict password access to change by owner and authentication.
# Allow read access by everyone to all other attributes.

access to attrs=shadowLastChange,userPassword
by self write
by * auth

access to *
by * read

#######################################################################
# database definition
#######################################################################

database bdb
suffix "dc=ibm,dc=com"

rootdn "cn=Manager,dc=ibm,dc=com"
rootpw {MD5}ijFYNcSNctBYg

directory /var/lib/ldap

# Indices to maintain for this database
index objectClass eq,pres
index ou,cn,mail,surname,givenname eq,pres,sub
index uidNumber,gidNumber,loginShell eq,pres
index uid,memberUid eq,pres,sub
index nisMapName,nisMapEntry eq,pres,sub

#Replicas of this database
replica host=dhcp64-253.ibm.com:389
binddn="cn=Manager,dc=ibm,dc=com"
credentials=secret
bindmethod=simple
replogfile /var/lib/ldap/replog


清单 19. 本文例子中使用的服务器 /etc/openldap/ldap.conf 文件
#
# LDAP Defaults
#

# See ldap.conf(5) for details

HOST 127.0.0.1
BASE dc=ibm,dc=com

TLS_CACERTDIR /etc/openldap/cacerts
TLS_REQCERT allow


清单 20. 本文例子中使用的客户机 /etc/ldap.conf 文件
a
# @(#)$Id: ldap.conf,v 1.34 2004/09/16 23:32:02 lukeh Exp $
#
# This is the configuration file for the LDAP nameservice
# switch library and the LDAP PAM module.
#
# PADL Software
# http://www.padl.com
#

# Your LDAP server.
# Multiple hosts may be specified, each separated by a
# space.

host dhcp64-233.ibm.com dhcp64-233.ibm.com

# The distinguished name of the search base.

base dc=ibm,dc=com

# OpenLDAP SSL mechanism, start_tls mechanism uses the normal LDAP port 389
ssl start_tls

#Require and verify server certificate
tls_checkpeer yes

# CA certificates for server certificate verification
tls_cacertfile /etc/openldap/cacerts/cacert.pem

pam_password md5





回页首


参考资料

学习

获得产品和技术
  • 索取免费的 SEK for Linux,这有两张 DVD,包括最新的 IBM for Linux 的试用版软件,包括 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere®。

  • 在您的下一个开发项目中采用 IBM 试用版软件,这可以从 developerWorks 上直接下载。


讨论




回页首


关于作者

Mike O'Reilly

Mike O'Reilly 是 IBM Linux 和 VMware ESX 产品支持小组的一员,他为 Linux 产品提供支持已经有 5 年的时间了。另外,他支持 VMware 超


posted @ 2006-08-10 09:19 Alex 阅读(858) | 评论 (0)编辑 收藏

仅列出标题
共15页: First 上一页 6 7 8 9 10 11 12 13 14 下一页 Last