Flyingis

Talking and thinking freely !
Flying in the world of GIS !
随笔 - 156, 文章 - 16, 评论 - 589, 引用 - 0
数据加载中……

地理空间数据处理与模型

作者: Flyingis

Michael F G 说过:“地理信息系统真正的功能在于它利用空间分析技术对空间数据的分析”,而不仅仅是停留在数据库型的 GIS 层面上,需要将关注点从数据库创建和系统开发建设,逐步转移到关注空间分析和空间建模,挖掘对科学决策具有指导意义的信息,解决复杂多变的地学应用问题,例如空间分析、预测预报、决策支持等。

地理空间数据处理与建模的重要技术方法一般涉及到数量地理学、 GIS 、地理计算、数据挖掘等知识领域。地理空间数据分析是地理学和地理信息科学的重要研究内容,它通过研究地理空间数据及其相应分析理论、方法和技术,探索、证明地理要素之间的关系,揭示地理特征和过程的内在规律和机理,实现对地理空间信息的认知、解释、预测、调控。

1.  数量地理学

数量化方法在感知、认识和解释现实世界的各种自然、人文、社会现象过程的相互关系中起着定性方法不能替代的作用。不论是学术研究中,还是实际决策中,不论是理工科学中,还是人文管理中,数量化的方法总是更让人觉得合理可信,通过表格化、图形化的形式表达出来,作为结论论断的有力支持,通常也可以说是定量化的分析方法。数量地理学是地理学领域中最先采用数学原理方法来探讨地理数据分析处理与建模的学科,主要涉及的分析模拟方法是地理系统分析、随机数学方法和地理系统数学模拟。

2.  地理信息系统

地理信息是一门学科,是描述、存储、分析和输出空间信息的理论和方法的一门新兴的交叉学科;另一方面,地理信息系统是一个技术系统,是以地理空间数据库为基础,采用地理模型分析方法,适时提供多种空间和动态的地理信息,为地理研究和地理决策服务的计算机技术系统 ( 经典定义 ) 。一般,我们利用 GIS 来反应客观显示世界抽象化的数字模型,对地理空间数据进行管理、显示与制图,最重要的是,可以用来对数据进行模拟分析,实现可视化和对现实世界的虚拟,提供决策的依据或直接进行决策分析。

3.  地理计算

地理计算本质上可认为是对地理学时间与空间问题所进行的基于计算机的定量化分析,它是一系列的程序或算法的应用过程和结果,不同的算法例如神经网络、模糊逻辑、遗传算法等产生的结果也会不同,一般可以通过和以往成果的对比,来论证自己算法更为优秀更为符合实际,或根本就是一个失败的计算过程。

其中涉及到的理论知识主要有 GIS 建库,人工智能技术和智能计算技术 ( 人工神经网络模型、模糊逻辑模型、遗传算法模型、元胞自动机模型、分形理论等等 ) ,高性能计算服务系统。通过这些知识体系建立一种动态模型,来反应地理空间的动态特性,强调作为地理空间基本部分的动态组成。

 

参考文献:

地理信息系统——原理、方法和应用

GIS 空间分析原理与方法

posted @ 2006-04-03 15:53 Flyingis 阅读(1833) | 评论 (2)编辑 收藏

[Java Puzzlers]表达式随想

    作者:Flyingis

    前段时间到书店抱了几本书回来,虽说网上有很多电子版的资料,但有时候觉得一些比较经典、自己比较喜欢的书籍还是有必要捧在手上细读的,《Java Puzzlers》就是其中之一,没事的时候就喜欢拿出来翻翻,怕自己像看新闻报纸一样看过就淡忘了,还是略作笔记让自己多份思考。

    软件开发人员无论最初是从哪种语言开始学习的,首先都要掌握该语言的编程基础,例如语句、表达式、变量、数据类型、运算符、字符串等等,这些基础性的知识简单,但细节却比较繁琐,不同的编译器也会有不同的编译规则。以前寝室有同学考过的全国计算机等级考试二级C语言的试题中,语言的础规则是出题者最热衷的题形之一,曾经也觉得出题者无聊,只重理论不看实际,毕竟一些表达方法和书写格式可以通过规范来约束简化,但是作为一名程序员,一个专业的开发人员,应该了解自己所使用语言的基础规则,有时候一些程序的BUG就是存在于这些不起眼,或是自己认为应该没有问题的地方。

    Java语言的表达式和C/C++比较相近,但也存在一些差异,这些差异不仅仅是那些看得见的差异,还有隐性的,例如相同的表达式,编译的规则不同。因此,我们需要理解Java表达式的一些基础性知识,加深认识。

1.  要精确表达一个浮点型变量,应该使用BigDecimal对象来构造这个实例,使用float或double在一般情况下只是提供了在一定精度范围下的一种近似,不能产生精确的结果。常用的数据库中都有与BigDecimal相对应的数据类型,有的更为详细。
2.  对于 long value = 30 * 300 * 3000 * 3000; 来说,long类型可以完整保存右边表达式计算的结果,但是右边表达式的计算是按照int类型进行的,只有当右边表达式计算完成后才会转换为long类型,在计算过程中,右边表达式的值就已经超出int范围,因此会出现计算溢出。
3.  通常我们使用最多的是十进制计算,和十进制不同的是,当十六进制或八进制常量的最高位被置位时,该常量是负值。
4.  注意数据类型之间的相互转换(特别是char类型和其他类型间的转换),以及三目运算符的第二和第三操作数类型不一致的情况处理。
5.  在C/C++中,操作符的操作数是从右向左计算,Java中相反。
6.  复合赋值操作和简单赋值操作在一般情况下是相同的,例如 x *= y 和 x = x * y ,但是当x和y类型不同时情况有所变化,例如当x为short类型,y为double类型时,x *= y的结果虽然和想象的有些出入,至少可以编译通过,但后者赋值却是非法的。

    大家可以继续补充……

posted @ 2006-03-30 23:47 Flyingis 阅读(1093) | 评论 (1)编辑 收藏

MVC的一幅简单素描

 作者:Flyingis

 

素描工具: Struts + Hibernate 3

素描对象:一个足够简单的基于 MVC Web 应用

目的:使用 Struts 分离业务逻辑与表现,使用 Hibernate 分离数据操作与业务逻辑,整理一种基本的 MVC 开发思路。

 

1. 素描框架
 

    该素描主要体现在系统层次的功能划分,系统结构的组织与设计上,素描足够简单,数据库中只涉及一张表:

    学生信息(学生编号、姓名、性别、年龄、专业信息)--Student( id, name, gender, age, specialty_id )

  • 系统设计

    公共类的设计与实现

    各模块的详细设计,主要描述一个基本的 CRUD 操作,以及对象数据传递

  • 系统的部署、测试与发布

2. 公共类设计
 

    基本的 CRUD 操作封装在基本的帮助类 HibernateHelper 中,实现 Object load(Class theClass, java.io.Serializable id) Query createQuery(String queryString) void setQueryParameter(Query query, String name, Object val) List list(Query query) void save(Object o) void update(Object o) void delete(Object o) void saveOrUpdate(Object o) 等这些基本方法。
 

    常量单独封装在 Constants 类中。

 

3. 各种对象设计

  • ActionForm:StudentForm-- 用于视图层与控制层之间传递数据。
  • 接口 StudentIf-- 实现了学生数据对象 Bean 所需要的所有接口方法。
  • 学生数据对象 StudentData-- 实现了记录学生对象数据的功能,并可以用作数据交互的传输对象,它实现了接口 Serializable StudentIf
  • 学生实体 Bean StudentBean-- 实现了学生实体的所有属性,它实现了接口 Serializable StudentIf

4. 对象管理实现类
 

    业务逻辑处理为项目的核心,直接关系到项目是否符合用户需求。因此,我们可以单独设计一个对象管理实现类 ManagerFacade,定义处理业务对象的CRUD操作,以增加学生信息为例public StudentIf addStudent(StudentIf student)。学生数据对象StudentDataAction中通过StudentForm接收到表现层传入的数据,然后作为ManagerFacade对象的addStudent方法的参数传入方法内,在方法体内声明学生实体StudentBean的一个对象,将学生数据对象即传入参数中的属性值赋给实体对象,然后调用公共类HibernateHelper的save方法完成数据库操作。其他基本操作与此类似,这样设计似乎对象较多,但各层之间分工明确,有利于降藕。

    另外,在数据传递过程中,还会涉及到数据类型的转换,可以专门设计帮助类来完成。

 

5. 页面 UI 设计
 

    除了设计美观的页面外,最重要的是页面结构要符合项目需要,并提供一定的使用体验,有时候简单实用就是最好。如果可以对用户浏览器统一规范要求,或是基本不会屏蔽 Javascript ,数据格式的控制可以放在客户端用 Javascript 实现。

 

6. 系统的部署、测试与发布。

posted @ 2006-03-27 17:50 Flyingis 阅读(2595) | 评论 (6)编辑 收藏

Web应用系统设计原则

    作者: Flyingis

    和C/S结构相比,B/S结构受限于网络带宽不利于进行大数据量的统计分析,网络传输存在潜在的安全问题,还有用户界面不及C/S结构友好等等,但随着网络带宽和网络应用的发展,加上AJAX技术的流行,使得现在越来越多的MIS系统或基于MIS系统的专业化应用系统都开始倾向于采用B/S结构进行设计,充分利用B/S结构的优点。但是,要充分发挥Web应用的内在潜力,挖掘应用深度和扩大适应能力,需要采用先进的应用架构和以实用为根本准则,使得系统既能满足业务需求,又能适应将来发展需要。因此,在开发Web应用系统时需要尽量遵循Web应用系统设计原则。

    实用性原则:这是所有应用软件最基本的原则,直接衡量系统的成败,每一个提交到用户手中的系统都应该是实用的,能解决用户的实际问题,否则该设计就是垃圾。

    适应性和可扩展性原则:系统需要具备一定的适应能力,特别是Web应用要能适应于多种运行环境,来应对未来变化的环境和需求。可扩展性主要体现在系统易于扩展,例如可以采用分布式设计、系统结构模块化设计,系统架构可以根据网络环境和用户的访问量而适时调整,从某种程度上说,这也是系统的适应性。

    可靠性原则:系统应该是可靠的,在出现异常的时候应该有人性化的异常信息方便用户理解原因,或采取适当的应对方案,在设计业务量比较大的时候可采用先进的嵌入式技术来保证业务的流畅运行。

    可维护性和可管理性原则:Web系统应该有一个完善的管理机制,而可维护性和可管理性是重要的两个指标。

    安全性原则:现在的计算机病毒几乎都来自于网络,Web应用应尽量采用五层安全体系,即网络层安全、系统安全、用户安全、用户程序的安全和数据安全。系统必须具备高可靠性,对使用信息进行严格的权限管理,技术上,应采用严格的安全与保密措施,保证系统的可靠性、保密性和数据一致性等。

    总体规划、分层实施原则:在开始设计之前应该对Web系统进行总体设计,然后在总体设计指导下分步开发。基于J2EE技术的应用系统是一个融合了多元信息的集成系统,现在一般都采用分层开发:表现层、控制层、业务逻辑层、模型层、数据访问层等,在适应系统需求的准则下,设计低耦合的分层结构,利于团队成员的分工协作,提高开发效率,降低项目风险,实现各个模块的功能设计,完成整个系统的开发。

posted @ 2006-03-25 15:28 Flyingis 阅读(5645) | 评论 (1)编辑 收藏

重温Struts--ActionForm

作者:Flyingis

ActionForm Struts设计中比较有争议的一个概念,在某些情况下也许不会使用到ActionForm,具体可以参照《Struts Action的多种角色一文。尽管如此,ActionForm在许多应用的开发中都实现了重要的功能,它是Struts框架提供的DTO,用于在视图层和控制层之间传递HTML表单数据,控制层可以从ActionForm Bean中读取用户输入的表单数据,也可以把来自模型层的数据存放到ActionForm Bean中,返回给视图,即使用它的主要目的是字段采集、类型转换器、以及传输对象等。对于ActionForm BeanMVC中所处层次结构的理解,可以参考《剖析MVC中的各种Object

ActionForm 的基本功能

1. 字段采集

Web应用程序开发过程中,数据的采集是最基本的一个环节,而html定义的数据输入控件和http定义的数据传输协议非常简单,因此在Struts中设计了ActionForm来弥补这种不足。Strutshttp参数处理的方法是将输入参数传递到JavaBean属性来进行处理,当ActionForm的属性与某个请求参数匹配,框架自动以参数的值设置属性。

2. 数据校验器

Html 没有在数据提交之前对数据进行校验的能力,使用javascript可以做到这些,优点在于可以减轻服务器负担,但javascript经常会被浏览器禁止,因此,在StrutsActionForm实现了部分数据校验的功能,当输入数据不符合要求时,页面将被返回到数据数据页面,要求用户重新输入。一般情况下,ActionForm属性定义为String类型,以便对各种输入进行捕获。另外,还可以用ActionFormAction对输入数据进行双重校验,ActionForm校验数据类型是否正确,Action校验该数据是否满足业务层的其他要求。

3. 类型转换

HTML 表单中的数据类型一般是Stringboolean类型,通过在ActionForm Bean中实现Helper方法,可以实现属性类型的转换。

4. 传输对象

ActionForm 可以作为其他Bean的数据载体,它装载的数据通常对应着持久层中的不止一个实体。

posted @ 2006-03-18 22:40 Flyingis 阅读(811) | 评论 (0)编辑 收藏

剖析MVC中的各种Object

    作者: Flyingis

    在Web应用和J2EE框架中经常可以碰到各种Object相关的名词,在网上搜索了一下,讨论各种Object术语的帖子一大筐,大的讨论整个框架,小的描述各个层次之间的细微差别,甚至有钻牛角尖之嫌。 BlogJava 上也有讨论VO和PO的贴子,例如 非飞 《各层共享使用PO的代价》 等。其实无论怎么讨论,这些术语、分层结构、应用框架无非都是为我们的应用而服务的,因此,我们需要的是理解这些术语提出的意义,是理解我们的项目需求,是理解我们采用的框架结构能否最大限度的满足项目的需要。

    在刚刚学习MVC/Model2之前,我是不了解VO/TO/PO/DTO/BO等等这些术语的含义的,至少理解上只是停留在浅层面,现在多看了一些,做了一点项目,多了些想法,但肯定还是存在理解上的偏差或误解,欢迎大家讨论指出!

    VO: 通常指ValueObject或ViewObject。ViewObject指的是UI需要的对象,Struts的FormBean就是其中的一种,它是Value Object和Transfer Object的总称。

    TO: Transfer Object,它和Value Object的区别可以参考Patterns of Enterprise Application Architecture。

    PO: Persistent Object,即可以被持久化的实体对象。

   
POJO : Plain Ordinary Java Object。

    DTO: Data Transfer Object,J2EE 中常用的一种设计模式,现在一般可以将使用Value Object的模式称为DTO模式,在
Jdon 上一篇《ValueObject和DTO模式的一些疑问》 阐述了两者的关系。

    BO: Business Object,可以分为三种情况,只包含业务对象的属性,或只包含业务方法,或两者都包含。对于BO的详细讨论,可以
参见这里

    这些概念经常交错在一起提出,给初学者造成了一些理解上的困难,其实只需要理顺下面几点,基本上就能弄清楚层次之前的前后关系和如何合理使用这些对象。

    1. VO能否和PO相同。首先回答是肯定的,VO是概念模型的一种抽象反映,当一个业务实体可以用一个物理实体表示的时候,VO和PO属性相同,那么它们是相等的。例如学生成绩管理系统中,成绩表单业务实体中包含学生信息、课程信息、成绩等,此时它已经不能用一个物理实体所能描述,而其中的学生信息,其VO和PO在属性上是一样的,此时的VO和PO相同。

    2. PO能否代替VO。仅仅从功能实现上来说,当VO和PO相同的时候,PO可以代替VO,这样可以减少一些代码量,但需要注意的是,这样会带来一些问题:当一个业务实体需要多个物理实体来表达的时候,在客户端显示一个业务实体就会多次访问数据库,即进行多次单表访问,非视图;当一个业务实体属性远少于一个物理实体的时候,可能会因装载过多不必要的数据而影响网络传输;对物理实体进行改动的时候会直接影响到表现层。简单的说,这样做增加了代码的耦合性,也增加了代码维护的难度,项目的可扩展性也大大降低,如果仅仅是为了减少代码量而付出这些代将显然是不值的,当然极为简单的应用可以考虑,一切从项目实际出发。

    3. VO包含的属性可以多于PO、少于PO、或等于PO中的属性。

    4. 一个基于Struts应用的简单数据提交流程(VO和PO单独存在):HTML 页面中包含了基本的信息,例如文本框、下拉框、单选等,构建一个ActionForm Bean与之一一对应,它是Web层数据的表示,当Web页面的操作流程发生改变的时候,需要对它进行修改,但不能将修改传递到业务层和持久层。然后Action读取ActionForm Bean的属性,构造PO对象,调用BO ,当BO收到这个PO之后,调用DAO接口方法,对PO进行持久化操作,完成数据的提交。这里,PO在业务层和持久层之间,没有被传递到Web层的View中去。

    5. 一个基于Struts应用的简单数据查询流程(VO和PO单独存在):Action读取ActionForm Bean中的查询属性信息,然后调用BO,BO获取ActionForm Bean之后调用DAO接口进行查询,返回所要查询的PO对象,交给Action,Action通过该PO构建 ActionForm Bean,通过request.setAttribute()或session.setAttribute(),重定向到查询结果页面输出需要的信息。

    6. 表现层中的字段一般定义为String或boolean类型,因此VO中的属性在传到Action并构建PO对象时需要进行数据类型的转换,或由ActionForm的helper方法来进行转换。

    参考文章和贴子:
   
http://www.jdon.com/jive/article.jsp?forum=91&thread=23672
    http://www.jdon.com/jive/article.jsp?forum=91&thread=21571
    http://www.hibernate.org.cn/viewtopic.php?t=627&postdays=0&postorder=asc&start=0
   
http://bbs.hidotnet.com/704/ShowPost.aspx
    http://lifework.cnblogs.com/archive/2005/09/03/229596.html
    http://www.microsoft.com/china/MSDN/library/architecture/patterns/esp/DesDTO.mspx  

posted @ 2006-03-17 00:28 Flyingis 阅读(2583) | 评论 (0)编辑 收藏

重温Struts--标签

作者:Flyingis

Struts标签提供了大部分应用来满足创建MVC架构表现页面的所有功能。在一个MVC应用中,请求并不是直接到达表现页面,而是首先经过控制器,仅当业务数据被获取,并且业务规则被应用后,控制器才处理表现页面。页面的职责就是输出结果和捕获用户输入,Struts标签的功能目的就在于此。

虽说Struts标签库能满足我们大多数情况下的需要,但不是唯一可用的标签,例如JSTL标签、DisplayTag等等。Struts标签和其他各种标签的基本使用方法在各种书本上都有介绍,这里总结一下标签使用中的个人体会,并不断更新。

1.        Struts中包含三个标签库,BeanHTMLLogic,其中HTML标签库依赖于框架,其他大部分标签不依赖于框架,可以在其他应用中使用。

2.        Struts HTML标签和一般HTML标签具有一定的对应关系,但也存在一点不同。使用ScriptletHTML标签需要在使用前在页面中将Form Bean声明为一个脚本变量,Struts标签则不需要声明就能找到该Bean。在默认情况下,Struts标签将对剩下的表单使用同一个Bean,所以不需要对每一个控件都进行指定。例如:
<input type=“text” name=“username” value=“<%=user.getUsername()%>”/>
使用Struts HTML标签
<html:text property=“username”>

3.        Struts HTML标签和一般HTML标签具有一定的对应关系,但存在几个特例,在Struts HTML标签中,Messages / errors / rewrite分别用来表示显示一组消息、显示一组错误消息、输出一个编码的URL路径,而这些在一般HTML标签中就不存在。

4.        HTML有时需要处理特殊的字符,包括标签的括号、&符号以及其他的内容,如果这些字符作为文本字段的一部分,可能会出现错误并造成HTML崩溃。如果确实需要在数据中存储这些字符,可以在网页中进行设置,使得这些字符不被页面过滤成为特殊字符,例如:
<bean:write name=“UserForm” property=“username” filter=“false”/>

5.        使用<html:password>时,如果页面校验错误,password属性将从Form Bean中读回,并放置在password标签中。虽然密码会被浏览器用符号隐藏,但在HTML源代码中仍然可以看到,存在安全上的隐患,因此可以在标签中加入redisplay=false来保证password总是以空白状态显示给用户。

6.        提供一个Javascript的返回按钮,可以定义一个没有属性的简单表单,Struts配置文件:
<action path=“/adduser”
      type=“org.apache.struts.ForwardAction”
      name=“BlankForm”
      scope=“request”
      validate=“false”
      parameter=“/user.do”>
JSP
页面:
<html:form action=“/adduser”>
<html:button property=“page” onClick=“history.go(-1)”>here</html:button>
</html:form>

posted @ 2006-03-12 09:23 Flyingis 阅读(2623) | 评论 (0)编辑 收藏

重温Struts--Validator和Tiles

作者:Flyingis

今天要回顾的是ValidatorTiles以及简单的Plugin实现,刚刚登录blogjava就发现Mustang已经发了两篇好文《在Struts中使用Validator实现可配置的信息校验() ()》,本文则从实现流程来总结Validator的使用方法,并针对ValidatorTilesStruts PlugIn插件略谈一些个人心得。

Validator

在使用ActionForm时,将数据的验证工作放在validator()方法中虽说是一个可行的方法,但在ActionForm中编写特定的验证逻辑会降低ActionForm的重用性,并给系统的维护带来麻烦。Validator框架可以将验证逻辑移至ActionForm之外,实现Javascript客户端验证或服务器段验证。具体实现Validator验证步骤如下:

1.        Validator是以plugin的方式来扩充ActionServlet功能的,需要在Struts-config.xml中声明这个plugin

2.        导入Validator中的资源信息,用来向用户提示验证中出现的异常消息。Validator可以支持国际化信息,为每一个国际化信息提供对应的资源信息。

3.        利用validaton.xml文件来定义用户需要验证的每一个JSP表单中的每一个字段的验证规则,其中可以利用validator-rules.xml中已经设计好了的验证器,也可以自定义验证方式。

4.        客户端验证需要validator-rules.xml中已提供的验证规则,或是自定义规则,然后在jsp页面中声明<html:form action=“/action.do” onsubmit=“return validateActionForm(this);”>,加上可以生成实现验证的Javascript代码<html:javascript formName=“ActionForm” staticJavascript=“true”/>。服务器端验证同样需要validator-rules.xml中已提供的验证规则,或是自定义规则,另外,实现验证的ActionForm需要是DynaActionForm的子类,和客户端验证不同的是,在捕获服务器端错误消息时,jsp页面中需要嵌入代码

<html:messages id=“error”>

  <bean:write name=“error”/>

</html:messages>

在配置和设计Web系统验证功能的时候,需要注意的是要理解在validaton.xml中定义验证规则的时候每个参数的具体功能,我最初使用Validator的时候就因为参数混淆而验证失败,费了一点时间。还有就是自定义验证规则时,需要注意每个参数的具体含义,例如在某种情况下,validaton.xml<var-name>myproperty</var-name>中自定义的属性myproperty需要和自己编写的验证器类中的代码一致等等。

Tiles

Tiles是一个模板机制,它可以让网页的配置框架和内容分离,提供一个版面管理机制。通常有两种方式管理Tiles配置资源,一种使用XML,另一种使用JSP页面直接管理。

使用XML配置的Tiles可以支持国际化,例如可以另存为tiles-defs.xml并命名为tiles-defs_zh.xml,将encoding改为GB2312,这样可以在配置中使用中文。使用XML配置文件可以方便的实现版面配置和内容的分离,并且能扩充某个定义,达到重新定义其中所管理页面资源的目的。使用JSP页面直接定义管理版面的配置资源更为简单和灵活,同样可以和xml一样重新定义网页的地址。不使用JSP框架页面而是直接在JSP页面中使用配置页面,可以不用额外去定义管理文件,但缺点是无法重用这个页面定义的内容。

TilesCSS结合起来,基本上能满足一般页面控制的需要。

PlugIn插件

通过继承ActionSerlvet,重写它的init()方法,修改或增减它的初始化资源来达到改变ActionServlet功能的方法,这从软件架构角度上来讲并不是一个好方法。Struts1.1之后,可以通过PlugIn接口来实现动态增减ActionServlet功能的目的。ActionServlet加载后,会执行实现PlugIn接口的类的init()方法,在ActionServlet终止前,执行实现PlugIn接口的类的destroy()方法。ValidatorTiles就是利用这种方式来扩充Struts功能的。

写到这里,感觉使用好ValidatorTilesPlugIn插件最重要的就是对配置元素的理解,和程序调用流程的掌握,了解到Struts的插件机制是如何运转的,以此来扩充Web应用程序的功能,提供更好的用户体验。

posted @ 2006-03-08 14:52 Flyingis 阅读(1957) | 评论 (2)编辑 收藏

重温Struts--Action

作者:Flyingis

Struts中,ActionServlet担任分配工作的控制器角色,实际的工作是交给Action对象来进行的。ActionStruts框架的核心类之一,它主要用来访问业务层、为表现层准备数据对象和处理错误异常。

ActionStruts框架中基本上属于控制器的角色,通常不建议在Action中加入过多的业务逻辑,将业务逻辑封装在其他的类中,然后在Action中建立这些类的对象,调用对象的方法来实现业务功能。比较遗憾的是,当业务逻辑中出现异常的时候没有办法将异常说明在页面中直接反应出来,展现给用户,在Action中控制这些异常可以做到这点。

要更详细的了解Action的工作机理,就要剖析ActionServlet控制器的工作流程及其核心方法。在Struts中,担任控制器角色的核心是ActionServlet,所有的请求都必须先通过它,而对所有请求的处理是交付给RequestProcessor来完成的,既然处理请求的任务是交给RequestProcessor来完成,那么可以直接查看org.apche.struts.action.RequestProcessor类,看其process()方法实现了哪些功能,从源代码中的英文注释我们可以更深入了解到整个处理过程,很多书籍和网上不少文章都描述了这个过程,还有典型的处理过程图示,这里就不再详述。只是从这个过程可以看出,通过继承ActionServlet来定义自己的控制器请求意义不大,重写init()方法倒是可以修改初始化工作,如果需要定义自己的控制器,可以继承RequestProcessor并修改其中的process()方法来实现。

Struts应用中,除了直接继承org.apache.struts.action.Action类实现Action功能外,Struts还提供了其他几种Action类来满足某种特定需要,这些书本上已经写了很多,这里只是照葫芦画瓢略作总结:

ForwardAction—当需要从一个页面转到另一个页面或资源时,不提倡直接使用页面或资源路径调用,除了与MVC/Model2架构向背之外,有时还会带来其他的问题,前几天在网上看到一个帖子就是因为直接调用资源出现了异常,具体出自于哪里没有记住。这里,应该通过控制器使用ForwardAction来完成链接的跳转,使用属性parameter设定forward的链接地址。

IncludeAction—ForwardAction类似,当需要引入一个资源时,可以使用IncludeAction来实现,属性parameter设定include的链接地址。

SwitchAction—用于从一个模块转换至另一个模块,一种方法是使用相对于Context的路径来进行forward查找,另外一种就是使用SwithAction,它需要在请求中带两个参数,一个是prefix用来指定模块前缀名称,一个是page用来指定相对于模块的资源路径。

DispatchAction—随着Struts Web应用规模扩大,维护Action复杂度提高,可以使用模块化来管理Action。另一方面,当一个页面需要多个Action时,我们就可以使用DispatchAction来将一个页面中所有相关的动作放在一个action类中实现,此时不需要重定义execute()方法,它已经在DispatchAction抽象类中定义,我们需要编写自己的方法来响应一个页面上不同的动作。它的关键属性是parameter

LookupDispatchAction—它是DispatchAction的子类,不同的是,当页面按钮的property属性相同的时候,它可以通过查询资源文件来确定相应的动作,这个功能主要是通过重写getKeyMethodMap()方法实现的。

posted @ 2006-03-06 00:07 Flyingis 阅读(1165) | 评论 (0)编辑 收藏

重温Struts--ActionMapping和ActionForward

作者:Flyingis

前段时间用Struts完成一个小项目,当时还没有来到blogjava,很多东西也没有记录。现在花一点时间,将整个Struts应用重新温习一遍,重新挖掘项目开发过程中没有注意到的知识点,并写下自己的一些心得与体会。

ActionMapping

ActionMapping将对Struts应用中有效的业务逻辑进行分类,当一个请求到达时,ActionSevletActionMapping目录中查找对应的信息。ActionMappingStruts应用的一个核心设计,当需要了解一个Struts应用,或编写一个新的Struts应用的时候,都应该从ActionMapping入手。ActionMapping有较多的属性信息,具体参考相关文档。

ActionForward

ActionForwardStruts的核心类之一,其基类仅有4个属性:name / path / redirect / classname。在基于StrutsWeb应用程序开发过程中,Action操作完毕后程序会通过Struts的配置文件struts-config.xml链接到指定的ActionForward,传到Struts的核心类ActionServletActionServlet使用ActionForward提供的路径,将控制传递给下一个步骤。ActionForward控制接下来程序的走向。ActionForward代表一个应用的URI,它包括路径和参数,例如:

path=“/modify.do?method=edit&id=10”

ActionForward的参数除了在struts-config.xml和页面中设置外,还可以通过在Action类中添加参数,或重新在Action中创建一个ActionForward

ActionForward中有一个重要的属性redirect,当redirect=false时,将保存存储在http请求和请求上下文中的所有内容,仅在同一个应用中可用。当redirect=true时,Web客户端进行一次新的http请求,请求的资源可以在同一个应用中,也可以不在,原来的请求参数不再保存,原来的请求上下文也被清除,新的http请求仅包含ActionForwardpath属性里所包含的参数。如果在同一个应用中,用户会话的上下文会被维护。

ActionForward分为全局转发和局部转发,ActionMapping对象的findForward方法首先会检查局部转发列表,查找失败就会到全局转发列表中查找。书写格式中,我们一般将全局变量定义为String常数,避免误解,使得转发列表结构清晰易读。

在项目开发过程中经常碰到一种情况,当页面已经改变了,浏览器中的地址如/modify.do/modify.jsp却没有变化,当时没有考虑这么细,虽然存在疑问,但没有影响到程序功能的实现,因此忽略过去了,今天查找了一些资料才弄清楚。客户端浏览器显示的是浏览器最后被给定的URL,当URL被提交后,在某个组件返回一个响应给浏览器之前,Web应用可能已经转发请求多次,而这些过程都发生在服务器端,客户端浏览器并不知道有什么变化。当一个http响应被返回时,它并没有包含地址栏的值,所以浏览器仅仅显示其用来作为初始请求的地址。通过使用redirect可以改变浏览器地址的显示,因为这样可以向浏览器提交一个新的请求,但付出的代价是数据不能通过请求上下文传递到页面,这也是使用forwardredirect的差异之一。

posted @ 2006-03-05 10:40 Flyingis 阅读(1414) | 评论 (0)编辑 收藏

IntelliJ IDEA 5.1 初步感受 + crack

作者:Flyingis

最初开始接触Java的时候总喜欢跟潮流,当经历JDK+UltraEdit的洗礼之后,便开始使用JBuilder7/8/9,然后是Eclipse3.0.1加上各种插件,用于Web系统开发,使用感觉还不错,加上Eclipse有众多优秀插件的支持,因此就没有再去琢磨其他的IDE环境。

前两年就听说过IntelliJ IDEA,当时是在《CSDN开发高手》杂志上看到一篇介绍它的文章,还记得上面说IntelliJ IDEA显著特征之一,就是方便的即时分析和重构功能,当时它的版本还是3.0.5,转眼之间现在IntelliJ IDEA 5.1都已经发布了,基本功能和易用性都得到了很大程度的改观和加强。在安装好软件以后,单是看开发环境中Refactor下的菜单项就知道它Refactoring的功底了。现在IntelliJ IDEA 5.1也开始支持插件,第一次进入开发界面整个右边栏目全部显示的是个人的插件和IDE已经集成的插件,虽然IntelliJ IDEA的开源插件还远不如Eclipse,但是这些才刚刚开始,IntelliJ IDEA 5.1Hibernate插件Hibero1.2已经发布,相信在这方面IntelliJ IDEA会越做越好。除此之外,IntelliJ IDEA似乎并不必Eclipse弱,甚至很多方面都比Eclipse强,例如全面支持Web开发、优秀的重构、众多实用插件的集成、方便的环境设置等等,在网上有很多这方面的文章。另外,过去曾经听说IntelliJ IDEA对资源占用量比较大,其实只要是Java IDE,就没有一盏省油的灯,刚才简单比较了一下,打开IntelliJ IDEA 5.1内存占用量是74M多,打开Eclipse 3.1内存占用大于88M,在机器配置越来越高,内存价格越来越便宜的今天,这种问题也不用过多考虑了,Visual Studio 2005的消耗量更大。

总之,个人感觉IntelliJ IDEA完全可以和EclipseJBuilder等开发环境相媲美,甚至更优秀,收费可能是它进一步扩大用户群的阻碍之一,不管怎么样,它给Java开发人员提供了另外的一种选择。

官方资源:

http://www.intellij.com

http://www.jetbrains.com

下载:

http://www.jetbrains.com/idea/download/

download crack

相关文章:

SUN发布开源Netbeans 5.0

Netbeans拉近和Eclipse差距

 

posted @ 2006-02-26 21:48 Flyingis 阅读(5072) | 评论 (16)编辑 收藏

Google启动个人网站服务

    Google为每个Gmail用户准备了100MB免费个人网站空间,并且没有任何广告,这和微软的MSN形成了一种对比。现在感觉不论什么事情,Google总能把微软先甩在后面,然后让微软去追赶,这得益于Google的经营模式,得益于Google的简约与实用,也得益于Google较好的把握住了用户潜在的需求。
   
   
点击这里来创建自己的空间

    近段时间其他Google相关热点文章参考以下链接:

   
Google的Offer
    Google新服务--出行路线规划服务
     wallop和orkut的差异
    Google吸引用户有新招:Gmail中融合GTalk
    开发人员专用搜索引擎--Krugle
    Google桌面搜索新功能体验记(上) (中) (下)
    Google总部似乐园(图)

posted @ 2006-02-24 00:27 Flyingis 阅读(1342) | 评论 (4)编辑 收藏

WebGIS发布前GIS工程规划设计

    作者:Flyingis

    对于一个GIS系统来说,不论是桌面GIS还是WebGIS,最重要的和最有价值的是数据,没有设计良好的空间数据的支撑,该GIS系统就失去了其存在的意义。目前,主流的比较成熟的 WebGIS发布平台是ESRI的ArcIMS和MapInfo的MapXtreme,基于这两大平台均可以发布各自产品的数据,通过整合MIS功能,实现政务管理、管网管理等应用。在程序发布前,我们需要经过深加工的、可以满足用户业务需求的、完整的、可用于特定平台发布的GIS数据,这个前期的工作属于GIS工程的规划设计,一般可以分以下几个步骤完成:

    1. 确定项目要实现的目标,即GIS工程的开发目的。经常我们需要回答这些问题,什么是需要解决的问题?目前这个问题解决的怎么样了?这个工程的最终产品需要以什么样的形式展示,是报告,是高质量的可用于大幅展示的地图,是用 WebGIS 将产品发布,还是这些最终产品都需要?这个产品的用户群是谁?这些数据是否还要用于其他的用途?等等。这个步骤有点类似于软件工程的项目可行性报告和需求分析中的部分工作,但是更强调产品对数据的要求。

    2. 建立工程数据。这项工作的工作量一般情况下都非常大,除非项目经费充足可以购买数据或是手中已经有许多工作中需要的数据,否则需要三个步骤来完成,设计地理空间数据库,包括所需字段、字段类型等等,产品数字化和数据的整理,还有管理数据库,如设定坐标系、连接相邻图层。

    3. 分析数据。空间数据的分析是GIS工程的一项重要任务,分析的过程将直接影响最终的产品结果。空间数据分析包括计算距离、生成缓冲区、计算面积周长、覆盖数据值相同的区域、定位、路径选择等等。

    4. 成果展示。主要是展示数据分析的最终结果,以什么样的形式展现出来最好,或能满足用户需求,以WebGIS发布是其中的一种,另外还有图表和报告等形式。

    GIS软件工程的开发和计算机软件工程有很多相似之处,但其中最大的区别也是最重要的就是对数据有比较特殊的要求,因此在进行WebGIS平台开发部署之前,需要把握整个数据的概况,而了解整个GIS工程的规划设计对开发人员理解WebGIS构造和应用是极有帮助的,包括平台软件的使用和基础功能的应用等等。


posted @ 2006-02-15 11:41 Flyingis 阅读(1807) | 评论 (1)编辑 收藏

开发人员专用搜索引擎--Krugle

作者: Flyingis

    网络搜索领域从来没有停止过战争,可能是
Google 了解到自己的即时通讯聊天软件 GoogleTalk 的市场份额还远远不及传统 QQ/MSN/YAHOO IM 软件,因此准备在Gmail中嵌入“Gmail Chat”,靠目前

Gmail 的影响力来让用户了解和使用 Google 公司的 GoogleTalk

但对于开发人员来说,近期关于网络搜索的热点新闻肯定少不了 Krugle 一个为开发人员量身定做的开发引擎,它主要有以下几种功能:

1.        和传统搜索引擎不同, Krugle 专门用来搜索代码,不管是压缩包文件,还是展示在 blog 、网页上的代码,只要是在网络开放的空间内, Krugle 都能找到,并且 Krugle 还可以自动生成某个特定代码的 API 报告 ( 尚处实验阶段 )

2.        Krugle 能提供和代码相关问题的解答。

3.      允许开发人员对搜索结果进行评论,并通过创建 tag 的方式来帮助其他人更好的找到所需的代码,实现共享。

4.       Krugle 具有较快的搜索速度,能对和代码相关的例如各种技术主题、 API 、示例、文档进行快速搜索。

Krugle 的宣传如此,究竟其功能和性能如何现在还不知道,要等到 3 8 Krugle 搜索才会在San Diego的 O’Reilly Emerging Technology Conference 上亮相,现在可以在Krugle网站上注册 ,等到该搜索引擎 3 8 上线后, Krugle 会向用户的注册信箱发送 E-mail 来邀请体验 Krugle 搜索。和最初 Gmail/orkut/wallop需要邀请 一样,体验新鲜东西总是有些麻烦,不管怎么样,Krugle还是让人期待的。

附图链接: krugle搜索主页面    搜索代码    搜索解答    保存和共享

posted @ 2006-02-09 23:57 Flyingis 阅读(3019) | 评论 (3)编辑 收藏

基本数据结构的Java实现

链表

class Node {

Object item; Node next;

  Node (Object v) {

item = v; next = null;

}

}

头指针,空尾指针

初始化:head = null;

x后插入t

if ( x == null)

{ head = t; head.next = null; }

else { t.next = x.next; x.next = t; }

移走x之后的结点:t = x.next; x.next = t.next;

循环遍历:for ( t = head; t != null; t = t.next )

检查链表是否为空:if ( head == null )

空头结点,空尾指针

初始化:head = new Node(); head.next = null;

x后插入tt.next = x.next; x.next = t;

移走x之后的结点:t = x.next; x.next = t.next;

循环遍历:for ( t = head.next; t != null; t = t.next )

检查链表是否为空:if ( head.next == null )

空头结点,空尾结点

初始化:head = new Node(); z = new Node(); head.next = z; z.next = z;

x后插入tt.next = x.next; x.next = t;

移走x之后的结点:t = x.next; x.next = t.next;

循环遍历:for ( t = head.next; t != z; t = t.next )

检查链表是否为空:if ( head.next == z )

循环链表

第一次插入:head.next = head;

x后插入tt.next = x.next; x.next = t;

移走x之后的结点:t = x.next; x.next = t.next;

循环遍历:t = head; do { t = t.next; } while ( t != head );

检查是否只有一个数据项:if ( head.next == head )

 

堆栈

数组实现

class Stack {

  private Object[] s;

  private int n;

  Stack ( int maxN ) {

    s = new Object[maxN]; n = 0;

}

boolean isEmpty() { return ( n == 0 ); }

void push ( Object item ) { s[n++] = item; }

Object pop() {

  Object t = s[--n]; s[n] = null; return t;

}

}

链表实现

class Stack {

  private Node head;

  private class Node {

Object item; Node next;

Node ( Object item, Node next ) {

  this.item = item; this.next = next;

}

}

Stack ( Object maxN ) { head = null; }

boolean isEmpty() { return ( head ==null ); }

void push ( Object item ) { head = new Node(item, head); }

Object pop() {

  Object v = head.item;

  Node t = head.next;

  head = t;

  return v;

}

}

 

FIFO队列的链表实现

class Queue {

  private class Node {

Object item; Node next;

Node ( Object item ) {

  this.item = item; this.next = null;

}

}

Private Node head, tail;

Queue ( Object max ) { head = null; tail = null; }

boolean isEmpty() { return ( head ==null ); }

void put ( Object item ) {

  Node t = tail;

  tail = new Node(item);

  if ( empty() )

    head = tail;

  else t.next = tail

}

Object get() {

  Object v = head.item;

  Node t = head.next;

  head = t;

  return v;

}

}

posted @ 2006-02-05 23:08 Flyingis 阅读(1109) | 评论 (1)编辑 收藏

数据结构中避免数据项的重复

抽象数据类型(ADT)是一种只能通过接口访问的数据类型,它是字段与基于字段的操作所构成的集合。这里的接口不是interface,而是访问数据的途径,接口把数据的表示和操作方法的实现完全分离开来。两种最基本的ADT是堆栈和队列,并且根据我们的需要,可以构建更为复杂的ADT,例如可以对数据项进行计数,检查数据项是否存在重复等等。

在很多实际应用中,我们都不允许存在数据项重复的情况,需要对用户提交的重复数据进行合适的处理。让用户保证不提交重复的数据可以避免这种情况的发生,但显然这种方法并不实际,既然使用ADT就是为了给使用它的程序员提供简单明了的数据类型解决方案,那么我们就应该在ADT中来解决这个问题。以队列为例,一般可以通过两种策略来处理这个问题:

1.        放弃新输入的数据项:当最新放入队列中的数据项已经在队列中时,放弃当前输入的数据项。

2.        放弃旧的数据项,保存新输入的数据项:当最新放入队列中的数据项已经在队列中时,放弃已经存在于队列中的数据项,保存当前放入的数据项。

    对于第一种处理方式,在一种特殊的情况下,数据项存储的数据是0~N-1之间的整数,那么可以通过增加一个新的数组a[i]或链表来储存boolean类型数据,当队列中第i个位置上已经存在数据i(i<=N-1),设置a[i]=boolean,那么可以通过a[i]来判断数据i是否已经存在于队列中。第二种处理方式比第一种更为复杂一些,如果有必要,还可以让用户去选择采取哪种策略来避免重复的数据项。但不管怎么样,我们可以通过构建不同类型的ADT,并在ADT中实现某些我们所需要的功能,将能极大限度地保证数据结构和算法的灵活性与清晰的结构,使基于ADT的实现能满足各种不同的具体应用,并方便类的重构。

posted @ 2006-01-30 00:34 Flyingis 阅读(1111) | 评论 (2)编辑 收藏

理解数组和链表的最基本特性

作者:Flyingis

 

数组和链表是数据结构中老生常谈的问题,在指针或是引用这些概念出来之前,数组就能用来实现链表的功能。这里所说的链表指的就是用指针或对象的引用来设计的链表。

在实际的应用开发中,数组由于它天生的种种特性(参考Java容器分析数组》),更多的会被开发人员所想到用到,但所有的数据结构都有它特定的适用场合。众所周知,数组和链表最大的区别在于,使用数组能够快速访问数组中的每个元素,而使用链表可以方便的操纵每个数据项。下面通过两个很有趣的例子说明了它们各自的区别与优势。

虽然在JDKJava提供了List接口及其接口的实现(ArrayList/LinkedList)对链表数据结构提供了有力的支持,具体可以参考Java容器分析—List和Set但下面数学上关于Josephus问题的实现仅使用了自定义的最简单的链表结构。

/**

 * 根据命令行输入的N值,计算出所有小于N的素数

 * 是素数将数组元素值设为true,否则设为false

 */

class ArrayApp {

  public static void main(String[] args) {

int N = Integer.parseInt(args[0]);

boolean[] a = new boolean[N];

for (int i = 2; i < N; i++)

  a[i] = true;

for (int i = 2; i < N; i++)

  if (a[i] != false)

    for (int j = i; j*i < N; j++)

      a[i*j] = false;

for (int i = 2; i < N; j++)

  if (a[i])

    System.out.println(“” + i);

}

}

/**

 * N个有编号的小球围成一圈,每个M-1个就拿去一个小球,计算最后剩下的球的位置

 */

class LinkApp {

  static class Node {

int value;

Node next;

Node (int v) { v = value; }

}

public static void main(String[] args) {

  int N = Integer.parseInt(args[0]);

  int M = Integer.parseInt(args[1]);

  Node first = new Node(1);

  Node x = first;

  for (int i = 2; i <= N; i++)

    x = (x.next = new Node(i));

  x.next = first;

  while (x != x.next) {

    for (int i = 1; i < M; i++)

      x = x.next;

    x.next = x.next.next;

}

System.out.println(“最后剩下的小球:” + x.value);

}

}

posted @ 2006-01-24 23:42 Flyingis 阅读(2209) | 评论 (0)编辑 收藏

算法分析规则

作者:Flyingis

    算法作为实现计算机程序实现时解决问题的方法,在计算机应用领域发挥着举足轻重的作用。它研究的内容是解决问题的方法,而不是计算机程序的本身。一个优秀的算法可以运行在比较慢的计算机上,但一个劣质的算法在一台性能很强的计算机上也不一定能满足应用的需要,因此,在计算机程序设计中,算法设计往往处于核心地位。如何去设计一个适合特定应用的优秀算法是众多开发人员所关注的焦点,在算法设计时,需要了解算法设计的规则。

要想充分理解算法并有效地应用于实际问题,关键是对算法的分析。通常我们可以利用实验对比分析、数学方法来分析算法。实验对比分析很简单,两个算法相互比较,它们都能解决同一问题,在相同环境下,哪个算法的速度快我们一般就会认为这个算法性能更好。数学方法能将算法分析的更为细致,能在严密的逻辑推理基础上判断算法的优劣,但在完成实际项目过程中,我们很多时候都不能去做这种严密的论证与推断,因为我们不是在完成一道数学难题,也不是数学领域的专家,将大量的时间花费在公式的计算与证明上会导致整个项目进度缓慢、成本过高,因此,在算法设计中,我们往往采用能近似表达性能的方法来展示某个算法的性能指标。例如,计算机对n2n2+2n的响应速度,当n比较大的时候几乎一样没什么区别,我们便可直接认为后者算法的复杂度为n2。在分析算法时,隐藏细节的数学表示法成为大O记法,它可以帮助我们简化算法复杂度的许多细节,提取主要成分,这和遥感图像处理中的主成分分析思想相近。

基于算法复杂度简化表达的思想基础上,我们通常会对算法进行最坏情况分析和平均情况分析。对于一个给定的算法,如果能保证它的最坏情况下的性能依然不错当然很好,但是在某些情况下,程序的最坏情况算法的运行时间和实际情况的运行时间相差很大,在实际应用中我们几乎不会碰到最坏情况下的输入,那么此时进行最坏情况分析显得有些画蛇添足,特别是分析最坏情况算法会花费大量精力的时候。算法的平均情况分析可以帮助我们估计程序的性能,作为算法分析的基本指标之一,但是平均情况和实际情况仍然会有相差很大的时候,这时我们便可以使用随机法来尽量模拟现实中的情况,这样可以得到在严格的概率意义上的预测运行时间。另外,对于一个经典算法,我们没有必要再去对该算法进行改进,研究它的上界和下界,只需要了解该算法的特性,然后在合适的时候使用它。

最后,当一个程序变快和变慢,让计算机反映出来的时间差几乎不会让人产生感觉的时候,我们也没有必要去改进这个算法,例如程序进行1000次循环花费0.001秒,改进后为0.1秒,在实际应用中通常也只需要几千次循环,此时我们就没有必要去花时间来研究这个算法了,只要该算法能正确完成任务即可。

posted @ 2006-01-22 00:34 Flyingis 阅读(3337) | 评论 (9)编辑 收藏

wallop 和orkut 的差异

    作者:Flyingis

    博客在前几年就已经存在了,但博客人数的增长速度和现在相比相差一个数量级,从QQ/BBS/Blog/Wiki的发展都经历了一个从缓速发展到飞速发展的质的变化,这是之前人们所不会预料的。它们都抓住了人们生活中最普通的但又是潜在的需求,从而在互联网中站稳脚跟,丰富了人们的网络生活,成为网络经济增长的亮点。

   
walloporkut大家都不陌生,它们被称为社会软件,似乎要像众多互联网上的“前辈”一样,挑起网络流行的大旗,成为网络中的新星。它们的理论基础,是美国著名社会心理学家米尔格伦(Stanley Milgram)于20世纪60年代最先提出的“六度分隔法”(Six degrees of separation)。前段时间在blogjava上胡子鱼给了一份邀请,让我有机会试用了wallop和orkut。

    虽然wallop和orkut都基于相同的理论基础,但Microsoft和Google的产品还是有许多不同点:

1. wallop算是一个真正意义上的RIA(
Rich Internet Application),orkut则基于当前最流行的AJAX技术。
2. wallop的风格当然离不开微软的“最佳用户体验”,不论是Windows XP、Vistual Studio 2005还是年底即将发布Vista都是如此。orkut则沿用Google一贯的简约、明了。
3. wallop的个人信息很简单,而orkut则为用户信息提供了丰富的细致的分类,让大家更容易了解朋友的基本信息。
4. wallop通过导入rss feed,可以让朋友直接在wallop上查阅个人的blog,并具有简单的blog功能。orkut则没有。
5. wallop中和朋友的等级划分比较简单,通过point to me来显示两人之间的关系。在orkut上可以了解到对方较为详细的信息,并通过众多等级划分和属性归类,将网络中的每一个个体都能准确划分到相应类别。
6. wallop功能上还比较简单。orkut则继承了Google搜索良好的基因,并集成了社区、媒体、新闻等功能,让人感觉更为丰富。

    在细节上,wallop和orkut还有许多不同的地方,但它们都为我们展示了Internet又一个丰富的内涵与体验,让人与人之间的距离更近。wallop和orkut这类社会软件最终走向何方,是否会成熟,和“前辈”一样被广大用户所接受?我们拭目以待。

    附图(点击后面链接可浏览原图):wallop  orkut
    
    wallop.gif    orkut.gif

    ps. 现在手上还有一些wallop、orkut和gmail的邀请,需要的朋友可以留下信箱。orkut没有限制,gmail有几十个,wallop有十个(送出去了两个,似乎没有减少)。注意,gmail的信箱接收邀请我试过两次都没有收到,大学校园的信箱也没有用,据说126/163的国内信箱也不行,因此建议用hotmail/msn/yahoo的信箱,这三个即发即收,我试过的。

    wallop邀请有限,需要的朋友请尽量提供hotmail/msn/yahoo的信箱,如果没有接收到邀请,证明邀请已送完,需要一点时间向wallop申请更多的邀请再发送给大家,已申请上wallop的朋友可以发送邀请给其他的人,我也可以请其他申请上的朋友发给你们。

    orkut需要gmail才能接收邀请,因此需要orkut邀请的我会先发送gmail邀请到你们的信箱,然后再把你们的gmail信箱反馈给我。

posted @ 2006-01-17 22:52 Flyingis 阅读(3435) | 评论 (143)编辑 收藏

Hibernate的灵活与方便

    作者:Flyingis

    许多软件设计的思维都源于生活的方方面面,可能存在某些设计思想并非受平时生活所启迪,但它们面临的情况却如此相象。软件设计原本就是生活的一部分,软件设计的“灵活”与“方便”(或“简便”)即是世界万物的一个共同点。

    Hibernate作为流行的企业应用和关系数据库之间的持久化中间件,受到越来越多的关注。虽然使用Hibernate可以使得项目易于维护,帮助开发人员更好地处理复杂关系模型,提供了很强的方便性,但却失去了JDBC原有的灵活性。如何在“灵活”与“方便”之间取舍、平衡显得重要起来。

    不久前江南白衣的一篇文章ORM透明持久化方案面对的共同困境道出了现在ORM不尽如人意的地方,除了网上,还有书本的前言等对Hibernate的众多赞美之词外,现在讨论它呆板、配置繁琐的声音也逐渐多了起来,最热闹的就是前段时间Ruby on Rails引起J2EE阵营的骚动。个人对Java研究尚浅,对Hibernate有一些使用心得,下面所列出的不一定是Hibernate本身的缺陷,不足之处希望大家拍砖指出。

1.  提取表单中字典Value的不便。
    字典一般由ID和NAME两个字段组成,其ID号存储于数据库其他表中,当查询这些表信息时,Hibernate以List或Set形式返回的结果,没有办法将ID号显示为对应的NAME。在JDBC中,可以直接通过Map来存储字典,通过map.getValue()来返回字典的值。

2.  Hibernate内置映射类型复杂化
    在开发过程中,时常会查找Hibernate映射类型--Java类型--标准SQL类型之间的关系。繁杂之处体现在两方面,一是各种数据库的数据类型和标准SQL之间会有一定的出入,二是Hibernate映射类型虽然大部分和Java类型相同,但也存在比较晦涩的地方,例如character类型对应Java的char / java.lang.Character / java.lang.String,text对应着Java的java.lang.String。

3.  ID规定化生成
    Hibernate中内置标识符生成器给表单ID自动生成提供了方便,但却不能自定义各种ID形式。开发过程中,有时需要特定的ID号来区分各种字典,例如字典1的ID号为1A,2A……,字典2的ID号为1B,2B……,当这些ID号存储在表单中时,可以方便开发人员在数据库中查找各表单存储各类字典数据的情况,方便调试,但使用Hibernate生成器就失去了这种灵活性。

    Hibernate的不足网上已有很多讨论,以上只是个人增加的几点体会。即使这样,Hibernate仍是一款优秀的持久层插件,只是“灵活”的背后隐藏着“复杂”,“方便”的背后隐藏着“不便”,如何取舍与平衡,还是看实际需要吧。

posted @ 2006-01-14 10:22 Flyingis 阅读(2709) | 评论 (5)编辑 收藏

GIS应用与开发中的网络模型

作者:Flyingis
   
    网络是用于实现资源的运输和信息的交流的相互连接的线性特征。网络模型是对现实世界网络的抽象。在模型中,网络由
Link Node Stop Center 组成。网络模型的典型的例子就是研究交通以及通过管线与隧道分析水、汽油、电力的流动。

网络组成要素简要说明

Link: 表示用于实现运输和交流的相互连接的线实体。如我们生活中的高速公路、铁路。

Node: Link 一定是在 Node 处相交,但相交的 Link 处不一定是 Node ,例如城市立交桥并没有相交,但是网络几何显示时却是相交的。

Stop: 在某个 Link 上经过的位置,如城市点、交通车站等。

Center: 指网络中一些离散位置,代表着现实世界里资源中心、购物中心,交通运输中心等。

常用的网络模型

1.        网络追踪

研究网络中资源和信息Link的流向。吉林石化爆炸造成松花江水域大面积污染,应用网络追踪即可分析从污染源开始,沿江流向下扩散的过程。网络追踪里涉及的一个重要概念是“连通性”,这决定了资源与信息在网络中的流动与走向。

2.        路径选择

路径选择即最佳Link路径选择,如经典的 Dijkstra 最短路径算法,在 GIS 应用中,物资输送、电力网络、行车路线等都涉及到这个问题,更为复杂的是,需要在这个过程中考虑许多影响流向通过的因素,例如交通中的红绿灯、堵塞情况,宽带网络中流量高峰期与低谷期。

3.        资源分配

反映显示世界网络中资源供需关系的模型。“供”一般位于 Center 位置,对空间中一个或多个点提供资源分配。这个分配范围有多大,分配距离有多远,分配的阻力有多强,是否有足够的物资信息等供分配,是这个模型需要研究的内容。

4.        空间相互作用和引力模型

用于理解和预测某点发生的活动和人、资源及信息的流动。通常情况下,两Stop点间距离越近,发生相互作用的可能性越大,但实际情况却不仅如此。

    在现在主流 GIS 应用软件中,例如 ArcGIS 已经提供了部分网络模型,如最常见的网络追踪模型,但模型的适用性和易用性并不完善,要满足实际应用要求,还需要在已有的模型基础上进行设计与二次开发。

Greenvalley.jpg

posted @ 2006-01-11 20:18 Flyingis 阅读(1678) | 评论 (1)编辑 收藏

软件整合--硬件整合--平台整合

    作者:Flyingis 

    “合久必分,分久必合”,不知道这句话最初是出自哪里?大概的意思应该是一个轮回的结束,代表的另一个轮回的开始。记得2004年考研的英语看图作文就是一位runner冲过终点线,在线的内侧写的是End,另一侧是Begin,这里面的含义很简单,在我们的生活中比比皆是。在IT行业,最近几年流行的是整合,软件整合、硬件整合与平台整合。

    软件整合
    Windows平台算是最典型的代表了,微软靠Windows整合了IE逐步吞噬了Netscape的市场,靠着Windows和Office / SQLServer / IIS / MediaPlayer最佳的兼容性,在各自的市场上都站稳了脚跟,有的甚至达到了一种垄断的局面,即使是最基本的记事本、游戏(扫雷、扑克牌之类的)、计算器等也成为了Windows使用者时常使用的软件。在开发平台上,微软也从来没有停止过脚步,最近的Visual Studio 2005 .Net让众多开发者望眼欲穿,其功能之强、操作之方便源于微软的强大实力,但最显著的特点就是整合了大多数软件开发中会使用到的应用工具,微软似乎像重新导演Windows当年的历史,靠整合不费吹灰之力打败那些倚着Windows(包括应用软件和开发软件)吃饭的小公司。
    除了微软之外,许多公司也进行着类似的整合,只是领域不同,应用范围不同,不管怎么样,微软总是会作为典型代表来分析讨论。Google公司是近年来IT领域的热点之一,也是让微软感觉不爽的公司之一,Google最近动作频频,特别是在搜索涉及的领域让微软防不胜防,虽然前段时间Bill Gates公开表示
公司的头号劲敌是IBM而不是Google,但Google让微软越来越紧张却是不争的事实,如果要故意挑他的语病,不是头号劲敌,那就是第二号或第三号吧,本来和IBM相比,Google还是欠些火候,但按照Google现在的发展趋势,谁也不敢小视。刚到2006年,Google就推出了一项新的下载服务:Google一体化软件服务--Google Pack。Google Pack是Google提供的面向Windows平台的一系列软件的集合,目的是方便快捷地为用户的电脑提供合适的基本软件。这又是一种软件整合。

    硬件整合
    硬件整合里面最耀眼的非Intel的迅驰莫属。Intel靠迅驰一代(三大件的整合CPU/芯片组/无线网卡)就在民用笔记本市场占领了大半的份额,受到了众多的好评,当然,也直接为Intel带来了丰厚的利润。迅驰二代Sonoma平台的虽然颇有争议,但凭借Intel强大的市场运作能力、产品推广速度和一代产品创造的良好根基,还是继承了迅驰一代的市场地位,并开始逐步过渡到迅驰三Napa。不论是哪一个时期的迅驰都吸引了全世界的眼球,Intel迅驰三Napa的发布也预示着Intel要将这个平台挖掘到底,甚至在台式机市场也要适时推出类似的硬件整合平台,将整合带来的利润最大化。家庭娱乐平台Intel VIIV已经推出,虽然其经济效应和规模效应都还不如迅驰,但总是让人充满期待。

    平台整合
    信息专家们和分析师们预言将来的数据中心将是多种操作系统共存的情况,包括Windows和各种各样的Unix变体。除此之外,还应该包括多种数据库、应用软件之间的无缝集成,这对各个系统的可靠性、弹性、可扩展性和交互性提出了更高的要求。.NET和J2EE的互用性问题非常重要,是因为大多数企业都在使用其中之一或同时使用这两种平台来开发程序,用Web Services来整合.NET和J2EE是不同软件开发平台之间的整合,它为两种平台之间的整合提供了一种解决方案。数据管理与应用集成解决方案供应商Sybase与Linux领域的Turbolinux共同打造的企业级数据管理平台,即整合了双方各自在数据库、操作系统平台的领先优势,将各自的旗舰产品捆绑成一个极具竞争力的企业级数据管理平台。这是数据库和应用软件之间的整合。因此,平台整合代表了应用性能的增强,开发集成的便利与应用开销成本的最小化,这也是IT领域的发展趋势之一。

    软件整合--硬件整合--平台整合代表了未来,至少未来这些年IT领域的发展方向,当然也代表行业垄断的趋势。除去政治上的各种因素,这些整合对于技术应用与发展来说,无疑是一种好的趋势。“分久必合,合久必分”,只是,后面的一句话会像前面一句一样,在今后的某一段时期,在IT行业繁荣起来吗?可能吗?

posted @ 2006-01-09 13:30 Flyingis 阅读(1159) | 评论 (0)编辑 收藏

Java I/O中的对象序列化

作者:Flyingis

      Java对象序列化将那些实现了Serializable接口的对象转换成一个字节序列,并能够以后将这个字节序列完全恢复为原来的对象。利用对象的序列化,可以实现轻量级持久性,这意味着一个对象的生存周期并不取决于程序是否正在执行,它可以生存于程序的调用之间。通过将一个序列化对象写入磁盘,然后在重新调用程序时恢复该对象,就能够实现持久性的效果。JDOHibernate等中间件为我们提供了更规范、完善的持久化机制,这里所述只是最基本的基于文件I/O的持久化。

对象序列化主要是为了支持两种主要的特性,一是Java远程方法调用(RMI),另外一个是序列化Java Beans

1.        实现了Serializable接口的对象的序列化

要序列化一个对象,首先要创建OutputStream对象,然后将其封装在一个ObjectOutputStream对象内。此时,调用writeObject()方法将对象序列化并发送给OutputStream。在反序列化时,需要将一个InputStream封装在ObjectInputStream内,然后调用readObject(),得到的结果是一个Object对象,需要进行转型得到最后所需的对象。需要注意的是,在对一个Serializable对象进行反序列化的过程中,没有调用任何构造器,包括缺省的构造器,整个对象都是通过从InputStream中取得数据恢复过来的。对象序列化是面向字节的,因此采用InputStreamOutputStream层次结构。

2.        实现了Externalizable接口的对象的序列化

Externalizable接口继承了Serializable接口,同时添加了writeExternal()readExternal(),它们在序列化和反序列化过程中会被自动调用。出于安全的考虑,可以将需要序列化的对象在上述方法中显式处理,否则不用在上述两个方法内考虑。注意,对于实现了Serializable接口的对象,对象完全以它存储的二进制位为基础来构造,不调用构造器。而对于一个Externalizable对象,所有普通的缺省构造器都会被调用,然后调用readExternal()

3.        transient关键字

在某些情况下,有些特定的子对象不希望Java序列化机制自动保存与恢复,即使对象中的这些信息是private的,经过序列化处理,就可以通过读取文件或者拦截网络传输的方式来访问到它。实现了Externalizable接口的对象的writeExternal()方法可以对需要的对象进行显式的序列化,但是如果我们操作的是一个实现了Serializable接口的对象,就只能用transient关键字逐个字段的关闭序列化,只需要在字段定义前加上该关键字即可。

4.        实现了Serializable接口的同时,提供两个方法

private void writeObject(ObjectOutputStream stream) throws IOException

private void readObject(ObjectInputStream stream)

throws IOException, ClassNotFoundException

这种方法使用起来比较混乱,仅仅提供了这样的一种功能,绝大多数情况下,使用前面三种方法就能满足需求。

posted @ 2006-01-08 13:13 Flyingis 阅读(2609) | 评论 (5)编辑 收藏

文件加锁基础

作者:Flyingis

    文件加锁是
JDK1.4引入的一种机制,它允许我们同步访问某个作为共享资源的文件。竞争同一文件的两个线程可能在不同的Java虚拟机上,或者一个是Java线程,另一个是操作系统中的某个本地线程。文件锁对其他的操作系统进程是可见的,因为Java的文件加锁直接映射到了本地操作系统的加锁工具。

通过对FileChannel调用tryLock()lock(),就可以获得整个文件的FileLock。特殊的是,SocketChannel/DatagramChannel/ServerSocketChannel不需要加锁,因为它们是从单进程实体继承而来,我们通常不在两个进程之间共享网络的socket

tryLock()是非阻塞式的,它设法获取锁,但如果不能获得,例如因为其他一些进程已经持有相同的锁,而且不共享时,它将直接从方法调用返回。

lock()是阻塞式的,它要阻塞进程直到锁可以获得,或调用lock()的线程中断,或调用lock()的通道关闭。

对独占锁和共享锁的支持必须由底层的操作系统提供。锁的类型可以通过FileLock.isShared()进行查询。另外,我们不能获取缓冲器上的锁,只能是通道上的。

文件加锁的实际应用之一:文件映射通常应用于大型的文件,我们可能需要对巨大的文件进行部分加锁,以便其他的进程可以修改文件中未被加锁的部分,数据库就是如此,使得多用户可以访问到未加锁的部分数据。其他的应用还知之甚少。

posted @ 2006-01-07 13:50 Flyingis 阅读(3899) | 评论 (2)编辑 收藏

2006年的 Java IDE

    作者: Flyingis

    随着Eclipse影响逐步扩大,IDE市场热闹非凡,不论是老牌Borland的JBuilder还是NetBeans,还有Sun免费的Java Studio Creator似乎都想在这个市场上拼出一条血路,记住!不要忘了可爱的IntelliJ!

    看着微软强大的Visual Studio系列产品,Java始终都想拥有一款可以相媲美的IDE,现在开源的Eclipse做的算是不错了,拥有丰富的插件支持,但Eclipse经常莫名其妙crashes估计谁的碰到过,在以前JBuilder7/8年代,中文光标的问题也需要修改一个文件才能解决(现在没有使用,不知道是否仍然存在),世上总是没有完美。也许最原始的EditPlus+JDK才是一种优雅简单的解决方案。下面,看看这些Java IDE新闻大杂烩吧,看看2006年的Java IDE会拼出什么火花。

    NetBeans VS Eclipse,新一轮的争端
    Matisse和NetBeans 弄潮下一波GUI设计
    Eclipse 3.2 M4 加入Swing 和IntelliJ IDEA 新功能
    凤凰浴火:JBuilder 2006新功能赏析

posted @ 2006-01-05 20:51 Flyingis 阅读(2334) | 评论 (3)编辑 收藏

Java I/O中的数据编码转换

作者:Flyingis

      JDK1.4
开始便引入了java.nio.*包,其目的在于提高I/O的速度,这是因为该类库使用的结构更接近于操作系统执行I/O的方式,即通过通道和缓冲器来读写数据。在实际应用中,和我们直接交互的是缓冲器,然后把缓冲器派送到通道,通道要么从缓冲器获得数据,要么向缓冲器发送数据。


    在基于
Java的各种开发中,字符编码是常见的问题之一,在最基本的Java I/O中也存在这种问题。新的Java I/O通过通道和缓冲器来读写数据,缓冲器容纳的是普通的字节,为了把它们转换成字符,我们要么在输入的时候对其进行编码,要么在从缓冲器输出时对它们进行解码。


import java.io.*;

import java.nio.*;

import java.nio.channels.*;

import java.nio.charset.*;

public class ByteToCharacter {

  private static final int SIZE = 1024;

  public static void main(String[] args) throws Exception {

FileChannel fc = new FileOutputStream(“Output.txt”).getChannel();

ByteBuffer buffer = ByteBuffer.allocate(SIZE);

/**

* 在输入的时候进行编码方式一

*/

fc.write(ByteBuffer.wrap(“Good holiday!”.getBytes(“UTF-16BE”)));  // UTF-16BE可以更换为其他编码方式

fc.close();

fc = new FileInputStream(“Output.txt”).getChannel();

fc.read(buffer);

buffer.flip();  //准备从缓冲区读取已经写入的数据

System.out.println(buffer.asCharBuffer());

/**

* 在输入的时候进行编码方式二

* 通过asCharBuffer()方法直接以char形式将字符写入

*/

fc = new FileOutputStream(“Output.txt”).getChannel();

buffer.clear();

buffer.asCharBuffer.put(“Good holiday has passed!”);

fc.write(buffer);

fc.close();

fc = new FileInputStream(“Output.txt”).getChannel();

buffer.clear();

fc.read(buffer);

buffer.flip();

System.out.println(buffer.asCharBuffer());

/**

* 从缓冲器输出时进行编码

*/

fc = new FileOutputStream(“Output.txt”).getChannel();

fc.write(ByteBuffer.wrap(“Once again!”.getBytes()));

fc.close();

fc = new FileInputStream(“Output.txt”).getChannel();

buffer.clear();

fc.read(buffer);

buffer.flip();

String encode = System.getProperty(“file.encoding”);  // 平台缺省字符集,更加通用的方法,跨平台特性的体现之一

System.out.println(Charset.forName(encode).decode(buffer));

}

}


   
在上述代码中,如果不对从缓冲器写入的数据进行正确编码,那么当再次通过缓冲器读取这些数据时,将不能显示任何所需要的数据。


    JDK
中的java.nio.charset.Charset类提供了把数据编码成多种不同类型的字符集的工具,满足在各种应用中的编码需求。

posted @ 2006-01-03 14:02 Flyingis 阅读(1418) | 评论 (0)编辑 收藏

Java I/O中的设计模式

作者:Flyingis

    任何程序语言的
I/O设计都是一项具有挑战的任务,因为数据的传输存在多种可能,这些可能不仅存在于数据发送端和接收端(文件、网络链接等),还存在于这些数据的多种存在方式,例如缓冲区数据、顺序存取数据、字符数据、字节数据等等。

JavaI/O使用“流”这个抽象的概念,它屏蔽了实际的I/O设备中处理数据的细节。在实际的应用中,我们很少使用单一的类来创建流对象,而是通过多个对象来提供所需要的I/O功能。Java1.01.11.4I/O类库作了多次重大修改,具体的可以参考相关的书籍或Sun官方网站。这里是从模式的角度来分析JavaI/O类库的设计。

Strategy设计模式

将会发生变化的代码封装在单独的类(Strategy对象)中,供其他保持不变的类使用,实现某种算法或应用,这是Strategy设计模式的一般思想。在Java I/O中,一个典型的应用是File类,它可以代表一个特定文件的名称,也可以代表一个目录下一组文件的名称。当我们要查询显示一个目录下特定文件类型的所有文件对象信息时,就需要将这个目录下的文件过滤,找到所需要的对象。

import java.io.*;

import java.util.*;

import java.util.regex.*;

 

public class AlphabeticComparator implements Comparator {

public int compare(Object o1, Object o2) {

  String s1 = (String)o1;

  String s2 = (String)o2;

  return s1.toLowerCase().compareTo(s2.toLowerCase());  //比较时不考虑大小写

}

}

 

public class FruitList {

  public static FilenameFilter filter(final String regex) {

return new FilenameFilter() {

  private Pattern pattern = Pattern.compile(regex);

  public boolean accept(File dir, String name) {

    return pattern.matcher(new File(name).getName()).matches();

}

};

}

public static void main(String[] args) {

  File path = new File(“.”);

  String[] list;

  if (args.length == 0)

    list = path.list();  //搜索出该目录下所有类型的文件

else

  list = path.list(filter(args[0]));  //搜索出该目录下指定类型的文件

Arrays.sort(list, new AlphabeticComparator());

for (int i = 0; i < list.length; i++)

  System.out.println(list[i]);

}

}在上述代码中,有两个地方使用了Strategy设计模式,一个是AlphabeticComparator类,用来在忽略字符串大小写的情况下提供排序的规则,另一个就是FilenameFilter接口,使用了匿名内部类的设计,然后将其中实现的accept()规则提供给File类的list方法使用。这里是用来判断正则表达式regex是否和文件名匹配,当运行程序在命令操作符中输入“E.*\.java”时,搜索到的是该目录下所有.java文件。

File类除了上述用法外,还可以创建或删除目录,查看文件的信息,包括文件大小、最后修改日期,读写状态等,具体的可以参考JDK文档。

Decorator设计模式

http://www.j2eesp.com上有对Decorator设计模式的定义:动态给一个对象添加一些额外的职责,就像在墙上刷油漆。使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。Decorator模式规定所有封装于初始对象内部的对象具有相同的接口,这使得该模式的应用具有透明性。

Java I/O设计中,Decorator模式主要体现在filter类的设计上,抽象类filter是所有Decorator模式类的基类。但是Decorator模式同样存在缺点:在编写程序时,它在给开发人员提供了灵活性的同时,增加了代码的复杂性,造成了Java I/O类操作不便,因为很多I/O设计中都需要应用Decorator模式,增加一些类来完成该设计。

例如在Java 1.0中,FilterInputStreamInputStream中读取数据,FilterOutPutStreamOutputStream中写入数据,在Java 1.1中,相应的有FilterReaderFilterWriter(抽象类,没有子类)用于Decorator模式设计。举个简单的例子:

import java.io.*;

public class DecoratorDemo {

  public static void main(String[] args) {

BufferedReader in = new BufferedReader(new FileReader(“FruitList.java”));

String s = new String();

while ((s = in.readLine()) != null)

  System.out.println(s);

in.close();

}

}

    BufferedReaderFileReader完成了Decorate模式设计,这两个类可以更换为其他具有相同功用的类(在Thinking in Java中称为“修饰器”类)来组合完成特定的任务,正如上文所述,这给开发者提供了多种组合方式,同时也相对的增加了复杂度。

    最后,祝blogjava所有成员和Java、开源爱好者元旦快乐!幸福安康!

posted @ 2005-12-30 21:47 Flyingis 阅读(2565) | 评论 (4)编辑 收藏

测试你电脑功率的大小

    这个网站可以测试你电脑的大概功率,当然,这个功率是所有部件都处于高负荷运行时的功率,可以作为参考。另外,笔记本的部件不在测试之列,如果台式机过于先进(例如显卡是Nvidia Geforce 7800 GTX)也不能找到相关的部件选项。
    测试链接:http://www.jscustompcs.com/power_supply/

    进入网站后,需要选择电脑的CPU类型是AMD还是Intel,或者你要测试的是服务器,进入页面后再选择电脑的各个部件即可。有空可以看看,纯属无聊消遣!

TestYourComputer.gif

posted @ 2005-12-28 15:38 Flyingis 阅读(5323) | 评论 (3)编辑 收藏

SOA介绍--什么是SOA?[转载]

版权声明:本文可以自由转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
作者:Raghu R. Kodali  翻译:
tetsu(译者的Blog:http://blog.matrix.org.cn/page/tetsu)
原文:
http://www.javaworld.com/javaworld/jw-06-2005/jw-0613-soa.html
中文:http://www.matrix.org.cn/resource/article/44/44070_SOA.html
关键字:SOA

摘要
在最近的软件发展中,面向服务架构(SOA, service-oriented architecture)成为了时下的热门话题。这篇文章将向大家介绍SOA, 讨论企业为什么需要SOA,什么是SOA, 从核心,平台,服务品质3个层面来解释SOA的基础构成。
By Raghu R. Kodali



对于面向同步和异步应用的,基于请求/响应模式的分布式计算来说,SOA是一场革命。一个应用程序的业务逻辑(business logic)或某些单独的功能被模块化并作为服务呈现给消费者或客户端。这些服务的关键是他们的松耦合特性。例如,服务的接口和实现相独立。应用开发人员或者系统集成者可以通过组合一个或多个服务来构建应用,而无须理解服务的底层实现。举例来说,一个服务可以用.NET或J2EE来实现,而使用该服务的应用程序可以在不同的平台之上,使用的语言也可以不同。

SOA有以下特性
        SOA服务具有平台独立的自我描述XML文档。Web服务描述语言(WSDL, Web Services Description Language)是用于描述服务的标准语言。
        SOA 服务用消息进行通信,该消息通常使用XML Schema来定义(也叫做XSD, XML Schema Definition)。消费者和提供者或消费者和服务之间的通信多见于不知道提供者的环境中。服务间的通讯也可以看作企业内部处理的关键商业文档。
         在一个企业内部,SOA服务通过一个扮演目录列表(directory listing)角色的登记处(Registry)来进行维护。应用程序在登记处(Registry)寻找并调用某项服务。统一描述,定义和集成 (UDDI, Universal Description, Definition, and Integration)是服务登记的标准。
         每项SOA服务都有一个与之相关的服务品质(QoS, quality of service)。QoS的一些关键元素有安全需求(例如认证和授权),可靠通信(译注:可靠消息是指,确保消息“仅且仅仅”发送一次,从而过滤重复信息。),以及谁能调用服务的策略。

为什么选择SOA?

不同种类的操作系统,应用软件,系统软件和应用基础结构(application infrastructure)相互交织,这便是IT企业的现状。一些现存的应用程序被用来处理当前的业务流程(business processes),因此从头建立一个新的基础环境是不可能的。企业应该能对业务的变化做出快速的反应,利用对现有的应用程序和应用基础结构(application infrastructure)的投资来解决新的业务需求,为客户,商业伙伴以及供应商提供新的互动渠道,并呈现一个可以支持有机业务(organic business)的构架。SOA凭借其松耦合的特性,使得企业可以按照模块化的方式来添加新服务或更新现有服务,以解决新的业务需要,提供选择从而可以通过不同的渠道提供服务,并可以把企业现有的或已有的应用作为服务, 从而保护了现有的IT基础建设投资。

如图1的例子所示,一个使用SOA的企业,可以使用一组现有的应用来创建一个供应链复合应用(supply chain composite application),这些现有的应用通过标准接口来提供功能。

image
Figure 1. Supply chain application. Click on thumbnail to view full-sized image.         


服务架构

为了实现SOA,企业需要一个服务架构,图2显示了一个例子:

image
Figure 2. A sample service architecture. Click on thumbnail to view full-sized image.        

在图2中, 服务消费者(service consumer)可以通过发送消息来调用服务。这些消息由一个服务总线(service bus)转换后发送给适当的服务实现。这种服务架构可以提供一个业务规则引擎(business rules engine),该引擎容许业务规则被合并在一个服务里或多个服务里。这种架构也提供了一个服务管理基础(service management infrastructure),用来管理服务,类似审核,列表(billing),日志等功能。此外,该架构给企业提供了灵活的业务流程,更好地处理控制请求(regulatory requirement),例如Sarbanes Oxley(SOX),并且可以在不影响其他服务的情况下更改某项服务。

SOA基础结构

要运行,管理SOA应用程序,企业需要SOA基础,这是SOA平台的一个部分。SOA基础必须支持所有的相关标准,和需要的运行时容器。图3所示的是一个典型的SOA基础结构。接下来的章节将逐一讨论该结构的每个部分。

image
Figure 3. A typical SOA infrastructure. Click on thumbnail to view full-sized image.         

SOAP, WSDL, UDDI
WSDL, UDDI和SOAP是SOA基础的基础部件。WSDL用来描述服务;UDDI用来注册和查找服务;而SOAP,作为传输层,用来在消费者和服务提供者之间传送消息。SOAP是Web服务的默认机制,其他的技术为可以服务实现其他类型的绑定。一个消费者可以在UDDI注册表(registry)查找服务,取得服务的WSDL描述,然后通过SOAP来调用服务。

WS-I Basic Profile
WS-I Basic Profile,由Web服务互用性组织(Web Services Interoperability Organization)提供,是SOA服务测试与互用性所需要的核心构件。服务提供者可以使用Basic Profile测试程序来测试服务在不同平台和技术上的互用性。

J2EE 和 .Net
尽管J2EE和.NET平台是开发SOA应用程序常用的平台,但SOA不仅限于此。像J2EE这类平台,不仅为开发者自然而然地参与到SOA中来提供了一个平台,还通过他们内在的特性,将可扩展性,可靠性,可用性以及性能引入了SOA世界。新的规范,例如 JAXB(Java API for XML Binding),用于将XML文档定位到Java类;JAXR(Java API for XML Registry)用来规范对UDDI注册表(registry)的操作;XML-RPC(Java API for XML-based Remote Procedure Call)在J2EE1.4中用来调用远程服务,这使得开发和部署可移植于标准J2EE容器的Web服务变得容易,与此同时,实现了跨平台(如.NET)的服务互用。

服务品质
在企业中,关键任务系统(mission-critical system,译注:关键任务系统是指如果一个系统的可靠性对于一个组织是至关重要的,那么该系统就是该企业的关键任务系统。比如,电话系统对于一个电话促销企业来说就是关键任务系统,而文字处理系统就不那么关键了。)用来解决高级需求,例如安全性,可靠性,事物。当一个企业开始采用服务架构作为工具来进行开发和部署应用的时候,基本的Web服务规范,像WSDL,SOAP,以及UDDI就不能满足这些高级需求。正如前面所提到的,这些需求也称作服务品质(QoS,quality of services)。与QoS相关的众多规范已经由一些标准化组织(standards bodies)提出,像W3C(World Wide Web Consortium)和OASIS(the Organization for the Advancement of Structured Information Standards)。下面的部分将会讨论一些QoS服务和相关标准。

安全
Web服务安全规范用来保证消息的安全性。该规范主要包括认证交换, 消息完整性和消息保密。该规范吸引人的地方在于它借助现有的安全标准,例如,SAML(as Security Assertion Markup Language)来实现web服务消息的安全。OASIS正致力于Web服务安全规范的制定。

可靠
在典型的SOA 环境中,服务消费者和服务提供者之间会有几种不同的文档在进行交换。具有诸如“仅且仅仅传送一次”( once-and-only-once delivery),“最多传送一次”( at-most-once delivery),“重复消息过滤”(duplicate message elimination),“保证消息传送”(guaranteed message delivery)等特性消息的发送和确认,在关键任务系统(mission-critical systems)中变得十分重要。WS-Reliability 和 WS-ReliableMessaging是两个用来解决此类问题的标准。这些标准现在都由OASIS负责。

策略
服务提供者有时候会要求服务消费者与某种策略通信。比如,服务提供商可能会要求消费者提供Kerberos安全标示,才能取得某项服务。这些要求被定义为策略断言(policy assertions)。一项策略可能会包含多个断言。WS-Policy用来标准化服务消费者和服务提供者之间的策略通信。

控制
当企业着手于服务架构时,服务可以用来整合数据仓库(silos of data),应用程序,以及组件。整合应用意味着例如异步通信,并行处理,数据转换,以及校正等进程请求必须被标准化。在SOA中,进程是使用一组离散的服务创建的。BPEL4WS 或者 WSBPEL(Web Service Business Process Execution Language)是用来控制这些服务的语言。WSBPEL目前也由OASIS负责。

管理
随着企业服务的增长,所使用的服务和业务进程的数量也随之增加,一个用来让系统管理员管理所有运行在多相环境下的服务的管理系统就显得尤为重要。WSDM(Web Services for Distributed Management)规定了任何根据WSDM实现的服务都可以由一个WSDM适应(WSDM-compliant)的管理方案来管理。

其它的qos特性,比如合作方之間的溝通和通訊,多個服務之間的事務處理,都在WS-Coordination 和 WS-Transaction 標準中描述, 這些都是OASIS 的工作.

SOA 不是Web服务
在理解SOA和Web服务的关系上,经常发生混淆。根据2003年4月的Gartner报道,Yefim V. Natis就这个问题是这样解释的:“Web服务是技术规范,而SOA是设计原则。特别是Web服务中的WSDL,是一个SOA配套的接口定义标准:这是 Web服务和SOA的根本联系。”从本质上来说,SOA是一种架构模式,而Web服务是利用一组标准实现的服务。Web服务是实现SOA的方式之一。用 Web服务来实现SOA的好处是你可以实现一个中立平台,来获得服务,而且随着越来越多的软件商支持越来越多的Web服务规范,你会取得更好的通用性。

SOA的优势

SOA 的概念并非什么新东西,SOA不同于现有的分布式技术之处在于大多数软件商接受它并有可以实现SOA的平台或应用程序。SOA伴随着无处不在的标准,为企业的现有资产或投资带来了更好的重用性。SOA能够在最新的和现有的应用之上创建应用;SOA能够使客户或服务消费者免予服务实现的改变所带来的影响; SOA能够升级单个服务或服务消费者而无需重写整个应用,也无需保留已经不再适用于新需求的现有系统。总而言之,SOA以借助现有的应用来组合产生新服务的敏捷方式,提供给企业更好的灵活性来构建应用程序和业务流程。

About the author
Raghu R. Kodali is consulting product manager and SOA evangelist for Oracle Application Server. Kodali leads next-generation SOA initiatives and J2EE feature sets for Oracle Application Server, with particular expertise in EJB, J2EE deployment, Web services, and BPEL. Prior to product management, Kodali held presales and technical marketing positions in Oracle Asia-Pacific, based in Singapore. Prior to Oracle, he worked as software developer with National Computer Systems, Singapore. He holds a master's degree in computer science and is a frequent speaker at technology conferences. Kodali maintains an active blog at Loosely Coupled Corner

资源
·
Java开发者社区:http://www.matrix.org.cn
·javaworld.com:javaworld.com
WS-I: http://www.ws-i.org
JAXB: http://www.java.sun.com/xml/jaxb
JAXR: http://java.sun.com/xml/jaxr
OASIS: http://www.oasis-open.org/home/index.php
SAML: http://www.oasis-open.org/specs/index.php#samlv1.0
SOAP: http://www.w3.org/TR/soap/
SOX: http://www.sarbanes-oxley.com/
UDDI: http://www.uddi.org/specification.html
W3C: http://www.w3.org/2002/ws/
WSDL: http://www.w3.org/TR/wsdl
WSBPEL: http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wsbpel
WS-Reliability: http://www.oasis-open.org/specs/index.php#wsrv1.1
WS-ReliableMessaging: http://xml.coverpages.org/WS-ReliableMessaging200502.pdf
Web Services Security: http://www.oasis-open.org/specs/index.php#wssv1.0
WS-I Basic Profile:http://www.ws-i.org/deliverables/workinggroup.aspx?wg=basicprofile
WSDM: http://www.oasis-open.org/committees/tc_home.php
XSD: http://www.w3.org/XML/Schema
Gartner: http://www.gartner.com/Init
To read about BEA's recent product offering in the SOA space, read "BEA's Patrick Discusses Project Free Flow," Paul Krill, InfoWorld (JavaWorld, June 2005): http://www.javaworld.com/javaworld/jw-06-2005/jw-0613-iw-bea.html
For more on SOA, read "Event-Driven Services in SOA," Jeff Hanson (JavaWorld, January 2005): http://www.javaworld.com/javaworld/jw-01-2005/jw-0131-soa.html
For more articles on Web services, browse the Java and Web Services section of JavaWorld's Topical Index: http://www.javaworld.com/channel_content/jw-webserv-index.shtml
For more articles on enterprise development, browse the Enterprise Java section of JavaWorld's Topical Index:
http://www.javaworld.com/channel_content/jw-enterprise-index.shtml

posted @ 2005-12-28 11:17 Flyingis 阅读(1613) | 评论 (0)编辑 收藏

Java容器分析--Map

    作者:Flyingis

标准的
Java类库中包含了几种类型的Map,它们都拥有同样的基本接口Map,但是行为特性各不相同,主要表现在效率、键值对的保存、元素呈现次序、对象的保存周期和判定键是否等价的策略等方面。

1.Map的功能方法

Map(interface): 维护labelvalue的关联性,使得可以通过label查找value

HashMap: Map基于散列表的实现,取代了Hashtable。插入和查询label/value的开销是固定的,并且可以通过构造器设置容量和负载因子,以调整容器的性能。

LinkedHashMap: HashMap的基础上做了一些改进,在迭代遍历它时,取得label/value的顺序是其插入的次序,或者是最近最少使用(LRU)的次序,速度上比HashMap要慢一点,但在迭代访问时速度会更快,主要原因是它使用了链表维护内部次序。

TreeMap: 查看labellabel/value时,元素会被排序,其次序由ComparableComparator决定,因此查询所得到的结果是经过排序的。另外,它是唯一带有subMap()方法的Map具体类,即返回一个子树。它也是SortedMap接口的唯一实现,subMap()方法也是从该接口继承的。

WeakHashMap: Weak Key映射,允许释放映射所指向的对象。当映射之外没有引用指向某个label时,此label可以被垃圾收集器回收。

IdentityHashMap: 使用==代替equals()label进行比较的散列映射。

2.hashCode()

         当使用标准库中的类Integer作为HashMaplabel时,程序能够正常运行,但是使用自己创建的类作为HashMaplabel时,通常犯一个错误。

         HashMap中通过label查找value时,实际上是计算label对象地址的散列码来确定value的。一般情况下,我们是使用基类Object的方法hashCode()来生成散列码,它默认是使用对象的地址来计算的,因此由第一个对象new Apple(5)和第二个对象new Apple(5)生成的散列码是不同的,不能完成正确的查找。通常,我们可以编写自己的hashCode()方法来覆盖基类的原始方法,但与此同时,我们必须同时实现equals()方法来判断当前的label是否与表中存在的label相同。正确的equals()方法满足五个条件:

(1)     自反性。对于任意的xx.equals(x)一定返回true

(2)     对称性。对于任意的xy,如果y.equals(x)返回true,则x.equals(y)也返回true

(3)     传递性。对于任意的xyz,如果有x.equals(y)返回truey.equals(z)返回true,则x.equals(z)一定返回true

(4)     一致性。对于任意的xy,如果对象中用于等价比较的信息没有改变,那么无论调用x.equals(y)多少次,返回的结果应该保持一致,要么一直是true,要么一直是false

(5)     对任何不是nullxx.equals(null)一定返回false

equals()比较的是对象的地址,如果要使用自己的类作为HashMaplabel,必须同时重载hashCode()equals()方法。

使用散列的目的:想要使用一个对象来查找另一个对象。使用TreeSetTreeMap也能实现此目的。另外,还可以自己实现一个Map,此时,必须提供Map.entrySet()方法来生成Map.Entry对象的Set

使用散列的价值:速度,散列使得查询可以快速进行。散列将label保存载数组中方便快速查询,因为存储一组元素最快的数据结构是数组,用它来表示label的信息(后面有信息的描述),而不是label本身。通过label对象计算得到一个数字,作为数组的下标,这个数字就是散列码(即前面所述的信息)。该散列码具体是通过定义在基类Object中,可能由程序员自定义的类覆盖的hashCode()方法,即散列函数生成。为了解决数组容量带来的限制,可以使不同的label生成相同的下标,保存在一个链表list中,每一个链表就是数组的一个元素。查询label时就可以通过对list中的信息进行查找,当散列函数比较好,数组的每个位置中的list长度较短,则可以快速查找到数组元素list中的某个位置,提高了整体速度。

散列表中的slot通常称为bucket,为了使散列分步均匀,bucket的值一般取质数。但事实证明,质数实际上并不是散列bucket的理想容量,近来Java散列实现都使用2的幂,具体如何验证以后再续。

3.HashMap的性能因子

容量(capacity): 散列表中bucket的数量。

初始化容量(initial capacity): 创建散列表时bucket的数量。可以在构造方法中指定HashMapHashSet的初始化容量。

尺寸(size): 散列表中记录的数量。(数组的元素个数,非list中元素总和)

负载因子(load factor): 尺寸/容量。负载因子为0,表示空的散列表,0.5表示半满的散列表。轻负载的散列表具有冲突少,适宜插入与查询的特点,但是使用迭代器遍历会比较慢。较高的负载会减少所需空间大小。当负载达到指定值时,容器会自动成倍地增加容量,并将原有的对象重新分配,存入新的bucket中,这个过程称为“重散列”。

4.重写hashCode()的关键

(1)     对同一个对象调用hashCode()都应该生成同样的值。

(2)     hashCode()方法不要依赖于对象中易变的数据,当数据发生变化时,hashCode()就会生成一个不同的散列码,即产生了一个不同的label

(3)     hashCode()不应依赖于具有唯一性的对象信息,例如对象地址。

(4)     散列码应该更关心速度,而不是唯一性,因为散列码不必是唯一的。

(5)     好的hashCode()应该产生分步均匀的散列码。在Effective Java(Addison-Wesley 2001)中,Joshua BlochhashCode()给出了设计指导,可以参考。

编写正确高效的hashCode()equals()可以参考ApacheJakarta Commons项目中的工具。

其它相关内容:
Java容器分析--数组
Java容器分析--List和Set

posted @ 2005-12-27 10:07 Flyingis 阅读(4316) | 评论 (3)编辑 收藏

仅列出标题
共6页: 上一页 1 2 3 4 5 6 下一页