寸心知

来源: BlogBus 原始链接: http://www.blogbus.com:80/blogbus/blog/archive.php?id=3182 存档链接: https://web.archive.org/web/20040904171037id_/http://www.blogbus.com:80/blogbus/blog/archive.php?id=3182


寸心知 2004/03/01 到 2004/03/31 文章千古事,得失寸心知 Groovy: a test case

2004-03-31 15:59 Groovy已经被JCP's expert group投票通过了,正式成为 JSR241 .我的电子表单中需要template engine,因此我特意写了一个testcase来测试Groovy中具备的特性.(代码比较乱,没有特意简化). 下面是GroovyTest.java的源码: import java.io.File; import java.util.List; import junit.framework.TestCase; import groovy.lang.Binding; import groovy.lang.Closure; import groovy.lang.GroovyShell; import groovy.lang.GroovyClassLoader; import groovy.lang.GroovyObject; import groovy.text.Template; import groovy.text.SimpleTemplateEngine; import org.codehaus.groovy.syntax.SyntaxException; public class GroovyTest extends TestCase { public void testSimpleTemplate() throws Exception { String text = "Dear ${firstname} ${lastname}"; Binding binding = new Binding(); binding.setVariable("firstname", "Sam"); binding.setVariable("lastname","Pullara"); SimpleTemplateEngine engine = new SimpleTemplateEngine(); Template template = engine.createTemplate(text); template.setBinding(binding.getVariables()); assertEquals("Dear Sam Pullara", template.toString()); } public void testShell() throws Exception { // call groovy expressions from Java code Binding binding = new Binding(); binding.setVariable("foo", new Integer(2)); GroovyShell shell = new GroovyShell(binding); Object value = shell.evaluate("println 'Hello World!'; x = 123; return foo * 10"); assertTrue(value.equals(new Integer(20))); assertTrue(binding.getVariable("x").equals(new Integer(123))); } public void testGroovyBean() throws Exception { ClassLoader parent = getClass().getClassLoader(); GroovyClassLoader loader = new GroovyClassLoader(parent); Class groovyClass = loader.parseClass(new File("src/test/com/dfsoft/snippet/HelloWorld.groovy")); // lets call some method on an instance GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance(); Object[] args = {}; assertEquals("Hello world!", groovyObject.invokeMethod("sayHello", args)); } public void testClosure() throws Exception { ClassLoader parent = getClass().getClassLoader(); GroovyClassLoader loader = new GroovyClassLoader(parent); Class groovyClass = loader.parseClass(new File("src/test/com/dfsoft/snippet/HelloWorld.groovy")); // lets call some method on an instance GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance(); Object[] args = {}; assertEquals(new Integer(2), new Integer(groovyObject.invokeMethod("sayClosure", args).toString())); } public void testFile() throws Exception { ClassLoader parent = getClass().getClassLoader(); GroovyClassLoader loader = new GroovyClassLoader(parent); Class groovyClass = loader.parseClass(new File("src/test/com/dfsoft/snippet/HelloWorld.groovy")); // lets call some method on an instance GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance(); Object[] args = {"src/conf/app.properties"}; assertEquals(2, ((List)groovyObject.invokeMethod("readLine", args)).size()); } public void testHtml() throws Exception { ClassLoader parent = getClass().getClassLoader(); GroovyClassLoader loader = new GroovyClassLoader(parent); Class groovyClass = loader.parseClass(new File("src/test/com/dfsoft/snippet/HelloWorld.groovy")); // lets call some method on an instance GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance(); Object[] args = {}; assertTrue(((Boolean)groovyObject.invokeMethod("printHtml", args)).booleanValue()); } } 下面是HelloWorld.groovy的源码: import java.io.File import groovy.xml.MarkupBuilder class HelloWorld { // properties Integer id String name Date dob String sayHello() { // println("Hello world!") return "Hello world!" } Integer sayClosure() { closure = { bill, tipPercentage | bill * tipPercentage / 100 } println(closure(20, 10)) closure.call(20, 10) } List readLine(String path) { file = new File(path) file.eachLine { println it } lineList = file.readLines() } boolean printHtml() { mb = new MarkupBuilder() mb.html() { head() { title("This is my title.") } body() { p("This is my paragraph.") } } println mb true } } Post by befresh @ 15:59 TDD by example

2004-03-30 10:47 XP编程创始人Kent Beck的又一力作,在书中它详细描绘了怎样用TDD来逐步开发的例子,并且还介绍了TDD与模式和重构之间的关系. 比如我吧,一直妄想尝试使用TDD方法来编程,心中始终认为先测试,再编程是高手的显著标志之一.虽然自己在开发中基本按照面向对象的方法来考虑,但是,苦于没有方法来领我入门. Kent Beck就想让我们通过它的实例来领悟TDD的实质,虽然书中只有一个例子,但是它表达的是一种方法,一种思想,一种勇气.如果,看完书之后,你只是认为这只是一本教程,那你完全浪费了Kent的良苦用心了. 既然是一种开发方法,那么它就会具备相应的实践步骤: 1)编写测试 2)所有测试运行不通过 3)小小的修改 4)所有测试运行通过 5)重构代码,消除重复设计,优化设计结构 以上五个步骤,非常简单,灵活,大概这就是所谓大道至简吧.甚至,咱们还可以把它总结成以下三个阶段: 不可运行/可运行/重构 . Kent还认为TDD编程的最终目标是产生整洁可用的代码( clean code that works ),甚合吾意. Post by befresh @ 10:47 动态表单(六): Groovy

2004-03-29 21:46 动态表单中无论如何也会使用到script language,选择什么templage engine来解释处理表单模板呢? 看到Tirsen blog上介绍Groovy,我就想到是否可以在电子表单中应用此项技术.难度可能不会小,但是潜力会很不错. 下面是Groovy的介绍: Groovy is a new agile dynamic language for the JVM combining lots of great features from languages like Python, Ruby and Smalltalk and making them available to the Java developers using a Java-like syntax. Groovy is designed to help you get things done on the Java platform in a quicker, more concise and fun way - bringing the power of Python and Ruby inside the Java platform. Groovy can be used as an alternative compiler to javac to generate standard Java bytecode to be used by any Java project or it can be used dynamically as an alternative language such as for scripting Java objects, templating or writing unit test cases. Groovy正在加入sun jcp,如果它能成为一种标准,那前途就能更加看好了. Post by befresh @ 21:46 项目管理工具: Maven

2004-03-22 16:32 使用Maven来管理项目的想法由来已久,可是一直没逮到机会.对于一般的项目而言,使用Ant已经足够了.看到Tirsen'blog中说使用Maven和ant构建非常庞大的系统,效果很好.不行,再不用,就真的没机会了. 在Maven中有几个重要的概念需要了解: project object model (POM) Maven is based on the concept of a project object model (POM) in that all the artifacts produced by Maven are a result of consulting a well defined model for your project.Builds, documentation, source metrics, source cross-references and anything else that may be provided by a Maven plug-in are all controlled by your POM. POM可以修改,并且还可以继承. Plug-ins Maven is in essence a small core that works with a satellite of plug-ins. All functionality provided by Maven is done so in the form of plug-ins. Goals A goal is a werkz tag similar in nature to an Ant target ; it's a named container for a set of tags to be executed. Maven是用Jelly作为自己的脚本语言,因此在编写自己的Goal时,需要了解一些Jelly的基本知识. 在Maven中,还有一些配置文件,如:project.xml,maven.xml,project.properties等.project.xml是项目的主配置文件,没有该文件Maven是不能执行的.文件中包含的属性,元素可以参考它的xsd文件. 一般在make java app时,都会应用很多其它的jar文件,在Maven中它提供了Repository,在这里它存有很多的jar文件.当然,在Repository中也存有Maven执行的一些类库文件. 如果,你第一次运行Maven时,它会从网上的Repository下载需要的类库.如果此时,网络是断的,就不行了. 运行Maven的site:generate,可以生成一个关于项目信息和项目报告的网站,所有的页面都是html格式的.其中,包含非常丰富的项目信息:项目组成员,邮件列表,单元测试,javadoc等等.这样,就可以让人能大致把握住项目的概括. 试试吧,你会喜欢它的! Post by befresh @ 16:32 An open project: PowerFolder

2004-03-18 16:28 今天看到了一个非常强大的 Web方式程序编辑器,叫作PowerFolder(简称pf).使用它可以在Browser中编写Web程序,并且它不只是能写1+1=2那么简单的程序,还可以在程序中加入比较复杂的商业逻辑.我一开始是仅仅把它作为工作流系统来了解的,逐渐深入研究以后,发现它不但包括了工作流,还包括了页面编辑器. 不过,在这儿我只介绍它的工作流,这部分是它的核心.你先可以去 http://www.powerfolder.org 下载它的源码和 samples,它的sample下载完以后可以直接运行,实在是非常的方便. 先来介绍它的工作原理,在pf中,工作流引擎是通过EJB中的MessageDrivenBean来实现的.既然是MDB,那么它一定是采用app server的JMS协议来实现消息传递.它是通过XML来定义流程模板和其他的一些定义数据,它没有依照XPDL来定义流程模板.它也有自己的O/R Mapping框架.给我的第一感觉是它非常象Ofbiz. 它的源码都包含在org.powerfolder.workflow 包中,在这个包里面你可以按照MVC模式来理解其代码分布,其中model包就代表M,web包就代表V,而其它一些包可以代表C. 在model包中包含了attribute,trigger,history,还有一大批的tag.根据这些名称我们就大致可以了解它的作用.刚开始,我一直在想,为什么有这么多的tag,并且tag分类也很复杂.不过,运行了它的sample以后,我感觉这些tag就是为了实现商业逻辑的.其它的包不要太多的介绍,看看基本上会明白. 下面再介绍一下它的workflow template,在模板中我们可以定义attributes和nodes,其中node它只分为三类:start,state和stop.在state nodes中,可以加入很多的节点,每个节点中又可以定义wait,action,If Transitions和Branch.If Transitions中可以定义条件,系统中包含了多种分类条件,如:Trigger,logical和programmatic等.在上述的分类条件中,会包含很多的条件,如:XOR,OR,Equal等. 说得不是太详细,有兴趣得朋友可以访问它的网站. Post by befresh @ 16:28 Aop资源

2004-03-17 16:24 一、相关网站: 1、aosd.net [ http://aosd.net/ ] The home of aspect-oriented software development 2、AspectJ [ http://eclipse.org/aspectj/ ] Mature and powerful AOP implementation that uses extensions to the Java language 3、Random Thoughts [ http://jroller.com/page/rickard ] Blog of Rickard Öberg, an AOP innovator 4、crazybob.org [ http://crazybob.org/ ] Blog of Bob Lee, the creator of dynaop 5、AOP Alliance [ http://aopalliance.sourceforge.net/ ] A joint open-source project between several software engineering people who are interested in AOP and Java 6、XEROX [ http://www.parc.xerox.com/csl/groups/sda ] The goal of the Software Design Area at Xerox PARC is simple and long-standing: to make it possible to cleanly capture complex design structures in software implementations. 7、bluefish[ http://www.bluefish.se/aop/ ] Välkommen till Bluefishs informationssida om Aspektorienterad systemutveckling (Aspect Oriented Programming, AOP) 二、相关项目: 1、Nanning( http://nanning.codehaus.org/ ) Nanning Aspects is a simple yet scaleable aspect-oriented framework for Java. 2、Dynaop( https://dynaop.dev.java.net/ ) dynaop, a proxy-based Aspect-Oriented Programming (AOP) framework, enhances Object-Oriented (OO) design in the following areas: code reuse decomposition dependency reduction 3、AspectWerkz( http://aspectwerkz.codehaus.org/ ) AspectWerkz utilizes runtime bytecode modification to weave your classes at runtime. It hooks in and weaves classes loaded by any class loader except the bootstrap class loader. It has a rich join point model. Aspects, advices and introductions are written in plain Java and your target classes can be regular POJOs. You have the possibility to add, remove and re-structure advices as well as swapping the implementation of your introductions at runtime. Your aspects can be defined using either an XML definition file or using Runtime Attributes. 4、Spring( http://www.springframework.org/ ) AOP functionality, fully integrated into Spring configuration management. You can AOP-enable any object managed by Spring, adding aspects such as declarative transaction management. With Spring, you can have declarative transaction management without EJB... even without JTA, if you're using a single database in Tomcat or another web container without JTA support. 5、JBossAOP( http://www.jboss.org/developers/projects/jboss/aop ) JBoss 4.0 brings Aspect-Oriented technology to Java through a pure 100% Java interface. Base on the new JBoss.org project Javassist , JBoss-AOP allows you to apply interceptor technology and patterns to plain Java classes and Dynamic Proxies. 6、AspectJ( http://eclipse.org/aspectj/ ) A seamless aspect-oriented extension to the Java tm programming language Post by befresh @ 16:24 动态表单(五)

2004-03-16 16:22 会签 虽然我一直在强调表单应该与流程结合起来考虑,但是仍然忘了在动态表单中考虑一些表单元素(表单域)多人操作的问题。涉及到表单与流程流转中的某些关联问题并没有考虑周全。一般,这种情况是由于流程中的会签活动(activity)引起的,多个人同时需要对某些表单域进行操作,那么前端视图应该如何显示这些表单域呢? 要完善的解决这个问题比较困难,先把问题提出来: 1、是增加一种会签(多人操作)控件,还是在控件中指定会签属性? 2、流程中如果有会签,视图应该如何显示,即会签的显示规则如何? 下面我就试着来回答这两个问题: 1、如果是增加一种会签控件,那么它的表现形式是什么呢?是输入框、下拉框还是其他形式呢?因为在很多表单中,涉及到多人操作控件的表现形式是不雷同的,有的是签名,那就需要是一个输入框;有的是选择“是”或“否”,那就需要一个下拉框;如果是填写意见,那就需要一个多行文本框。因此,仅仅增加一种会签控件是解决不了问题的。 那么,控件中指定会签属性又如何呢?试想,当有会签活动时,正在指定各个控件的操作权限,我们可以增加一种属性:“需会签”。当生成视图时,ViewGenerator就知道该控件是有多人操作的,这就可以根据显示规则来显示控件。因此,采取该方法是能够定义会签活动语义的。 2、语义能够定义出来,那显示该如何呢?这就需要显示的规则了。如果一个会签活动有10个人来参与,那就会生成10个会签任务,按照简单原则,就需要在视图中生成10指定需会签的控件,页面美观就会被破坏殆尽了,而且,当涉及到表单“暂存”、“回退”等动作时,页面中控件权限的控制就非常的麻烦。 那如何来制定显示规则呢?我想各个表单工具可以采用不同的显示规则,关键是如何让页面保持美观,不至于引起页面混乱。我这里提供一种简单的方法:无论是否会签,视图中只显示一个“需会签”控件。当然,别的参与者会签过的数据可以显示,但是不能修改。 当然,会签数据应该如何保存呢?我觉得应该采用从表的方式,这样就能相应的增加了动态表单的灵活性和扩展性。 Post by befresh @ 16:22 Nanning

2004-03-19 17:27 刚开始我还以为这是中国人的作品呢?原来只是作者Jon Tirsen来中国广西南宁旅游,后来非常喜欢这个城市,就以"南宁"来命名了,真是让我们汗颜呀. Nanning( http://nanning.codehaus.org )是一个Java AOP framework,它是以dynamic proxies的interceptor方式来实现Aop的. 下面介绍一些它的概念: Proxies The main object in the Core of Nanning is the AspectInstance. The AspectInstance is used to create a dynamic proxy: AspectInstance instance = new AspectInstance(); Object proxy = instance.getProxy(); Mixins An AspectInstance and the proxy it produces contains and does nothing by default. In order to add some kind of behaviour and state to an AspectInstance a Mixin is added to it. A mixin consists of an interface and a target-object which usually implements the interface. Methods invoked on the proxy is invoked on the target. AspectInstance instance = new AspectInstance(); // add a mixin with a Intf as interface and an instance of Impl as target instance.addMixin(new Mixin(Intf.class, new Impl())); Intf intf = (Intf) instance.getProxy(); // target object is invoked intf.call(); Interceptors Interceptors in Nanning are around-advices, that means the interceptor is called directly when the method is called, the interceptor is itself responsible for propagating the call to the actual method (or next interceptor if several interceptors are applied to the same method). An interceptor is applied like this: AspectInstance instance = new AspectInstance(); Mixin mixin = new Mixin(Intf.class, new Impl()); Method callMethod = Intf.class.getMethod("call", null); mixin.addInterceptor(callMethod, new MethodInterceptor() { public Object invoke(Invocation invocation) throws Throwable { System.out.println(invocation.getMethod() + " was called!"); // invokes next interceptor or actual method return invocation.invokeNext(); } }); instance.addMixin(mixin); Intf intf = (Intf) instance.getProxy(); intf.call(); assertTrue(called); Interceptors can also be added to a whole mixin or a whole aspect instance: // interceptor will be invoked for all method calls on mixin mixin.addInterceptor(interceptor); // interceptor will be invoked for all method calls on proxy instance.addInterceptor(interceptor); Dynamic Proxy Post by befresh @ 17:27 动态表单(四):page

2004-03-11 17:06 现在可以详细说说表单定义文件的具体格式,既然我们把表单定义文件定义成XML文件格式。XML大家都已经非常熟悉了,我根据Tapestry,照猫画虎把该定义文件命名为*.page。 首先我们需要在Page中定义element,初步估计,XML中需要包含以下Element: 1、 page-specification 定义Page文件的根元素,可以在其中加入一个Attribute: class :指定该Page的处理Java类,系统实现一个Base类,有特殊要求可以继承并扩展。 2、 component 定义Page文件中的控件,可以定义以下几个Attribute: id :控件的ID type :控件类型 3、asset 定义表单的一些资源:图片、CSS等,可以定义以下几个Attribute: ame :名称 path :路径 4、 node 定义流程节点与控件的关联,这还需要充分展开 其实,节点与控件的关联是非常复杂的,要充分考虑节点的操作方式,也就是所谓的流程的Pattern,如:AND , OR ,XOR等.节点的状态也会与控件有关系.这就留给有志于开发动态表单的各位朋友了. Post by befresh @ 17:06 动态表单(三)

2004-03-10 15:09 难点呈现出来以后,也就到了消灭它的时候,我一直认为解决问题的能力是衡量自我水平的杠杆。以上三个问题主要都集中在两者映射上,而解决映射的方法之一就是使用定义文件,通过定义文件来反映两者之间的关系。当然,定义文件的好坏,很大程度上决定了动态表单工具的好坏。 用定义文件(XML格式)来描述关系,我认为主要有以下两点好处: 1、XML现在非常成熟,是数据格式定义的标准。因此,我们根本不用担心跨平台、表达能力欠缺等问题。而且,它的表义能力非常强,任何人都可以看的明白。 2、降低工作量,正因为第一点,现在有很多的XML文件处理工具,操作XML文件非常的方便。而且,XML是一个文本文件,对其修改也是非常方便,这就提供了很好的扩展性。 当然,你也可以用数据库来表示这种关系,但是基于以上的原因,我更推荐使用XML来描述关系。 在动态表单中,有四种主体对象: 1、Form 2、Component 3、View 4、DataSource 从根本上说每一类对象都可以通过定义文件来描述自己,现在就有许多工具可以从XML转化到JAVA对象。我们先理清上面对象之间的关系,其实,从框图和名词的含义就可以搞清它们之间的关系。 现在我们正在Form Designer中设计Form,首先,我们会画出表单的版式(表格),版式决定了整体形状和控件位置;然后往Form的表格中加入所需的Components,当然是很多的Components了;Component是有数据和行为组成的,而数据就是从DataSource中获取/存储的;这时候,就需要和流程来绑定了,对于每个节点Component的行为是不一样的,也就是说每个节点的操作权限是不同的。用户在处理这个表单时,其实她看到的只是这个Form的View,也就是Form经过处理(包括很多的处理过程)后显示给用户的一个界面。 通过上面的例子,我们很容易理解他们之间的关系。我们也可以知道Form对象是这四个对象的核心,由它来联系其他的对象。因此,我们应该把重点放在Form的定义文件上来。 当然,Component也是重点,但是对其定义是有困难的。第一,在Web程序中,一个Component一般会包含数据、表现和行为三方面的元素,因为,把这三方面分开是很困难的;第二,一般的动态表单不会包含很复杂的Component,主要是一些TextField,Link,Select(包括SelectBox和一些日期、人员和部门等选择叶面)和Radio等,因此,对这种控件的定义也没有太大的意义。正是基于此,我们暂缓对Componet的定义。 重新回到Form上来,Tapestry框架给了我们很好的启示。Tapestry框架是一个基于Web Component的开发框架,它就提供了很好的组件式层次结构。不熟悉Tapestry的朋友可以去Apache网站看看。 让我借鉴Tapestry来构造动态表单的框架,主要是考虑到他们之间的一些相似之处: 1、都是基于Web Component的开发方式,有很好的层次结构,把表现、行为和数据比较清晰的分开,提高了控件的重用性。 2、Tapestry的模板是采用插入式标签,如。它不会破坏页面的结构,可以让页面设计人员更好的使用Dreamweave、FrontPage等工具。而动态表单,我也想让它能多次导入/导出通过工具来修改。 当然,我们也不能照搬照抄,完全采用Tapestry,因为,他们之间也有很大不同: 1、面向的用户不一样。Tapestry面向的是开发人员,而动态表单面向的是普通用户,至多也就是系统管理员。 2、Tapestry是一个大的Web开发框架,而动态表单只是一个设计工具,应用面要狭窄的多。 归根结底,我们只能借鉴它的一些思想,然后,在动态表单中应用起来。啊,越扯越远,还是回到Form的定义上来(其实,我们需要参考Tapestry's page definition)。 Post by befresh @ 15:09 动态表单(二)

2004-03-09 17:04 国内做好动态表单工具(B/S)的企业基本上没有,很可能是由于: 客观原因:base on browser的开发难度很大,而且有些还受browser的限制,当然表单本身的工作也非常具有挑战性。 主观原因:没有哪家公司会投那么多资源去开发这个工具,很多公司完全是基于项目而构建,甚至有很多公司完全在卖概念。 按昨天提供的结构来说动态表单开发中主要难点,主要有以下几处: 1、 表单控件的定义 表单是通过版式来定义主体结构(表格),通过表单控件来与用户进行交互,控件是表单的核心元素。 2、 控件与数据源绑定 表单是通过控件来显示和提交数据,一般来说表单中的数据都是需要持久化的,而数据源就是我们定义的持久化接口。绑定的难点在于:一是使用该工具的用户群是普通用户,不是开发人员,这样展示给用户的该项功能不能很复杂;二是控件与数据源关联是松散的,除非在指定的设计器(IDE)中进行,任何一方面的改动都不会触动另一方面的变化。 说到第二点,一般表单都是html格式的,都可以导出通过专业网页工具来进行多次设计,如果表单在这个过程中增加/删除控件,数据源当然是没有任何反映的。这就需要我们加入控件与数据源绑定的验证器,通过这样的策略来避免错误。 3、 表单视图 表单一定会是与流程结合起来应用,流程中各个节点对于控件的操作权限是不一样的,也就是说每一个流程节点都会有不同的表单视图。当前的表单一般只提供三种权限:不显示、只读、可写,每个节点对表单控件的绑定权限就只有这三种。表单视图的难点就在于与流程节点的绑定。 下面是我画的表单定义的示意图,可以参考。 Post by befresh @ 17:04 动态表单

2004-03-08 09:34 动态表单对于一个以企业应用为主的产品来说,基本上是一个必不可少的模块,如果没有动态表单定制功能,很多与流程有关的工作是很难实现的。记得有位老板说:表单 + 流程 = ERP,虽然这话说的有点过,但在这两者结合后要占整个企业应用业务的80%以上。 经过我的总结,动态表单的整体架构见下图: 版式 版式表格可以定义表单中放置文本、图像和控件的单元尺寸和顺序 控件集 控件是显示在表单上的图形对象,也就是允许用户控制程序的图形用户界面对象,如文本框、复选框、滚动条或命令按钮等。使用控件可以显示数据或选项、执行操作或使用户界面更易阅读。输入到控件中的信息将存储在表单的数据源中。在设计表单时,你可以自定义控件的外观,包括字体、颜色、对齐方式、默认值、数据类型以及其它属性 数据源 将控件绑定到表单的数据源,否则输入表单的数据将无法保存 视图 自定义表单视图, 可以修改表单的背景色、版式宽度,也可以修改控件的字体、字号和文字颜色等属性,也可以改变表单的打印方向并添加页眉、页脚等内容 表单库 存储表单模板,可以导入 / 导出到文件系统,也可以发布给用户使用 一般来说,动态表单应该具备以下8大功能: 1、导入 2、导出 3、定义(表单设计) 4、验证 5、报表 6、统计 7、查询 8、打印 当然,除了表单本身的功能以外,它必须与工作流结合起来应用,才能把它的作用发挥到极致。 Post by befresh @ 09:34 OA系列(二):发展历程

2004-03-05 11:38 虽然国内的OA产商非常之多,但并没有多少公司去详细研究OA本身的一些特性。比如:它是什么时候出现的、什么时候成熟的、它又是怎样出现的呢等问题。我从网上找了很久,没有发现答案,只看到一些XXOA的十大优势、XXOA的理念等。 OA在国内的发展历程可以追溯到90年代初期,从M$的Windows95出现后,一大批国内用户开始使用PC机,通过PC上的各种工具软件来辅助办公,可以说这个时候出现了OA的雏形。 下面让我们进入OA的生命历程(仅指国内): 1、字处理阶段(初级阶段) 在Win95进入国内以后,Office工具包首先派上了用处。纯文字、表格处理、存储、查询等是大多数企业用户的首选。打印机的发展促进了纸张信息数字化,用户可以通过计算机来完成自己的工作。 大约96-98年期间,最早是根据政府上网这个词,从福建省长提出数字福建以及北京辽宁等省市提出“数字XX”等,开始有了政府网站的静态页面,在这个时期(主要是98年前后),计算机档次和价格都相对稳定,国家开始对政府投入这笔钱,政府大规模上网,那时企业很少有花OA钱的,都是些单机操作,做些报表,可以说进入了OA的初级阶段。 2、MIS阶段 随着计算机硬件、软件的飞速发展,用户对工具软件的日益精熟。MIS系统的需求开始出现了,主要是为了应付对数字信息的采集汇总、共享、管理。二/三层结构开始出现,C/S结构的系统逐渐成为主流。 Lotus的Notes在这个时候被引进到国内,可以说是Lotus引导了中国人进入OA的新概念,把OA进行了功能上极大的扩容,Notes的群件功能是特别为此设计的。此时政府机关、事业单位是OA的主要用户。 3、协同办公阶段 互联网让世界越来越小,用户对信息的需求量却越来越多。用户对MIS业务的熟悉、互联网的推动,对信息全方位、多角度共享及协同要求,基于智能、门户、管理及业务一体化整合,可以说这是现阶段OA的主要理念。 B/S结果开始成为OA系统的主流,Lotus Notes仍然有市场,M$ exchange吹响了冲锋号,J2EE架构有燎原之势。 当前我们正处于第三阶段,那么OA的下一阶段会在什么时候出现呢,这一阶段的主要内容又如何呢?我们不妨做以下预测: 4、智能整合阶段 虽然现在整合已经在进行,但是还远远没有达到用户的要求,更不用说无缝整合。这个阶段应该是各种系统以网状方式逐渐融合,最终OA的概念逐渐淡化,很有可能成为其他业务系统的入口。 Post by befresh @ 11:38 OA系列(一):概念

2004-03-04 18:09 OA即办公自动化,是英文Office Automation的首字母缩写,究竟什么是办公自动化呢?为了了解办公自动化系统,必须首先了解“办公”。 “办公”即Office在这里应该代表日常办公,日常办公是主要针对企事业单位的(当然政府也可以,但是应该叫政务了),也就是说在上班期间员工经常会做的工作,基本上是各个行业中共有的那部分工作(管理活动)。譬如:考勤、报销和会议等。 日常办公主要包括以下4部分工作,无论它是何种形式出现: 1、沟通(Communication) 沟通是工作的基础。无论你是以电话、会议和聊天等形式进行,都是在沟通。没有沟通,不要说工作,生存都难。 2、协作(Collaboration) 协作是工作的前提。没有人能把所有的事情都干完,没有其他人的配合、参与,很多工作都没法完成。尤其对于日常办公,更可以说大部分都是需要由多人参与完成。 3、管理(Manage) 管理是工作的重要部分。管理工作是企业的重点工作,难点工作。 4、共享(Share) 工作资料、成果,是需要储存并共享的。 了解了什么叫办公,那办公自动化就很好理解了。自动化,顾名思义就是办公的信息化,也就是说把日常工作转化成利用计算机来辅助完成。 用计算机来实现以上的4种工作,很可能与原来的工作形式发生的变化,有的完全不同,有增有减,这就需要办公人员的思维进行转变。 Post by befresh @ 18:09 XDoclet & Hibernate初体验

2004-03-03 15:20 利用java sourcecode直接生成hbm映射文件对我的诱惑不是一天两天了,始终觉得这才是朝自动化编码迈出了一大步。但是,如果只是单个文件的generate,不会显著的提高编程效率,只有ant + XDoclet两相配合,才会发挥出令人惊讶的优势。 先来一段XDoclet的说明: XDoclet是一个扩展的Javadoc Doclet引擎。它是一种通用的java工具,可以让你创建自己的javadoc @tags进而利用XDoclet中的Templet enging基于这些@tags生成源代码或其他文件(例如xml的deployment descriptors)。XDoclet已经支持一些常见的任务了,例如生成web.xml和ejb-jar.xml等,用户可以创建其他templets和@tags,以增加对其他技术的支持。 总是听说使用XDoclet比较简单,按照samples就可以搞定。刚好有一个项目,我就先来体验一下。因为是在Eclipse中开发,所以我使用的是MyEclipse插件,在该插件中,本身就有XDoclet集成,如果不太清楚,可以参考它的帮助。 为了偷懒,我先使用MyEclipse来build project,可以无论我如何配置,总是报taskdef没有找到的错误,试了很长的时间,一直搞不定。不能碰到难题就躲呀,我首先怀疑build.xml有问题,但是参考了很多的sample and reference,都没有找到问题所在。既然此路不通,那就干脆直接使用ant来build。 谢天谢地,最后总算搞定,这其中也遇到了几个问题: 1、 最好使用jdk1.4.1及以上版本。 我最开始使用的是jdk1.3,可以在import hbm to database时始终报SAX exception,其实就是让你指定sax parser,可以我发现classpath中已经有了xerces,可是这样还不可以。后来,看到可以通过ant -D来指定sax.driver,但是也是徒劳,并没有起作用。最好,没办法只能是升级jdk,使用jdk1.4.1,一切都没有问题。 2、 在java sourcecode中必须在声明相应的tag。 例如,我使用hibernate module,见源码: /**

  • @hibernate.class

*/ public class Test{ } 如果不这样做,就不能生成doc。这也费了我一些时间,追根结底是没有看各种template tag具体要求。 Post by befresh @ 15:20 单表的父子关系

2004-03-02 18:36 今天,在整理组织结构模型时,忽然遇到一个问题,在我的组织结构中有一个Group对象,见源码: public long getGroupId(); public void setGroupId(long groupId); public long getParentId(); public void setParentId(long parentId); public Group[] getChildGroups(); 把Group映视到数据库group table,该表主键是groupId,然后其中还包含parentId,也就是说group表是有父子(包含)关系的,那在hbm中应该如何定义呢?。 突然碰到这个问题,我就急着去找one2many relationship,可是在hibernate中表示one2many都是两个表之间的,单表之间的父子关系应该如何表示呢? 看了hibernate reference后并没有找到答案,我陷入了深思之中,但是始终找不到解决方法。 快到下班时,突然想到,竟令我恍然大悟,原来单表的父子关系根本不需要在hbm中进行定义,因为根本用不着保证它们之间的关系。当然,为了保证parentId的正确性,可以加上与groupId有关的index。 Post by befresh @ 18:36 妄想工作流

2004-03-01 17:03 对于我这个规划师来说,规划一个工作流产品,简直就跟设计国家大剧院那么简单,不信,往下看: 规划一个工作流产品,可不是搭积木那么简单,至少也不比建国家大剧院的工程量少。国家大剧院不就挖个大洞,搞个小型拦水坝,上面再铺层玻璃,当然灯光要搞好,这差不多就Ok了。 而我的工作流产品就不一样了,首先它的外围产品就应该有“可视化建模工具”、“动态表单定义工具”、“组织结构定义工具”、“监控工具”和“外部应用设计工具”,当然这些怎么也得是图形化的,最好是插件方式,即插即用嘛。 外围产品有了,那核心产品就得好上加好,没有“引擎”,那就不叫工作流产品了,超级引擎是必不可少。至于引擎中的各个部分:任务管理器、时间管理器、路由管理和消息管理器等那就是紧密团结在核心周围。 至于用什么技术来搞,简单,一句话:现在是“OO”时代,从OOA,OOD,OOP,然后在加上流行的AOP。按照这些技术出来的东东,怎么也是走在时代的前列,在国际同类产品中取得领先地位。 至于主体架构嘛,也是走流行路线: 以 xml 来配置各个功能接口 以 services 方式来提供引擎的各种功能 以 container 方式来处理、管理请求 以 component 方式来集成各种功能 本着不重复生产轮子的原则,可以借用如下开源产品: Hibernate,Log4J,commons,spring等 哎,妄想症是越来越严重了! Post by befresh @ 17:03