Shao Fan

关于JAVA与软件工程
posts - 31, comments - 71, trackbacks - 0, articles - 4
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2006年3月20日

目前开发人员对系统开发的一个共识是使用三层架构,分为表示层,业务层,和持久层。而这三层之间的依赖关系如何?比较常见的一种看法是

表示层 --> 业务层 --> 持久层

这表明了层与层之间的调用关系,表示层通过调用业务层来完成任务,而业务层则调用持久层。从另一个角度来看,一种依赖关系是

表示层 --> 领域模型(Domain Model) <-- 持久层

表示层和持久层都应该理解(recognize)领域模型。而领域模型则是业务层的一部分。业务层正是系统的价值所在。虽说表示和持久也很重要,在某些系统中可以说是很关键,但是它们的最终目的都是为业务服务,所以业务层应该是系统的核心

基于以上的认识,在系统设计的时应首先分析需求得到领域模型,找出系统中的实体、对象(静态的一面),并明确大致的业务流程(动态的一面)。 而另两层应尽最大努力为业务层服务,且尽量减少业务层受另两层的限制。


各层的职责:

表示层:负责显示信息,及从系统外部得到输入。表示层的设计决定系统界面的可用性,及信息输入和展示的可靠性。表示层只知道如何展示信息,及收集用户输入,并不知道该如何对这些输入进行处理来完成业务。

业务层:完成业务逻辑。业务层设计决定客户价值是否能够得到实现。这是系统的关键。外在的表现是功能性。业务层设计和实现的失误表现在用户端即功能缺失,功能不可靠等。如果需要对业务层的业务规则进行解耦,则可以使用规则引擎如Drools,把业务规则分离出来。但分离后的业务规则仍属于业务层。业务层知道如何对用户输入进行处理,能够应用业务规则完成用户所需的业务,但它不知道数据如何读取和保存。

持久层:负责用户信息的持久化。持久层的失误表现在外即数据处理(储存,展示等)不可靠。持久层完全不知道业务,只专注于数据存储和读取。所谓持久化并不一定是指数据库,任何方式的持久化(通过文件,网络的持久化等)都应由持久层完成。

各层的设计都会直接影响系统性能。

三层的体积大小和复杂度在不同的系统中可能会有很大的不同。比如说GOOGLE的搜索引擎,它的界面很简单,可以想像表示层是比较容易实现的,而它的业务层,关系到处理关键字,分析搜索结果,决定排名等,而持久层则要负责处理超大量的数据。业务层和持久层则相当复杂。而有的系统持久层会很小,比如杀毒软件,媒体播放软件等。业务层小而另两层大的例子暂时还没有想到:)


posted @ 2007-09-08 19:45 shaofan 阅读(5114) | 评论 (2)编辑 收藏

help是一个内置函数,所谓内置函数,就是在Python中被自动加载的函数,任何时候都可以用。参数分两种:

  • 如果传一个字符串做参数的话,它会自动搜索以这个字符串命名的模块,方法,等。
  • 如果传入的是一个对象,就会显示这个对象的类型的帮助。

比如输入help(’print’),它就会寻找以’print’为名的模块,类,等,找不到就会看到提示信息。而print在python里是一个保留字,和pass,return同等,而非对象,所以help(print)也会出错((kkkkkkk))。

举个例子:

1 help(’sys’) #会列出sys模块的帮助
2 = [1,2,3]
3 help(a) #会显示list的帮助
4 help(a.append) #会显示list的append方法的帮助

python安装自带的library reference,2.1节是关于内置函数的。

Reference Manual的6.6节可以找到关于print的东东。

posted @ 2007-06-05 06:28 shaofan 阅读(2757) | 评论 (0)编辑 收藏

Struts2默认theme是xhtml,它用表格来对表单中的控件进行排版。它也提供一个客户端的js验证功能,但是它的js脚本却有些问题,在某些情况下,前次验证的提示信息无法被清除,提示信息会不断的累积显示在屏幕上。而按照设计,每次提交表单时应只显示每次验证的出错信息。

它的客户端验证的流程大概是这样,用户提交表单时,对各个控件的输入按预先设置的规则进行验证,如果有问题,则清除表单里原有的出错提示信息,并写入新的提示。其设计的功能是把出错信息写表格里出错控件的上方,以便用户看得更加清楚。问题就出在其用来清除原出错信息的函数,其代码是这样的(在struts.jar的template/xhtml目录下可以找到):

 1 function clearErrorMessages(form) {
 2 
 3     var table = form.childNodes[1];
 4     iftypeof table == "undefined" ) {
 5         table = form.childNodes[0];
 6     }
 7 
 8     // clear out any rows with an "errorFor" attribute
 9     var rows = table.rows;
10     var rowsToDelete = new Array();
11     if (rows == null){
12         return;
13     }
14 
15     for(var i = 0; i < rows.length; i++) {
16         var r = rows[i];
17         if (r.getAttribute("errorFor")) {
18             rowsToDelete.push(r);
19         }
20     }
21 
22     // now delete the rows
23     for (var i = 0; i < rowsToDelete.length; i++) {
24         var r = rowsToDelete[i];
25         table.deleteRow(r.rowIndex);
26         //table.removeChild(rowsToDelete[i]);
27     }
28 }


看这个函数的前三行,它试图取得form的第1个或第2个子节点,并把它作为table来处理(看接下来的几行)。要想清除表格里的错误信息,首先要取得表格本身,这没错,但是如果第1个或第2个子节点不是table的话,脚本就会出错,造成原出错信息无法清除,这样每次提交后的提示信息就会累积在屏幕上。

要解决这个问题有两个办法:
  • 写代码时要小心,保证form的第1或2个子节点是table,不要在生成table前加其他代码。
  • 或,修改xhtml的validation.js,使它总能获得正确的table元素,重新打包到struts.jar。
刚看了一下Struts的JIRA,已经有人报告了这个问题(id WW-1802),而且这个bug在2.1版本中已经解决了。

posted @ 2007-06-03 17:56 shaofan 阅读(2529) | 评论 (3)编辑 收藏

假设:用两者写一个最小的WEB程序。
过程可以参照:
1.struts的就太多了,随便哪个都可以
2.python/django可以看limodou写的Django step by step

 

Java/Struts/JSP  Python/Django
开发步骤 1.在web.xml里配置struts的servlet
2.在struts-config.xml里配置URL和action的映射
3.写action
4.写JSP
1.在urls.py里配置URL到方法的映射
2.写相应的方法
3.写HTML模板
调用过程 1.根据web.xml的映射调用struts的servlet controller
2.servlet controller根据struts-config.xml的映射调用相应的action
3.action处理请求
4.JSP渲染显示
1.根据urls.py的映射调用相应的方法
2.方法处理请求
3.HTML渲染显示


相比之下前者用了两层才把一个HTTP请求映射到实际处理的方法:第一次是servlet的映射,第二次是struts action的映射。
而django则一次就从URL映射到相应的方法了。

另外一个比较显著的区别,也是基于java和python的语言上的区别吧,java的所有方法必需包含在一个类中,因此action mapping配置时是映射到类,而action在实现类则应实现事先约定的方法(通过继承或实现接口)。而django则直接得多,可以直接在配置里写明处理请求的方法名。


posted @ 2007-04-06 19:11 shaofan 阅读(4966) | 评论 (0)编辑 收藏

DOM (Document Object Model)是一套语言无关的XML解析的接口定义。它定义了在XML解析中需要的类型,方法,以及属性,比如如何获得一个XML标签,如何改变标签的内容,如何改变它的属性,等等。

DOM只是一个定义,并不是具体的实现,它的目的就是为了让大家在各个平台上都能用相同的方式来处理XML,这样一来,我只要了解DOM,基本上在各个平台上都可以方便的处理XML,而不用重新学习了。比如说,Java, JavaScript, Python都有DOM的实现,用它们来处理XML,方式基本上都是一样的(当然也有非DOM的XML解析方式)。在Java下,实现DOM的类库就有很多,比如JDom,Xerces, 用GOOGLE一搜就一大把。现在Java 5.0内置的就是Xerces。而JavaScript本身就内置了DOM的实现。Python也默认安装了DOM的库。

正因为DOM致力于实现各个平台上对XML一致的处理方式,它定义了一堆自己的接口。因此在用DOM的时候,会有很多非NATIVE的东东。比如说,返回节点的子节点的方法,childNodes,返回的类型是NodeList。我第一次在Java上用,就以为是返回一个List,然后用get(n)方法来取得某元素。而实际上NodeList是用item(n)的方法来取得某元素的。这就让我觉得很怪。而DOM正是用这种方式来获得“语言无关”的能力的。

DOM是用IDL(Interface Definition Language)来定义的。完整的定义可以在这里找到 http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html。IDL也很容易看懂。定义的1.1节列出了所有的接口。

这些接口里,最重要而且常用的是Node,NodeList,Document,Element,Text,Attr这几个。DOM把XML文档看作一棵树,树上的每个元素都是Node。每个Node都属于某个类型,比如Element,attribute,text等。这些类型就表明这个节点在XML文档里的类型了。

比如Node里有个属性:

  readonly attribute unsigned  short   nodeType;

根据这个定义,对于取得的节点,我们就可以通过读取nodeType这个属性来判断这个节点的类型。在Java里,所有的属性都是用getter来取得的,因此对某节点n,就可以用n.getNodeType()取得它的类型。Node接口里也定义了类型常量:

  const unsigned short      ELEMENT_NODE                   = 1;
  const unsigned short      ATTRIBUTE_NODE                 = 2;
  const unsigned short      TEXT_NODE                      = 3;
  const unsigned short      CDATA_SECTION_NODE             = 4;
  const unsigned short      ENTITY_REFERENCE_NODE          = 5;
  const unsigned short      ENTITY_NODE                    = 6;
  const unsigned short      PROCESSING_INSTRUCTION_NODE    = 7;
  const unsigned short      COMMENT_NODE                   = 8;
  const unsigned short      DOCUMENT_NODE                  = 9;
  const unsigned short      DOCUMENT_TYPE_NODE             = 10;
  const unsigned short      DOCUMENT_FRAGMENT_NODE         = 11;
  const unsigned short      NOTATION_NODE                  = 12;

用这些常量和和n.getNodeType()的结果比较,就可以知道它是不是某种类型。

Node接口中也定义了一些方法,比如:

 Node     appendChild(in Node newChild)    raises(DOMException);

表明appendChild方法需要一个Node类型的参数,返回一个Node。 具体的说明可以点文档上的链接进去,也很容易看懂。

Node接口里定义了操纵节点的方法,比如增加子节点,返回父节点,插入新节点,返回节点类型,等等。Document,Element等接口都继承Node接口,因此在它们上面都可以使用操纵节点的方法。

Document:代表整个XML文档。所有DOM元素都不能用类似Java里new的方式来生成,而是要通过调用Document里的相应方法来生成。因此它提供了生成诸如Element, Attr, Text的方法。比如createElement, createTextNode, createComment等。它也提供了名为getElementsByTagName的方法,用来通过标签名称来取得其对象。比如getElementByTagName("ul")就可以获得所有ul标签。它也提供一些文档的属性,比如xmlEncoding,inputEncoding等。它的一个属性,documentElement代表文档的根节点。所有对XML元素的操作,基本上都是从Document开始的。

Element:代表一个XML标签。它可以有属性,子标签,等。比如<ul id="booklist"><li>hello</li></ul>。标签ul是一个Element,它有一个属性叫id,属性的值是booklist。它有一个子结点li。li也是一个标签,它也有个子节点hello,是一个Text类型的节点。这个接口提供操纵其标签属性的方法,比如getAttribute,setAttribute,removeAttribute等。它也提供了和Document中一样的getElementsByTagName的方法,用来获得在这个节点下的元素。

Attr:代表标签中的属性。比如上面的id。它也是一个Node。它有名字,值,也可以获得它的所属标签。

Text:代表一段文字,比如上面的hello,它也一个Node,但比较特殊,它不是直接继承Node,而是继承CharacterData接口,后者继承了Node。但是它不能有子节点。

用JavaScript给一个例子。假设有一个HTML文档:

< html >< head >< title > Try DOM </ title ></ head >< body >
< ul >
< li > hello </ li >
< li > world </ li >
</ ul >
</ body ></ html >

下面是增加一个li的JavaScript方法:

ulList  =  document.getElementsByTagName( " ul " );
ul     
=  ulList.item( 0 );
txt    
=  document.createTextNode( " I am new li " );
li     
=  document.createElement( " li " );
li.appendChild(txt);
ul.appendChild(li);

用Java来写,是这样:

NodeList ulList  =  document.getElementsByTagName( " ul " );
Node        ul      
=  ulList.item( 0 );
Text          txt      
=  document.createTextNode( " I am new li " );
Element    li        
=  document.createElement( " li " );
li.appendChild(txt);
ul.appendChild(li);

可以看到处理方式和数据类型都是一样的。如果要了解更多,可以看看DOM的定义,都是IDL。

posted @ 2007-04-01 18:45 shaofan 阅读(844) | 评论 (0)编辑 收藏

我的博客已搬家,请移步到 http://shao-fan.com/blog 阅读最新内容!


Ubuntu/Debian中的update-alternative用来对系统中不同版本的同个软件进行管理。
比如,系统中可能装有GNU的Java编译器,和SUN的Java编译器。可以用update-alternatives来设置当前使用它们中的哪一个。

它的原理是在/usr/bin中建立一个link,指向/etc/alternatives中的一个文件,而些文件又是一个link,指向当前使用的命令。比如java命令,查看如下:

 $ which java
/usr/bin/java
$ ls -l /usr/bin/java
lrwxrwxrwx /usr/bin/java -> /etc/alternatives/java
$ ls -l /etc/alternatives/java
lrwxrwxrwx /etc/alternatives/java -> /usr/lib/j2re1.5-sun/bin/java
$ ls -l /usr/lib/j2re1.5-sun/bin/java
-rwxr-xr-x /usr/lib/j2re1.5-sun/bin/java

参数--display可以某个软件的当前配置,如:

 $ /usr/sbin/update-alternatives --display java
java - status is auto.
link currently points to /usr/lib/j2re1.5-sun/bin/java
/usr/lib/kaffe/bin/java - priority 300
slave java.1.gz: /usr/share/man/man1/java.kaffe.1.gz
/usr/lib/j2re1.5-sun/bin/java - priority 315
slave java.1.gz: /usr/lib/j2re1.5-sun/man/man1/java.1.gz
Current `best' version is /usr/lib/j2re1.5-sun/bin/java.

status有auto和manual两种。一旦用户更改了系统的默认设置,它就变为manual。在auto的状态下,系统会根据几套配置的priority来判断当前应该使用哪套配置。

每套配置可以设定多个link,它们被称为slave。上面的例子中,有两套java的配置。一套是/usr/lib/kafe/bin/java,另一套是/usr/lib/j2re1.5-sun/bin/java,它们各有一个slave。在些例中这些slave设置的是java命令的 manual。当更改了配置时,用man命令查看的帮助也会相应更改。

参数--config可以用来更改当前的配置。

 $ sudo /usr/sbin/update-alternatives --config java 
There are 2 alternatives which provide `java'.
Selection Alternative
-----------------------------------------------
1 /usr/lib/kaffe/bin/java
*+ 2 /usr/lib/j2re1.5-sun/bin/java
Press enter to keep the default*, or type selection number: 1
Using `/usr/lib/kaffe/bin/java' to provide `java'.

参数--install用来设置一套新的配置。具体参见 http://blog.stevenkroon.com/2006/08/29/debian-update-alternatives/

posted @ 2006-12-25 01:43 shaofan 阅读(6305) | 评论 (1)编辑 收藏

Web开发真是越来越有意思了。现在居然可以在JavaScript里直接调用Java写的方法。大水牛Buffalo的最新版1.2.3发行离现在已有半年时间了,现在才注意到。在客户端的代码相当简单:

buffalo.remoteCall("userService.listAll",[],function(reply){
 // 不用担心,reply.getResult会从聪明的判断服务器端远程调用的结果类型。
 var userList = reply.getResult(); 
 var firstUserFamilyName = userList[0].name.familyName;
});

给Web程序加上Buffalo也相当容易。只要下载几个jar文件放到lib目录下,外加几个JS文件,然后在web.xml里加一个Servlet即可。用的时候是需要有个properties文件来定义哪些JAVA方法可以被JS调用。而服务器端的JAVA代码不需要做任何改动。

暂时手头上还想不起来哪些地方会用,但是这个东东可是我很久以前曾经想过的,现在有人实现了,还是很激动人心的啊。Buffalo的主页是 http://www.amowa.net/buffalo/zh/index.html 。


posted @ 2006-09-08 03:59 shaofan 阅读(8908) | 评论 (6)编辑 收藏

最近因为Globus的原因,不得不用Linux了。以前几次想学,都因为难得要领放弃了。这次装了Ubuntu,又碰巧在它的论坛上看到一篇很不错的教程,终于有些“入门”的感觉了。看来找到合适的教程真的是很重要啊。这几天用下来,感觉还真的很不错。用Python写了个显示目录树的小程序。也不知道有没有现成的,反正很简单,刚好就练练手,功能也够我自己用了:)

下载Python脚本


posted @ 2006-08-01 08:57 shaofan 阅读(1493) | 评论 (0)编辑 收藏

最近Firefox出了点问题。我这里用http proxy上网,连接设置里要设置相应的proxy。但发现每次重启ff,连接设置都被重置为“直接连接”。即使改回“通过proxy连接”,下次重启又被重置了。

马上google一把,发现类似的问题大致有两种解决办法:
1.进入safe mode,会出现一个对话框,把三个选项都勾上,重启。
2.在地址栏输入about:config,会出现所有的配置,把要改的改了即可。
3.直接修改prefs.js文件。

但这三个方法对偶的FF都不管用。

最后的解决方法是,删除
C:\Documents and Settings\<user name>\Application Data\Mozilla\Firefox\Profiles\<xxxxxxxx.default>\
下的user.js,然后再修改prefs.js。然后一切都正常了。

原来,ff最基本的配置文件是prefs.js。而user.js的优先级应该是比prefs.js高,因此每次重启它都从user.js读取配置。而通过正常途径,如在选项菜单里改设置,无法在user.js里保存(不知道为什么)。所以就造成了每次重启配置被重置的情况,其实就是设置无法被保存。把user.js删掉以后,ff就从prefs.js里读取配置了,而且新的设置也可以正常保存。

不管是从选项菜单里修改配置,还是以上的第二种方法,最终的结果都是配置被保存在prefs.js文件里,效果都是一样的。

目前已知的会私自修改FF配置的软件只有Hide IP Plantium,而以上情况正是在安装Hide IP Plantium以后出现的。用的时候要注意。

相关的讨论在mozillazine里有很多。不得不承认,这类的英文资源要比中文的多得多。看这里的详细讨论:
http://forums.mozillazine.org/viewtopic.php?t=413875&postdays=0&postorder=asc&postsperpage=15&start=15

posted @ 2006-07-24 18:21 shaofan 阅读(4586) | 评论 (2)编辑 收藏

1.理解页面流(flow),理解几种不同的定位方式:static, relative, absolute等
Positioning and other definitions:http://css.maxdesign.com.au/floatutorial/definitions.htm  

2.HTML页面表达内容逻辑,把样式控制写到CSS文件中

3.浮动(float)的DIV要配合width属性来用

4.怎样控制层的位置:用float,padding,width,height这些属性来控制
Float Tutorial: http://css.maxdesign.com.au/floatutorial/index.htm

5.设置可见的border或background-color来帮助排版

6.出现内层的DIV跑到外层之外的情况时,可以在外层DIV的</DIV>前加上一个clear层来解决问题。就是这样:
   <div class="container">
    ...
    ...
    <div class="clear"></div>
  </div>

  css:
  .clear{
    clear:both;
  }

7.样式表的选择符(Selector):
   Type/Class/ID等
  Selector Tutorial:http://css.maxdesign.com.au/selectutorial/index.htm

8.关于表单的样式设计:
让我们更好的设计表单:浅议Web的表单设计 http://tech.163.com/06/0529/04/2I8UPHTB0009158Q.html
用CSS制作具有亲和力的表单 作者:greengnn
http://www.jluvip.com/blog/article.asp?id=192

9.各种浏览器对各种标签用不同的方式渲染,如p, h1, ul等,它们会有不同的padding和margin,为了在各种浏览器下都正常的显示,可以把它们清零,如:
*{
    padding:0;
    margin:0;
}

10.使用list来显示数据或菜单
List Tutorial:
http://css.maxdesign.com.au/listamatic/
http://css.maxdesign.com.au/listamatic2/
http://css.maxdesign.com.au/listutorial/

11.关于各种标准,布局,技巧等的网站:
网页设计师:http://www.w3cn.org/
CSS教程:http://www.netvtm.com/w3s/css/
网页制作指导 - 致力于网页制作知识的普及:http://www.jianzhan8.cn/
当然还有必不可少的经典论坛blueidea:http://www.blueidea.com/bbs/list.asp?GroupName=%CD%F8%D2%B3%B1%EA%D7%BC%BB%AF%D7%A8%C0%B8

posted @ 2006-06-21 06:22 shaofan 阅读(928) | 评论 (0)编辑 收藏

如果你不幸装了NetBeans并且启用了外置的服务器,那么它会自动在你的web server的web.xml里添加一个filter,名叫HttpMonitorFilter。你用NetBeans时,它会过滤所有的http请求,这样NetBeans就可以显示所有的相关信息。但是如果不用NetBeans,比如我,用eclipse + Tomcat ,那就会得到这个异常:

NotifyUtil::java.net.ConnectException: Connection refused: connect
  at java.net.PlainSocketImpl.socketConnect(Native Method)
  at java.net.PlainSocketImpl.doConnect(Unknown Source)
  at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
  at java.net.PlainSocketImpl.connect(Unknown Source)
  at java.net.Socket.connect(Unknown Source)
  at java.net.Socket.connect(Unknown Source)
  at sun.net.NetworkClient.doConnect(Unknown Source)
  at sun.net.www.http.HttpClient.openServer(Unknown Source)
  at sun.net.www.http.HttpClient.openServer(Unknown Source)
  at sun.net.www.http.HttpClient.(Unknown Source)
  at sun.net.www.http.HttpClient.(Unknown Source)
  at sun.net.www.http.HttpClient.New(Unknown Source)
  at sun.net.www.http.HttpClient.New(Unknown Source)
  at sun.net.www.http.HttpClient.New(Unknown Source)
  at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
  at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
  at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
  at org.netbeans.modules.web.monitor.server.NotifyUtil$RecordSender.run(NotifyUtil.java:237)



解决方法是

第一步. 删除 Tomcat目录中common\lib下的两个和netbeans有关的jar文件(以org-netbeans开头的)

第二步. 修改tomcat目录下的conf\web.xml,删除相关Filter的定义,就是这一段:

    <filter>
        
<filter-name>HTTPMonitorFilter</filter-name>
        
<filter-class>
            org.netbeans.modules.web.monitor.server.MonitorFilter
        
</filter-class>
        
<init-param>
            
<param-name>netbeans.monitor.ide</param-name>
            
<param-value>127.0.0.1:8082</param-value>
        
</init-param>
    
</filter>
    
<filter-mapping>
        
<filter-name>HTTPMonitorFilter</filter-name>
        
<url-pattern>/*</url-pattern>
        
<dispatcher>REQUEST</dispatcher>
        
<dispatcher>FORWARD</dispatcher>
        
<dispatcher>INCLUDE</dispatcher>
        
<dispatcher>ERROR</dispatcher>
    
</filter-mapping>

posted @ 2006-06-13 20:37 shaofan 阅读(1038) | 评论 (0)编辑 收藏

据英国的职位搜索引擎Workcircle的调查显示,93%的IT经理人和几乎所有的CEO和CTO会在英格兰队比赛的那天请病假。相比之下,程序员的请假的比例要低得多,JAVA程序员为86%,而最可怜的是SQL程序员,只有14%。更搞笑的是WikiHow上还有一个“怎样请病假”的教程。

原文如下:

Managers most likely to take a sickie to watch England play

9 June 2006, Cambridge UK – UK job site, Workcircle ran a survey this week asking how likely jobseekers are to take a sick day to watch an England World Cup match.

World cup surveyThe results show the deep divide between workers and management, just 14% of Engineers surveyed will take a sickie to watch a match, but a shocking 93% of managers will.

And it gets worse the higher you get – all CEOs and CTOs surveyed will take a day off.

As far as the developers go, Java programmers are the most patriotic – 86% would call in sick to watch a match, compared to 14% of hard-working SQL developers.

So when the boss is in an unexplained long meeting during the World Cup, check if there’s an England match on!

posted @ 2006-06-12 06:45 shaofan 阅读(681) | 评论 (0)编辑 收藏

适用于webwork 2.2.2,详见随包文档。源文件下载:Hello.rar

一共五步:

1.建立web应用程序的目录结构
2.拷贝库文件:ww安装目录下的lib\default中的所有jar,以及webwork-2.2.2.jar,复制到WEB-INF\lib下。
3.生成配置文件:web.xml在WEB-INF下, xwork.xml在WEB-INF\classes下

web.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

    
<display-name>My First Hello Webwork</display-name>

    
<filter>
        
<filter-name>webwork</filter-name>
        
<filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>
    
</filter>

    
<filter-mapping>
        
<filter-name>webwork</filter-name>
        
<url-pattern>/*</url-pattern>
    
</filter-mapping>

    
<welcome-file-list>
        
<welcome-file>index.jsp</welcome-file>
    
</welcome-file-list>

    
<taglib>
        
<taglib-uri>/webwork</taglib-uri>
        
<taglib-location>/WEB-INF/lib/webwork-2.2.2.jar</taglib-location>
    
</taglib>
</web-app>


xwork.xml:
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">

<xwork>
    
<!-- Include webwork defaults (from WebWork JAR). -->
    
<include file="webwork-default.xml" />

    
<!-- Configuration for the default package. -->
    
<package name="default" extends="webwork-default">
    
</package>
</xwork>


4. 编写action和jsp
5. 在xwork.xml中添加相应配置,如在package之间加入:
        <default-interceptor-ref name="completeStack"/>
        
<action name="helloww" class="net.blogjava.shaofan.helloww.Hello">
            
<result name="success">greetings.jsp</result>
        
</action>


下步计划:
* 了解package
* ww的taglibs
* 在action和jsp间传递数据的机制(struts中使用formbean,利用session,request等)

posted @ 2006-06-04 09:13 shaofan 阅读(2290) | 评论 (7)编辑 收藏

     摘要: 在这篇文章里,Nick Afshartous描述了一种把HTML的内容转换为PDF格式的方法。这种方法相当有用,比如说,一个web程序可以在它的页面上提供如“下载为 PDF”的功能。这种功能方便了打印和储存,以供日后使用。Afshartous的转换方法只使用开源的组件。也有一些商业产业可供使用。因此,在这篇文章里描述的这种方法既在价格上可以承担,又能够获得所用组件的源码。(1600字;2006年4月10日)   阅读全文

posted @ 2006-06-01 07:56 shaofan 阅读(3534) | 评论 (10)编辑 收藏

     摘要: 在这篇文章里,Nick Afshartous描述了一种把HTML的内容转换为PDF格式的方法。这种方法相当有用,比如说,一个web程序可以在它的页面上提供如“下载为PDF”的功能。这种功能方便了打印和储存,以供日后使用。Afshartous的转换方法只使用开源的组件。也有一些商业产业可供使用。因此,在这篇文章里描述的这种方法既在价格上可以承担,又能够获得所用组件的源码。(1600字;2006年4月10日)
  阅读全文

posted @ 2006-05-30 06:15 shaofan 阅读(5675) | 评论 (7)编辑 收藏

天差点栽在JAVA路径设置上。

本来是想用ANT的。但是在命令行输入ant,得到了这样的提示:

Usage: java [-options] class [args...]
           (to execute a class)
   or  java [-options] -jar jarfile [args...]
           (to execute a jar file)

       ......
       ......

奇怪。想来是刚重装了系统,JAVA_HOME没有设好。于是检查了一遍。问题依旧。那是不是虚拟机的问题?虚拟机缷掉重装。折腾了半天,问题还是没有解决。

逼得我只能静下心来仔细想想问题所在了。ant的命令执行的是一个批处理文件,在这个批处理中它会调用java.exe来运行ant。出现这样的问题,必定是java.exe的用法格式不对了。于是打开ant.bat,发现它的执行有几个分支。在每个分支上加上一句echo b1, echo b2,再次运行,确定是哪个分支被执行。被运行的语句分支就是这个了:

:runAntWithClasspath
"%_JAVACMD%" %ANT_OPTS% -classpath "%ANT_HOME%\lib\ant-launcher.jar" "-Dant.home=%ANT_HOME%" org.apache.tools.ant.launch.Launcher %ANT_ARGS% -cp "%CLASSPATH%" %ANT_CMD_LINE_ARGS%
goto end

OK。现在几乎可以肯定是那一堆%%的变量里出了问题。拿出我们程序员百试不爽的绝招的时候了:打印每个变量。哈哈,问题出来了:

"D:\lib\apache-ant-1.6.5\\lib\ant-launcher.jar"

看到了吗?"lib"前面居然是两个反斜杠杠。OK。发现了问题所在,现在是解决的时候了。打开系统变量ANT_HOME,果然,它被设置为"D:\lib\apache-ant-1.6.5\"。把最后的反斜杠去掉。再试运行ant,得到:

Buildfile: build.xml does not exist!
Build failed

ant可以正常运行,问题解决了。

这个小小的问题前后用了我快一个小时的时间。但是最后真正发现并解决问题的时间也不过十分钟而已。看来还是太浮躁了。如果一开始就用心去想,也不会有这么多的浪费。想想,为什么那后面会多一个\,其实也很简单,从WINDOWS的地址栏直接拷贝的咯。Windows啊......我知道不能怪Windows,但总要找个出气桶,对不对?

自以为用了几年JAVA已经挺熟了,没想到差点栽到最低级的失误里了。反省反省。。。。。。

posted @ 2006-05-29 07:28 shaofan 阅读(2586) | 评论 (3)编辑 收藏

Sun 的Java EE 5终于发布了(上一版本称作J2EE)!这一版本可说是万众瞩目了,目前在SUN的站点上已经提供下载。值得关注的特点是:

"第一个商业的,比较完善的Java EE 5 实现

简化开发--对编程模式的重新组织
支持EJB3.0--POJO
支持Java Persistence API , ORM更简单
JAX-WS 2.0 以及 JAXB 2.0 使得开发web services 以及SOA应用更加便捷
JavaServer Faces 1.2--更简易开发AJAX
效率更高, 同时管理和部署功能更强大
启动速度提高30%, 占用内存减少30%.
web services 效率提高至少5倍.
web services 管理更强大
整合了NetBeans以及支持Eclipse plug-in
提供了整合NetBeans的可视化的SOA 开发以及部署
Sun's Java System Application Server PE 9.0是完全开源的"

                                                 ----摘自www.Matrix.org.cn

它的结构如下图:


Matrix上的相关文章:http://www.matrix.org.cn/resource/news/728_SUN+JavaEE5+SDK.html
SUN网站上的下载地址:http://java.sun.com/javaee/downloads/index.jsp

posted @ 2006-05-17 08:04 shaofan 阅读(676) | 评论 (0)编辑 收藏

Google好用吗?大概很多人会说"Yes"。

但是老外Don Norman去从另一个角度说明,Google的易用性只是一个假象。因为他的主页只放一个搜索框,要想使用Google的其他服务,比如Google Map, Google Earth,却要经过很多次不同的点击,给用户造成很大的不便。相比之下,其他的比如Yahoo,MSN,大家认为它们复杂,但实际上从他们的主页访问他们提供的各种服务都很方便。

要我说,就一个字:赞成。两个字:非常赞成!

全文请见:

英文原文:The truth about Google's so-called "simplicity"   by Don Norman
中文译文:关于 Google 界面所谓的“简洁性”的真实情况  翻译:张亮

posted @ 2006-05-14 06:24 shaofan 阅读(502) | 评论 (0)编辑 收藏

些天,不记得是用SOHU的邮箱注册了哪个网站了,现在每天都收到大量的垃圾邮件。不知道别人怎么样,反正我觉得SOHU的闪电邮件的反垃圾邮件功能基本是个摆设。而它的“垃圾邮件举报”的功能似乎也没什么作用。相比YAHOO和GOOGLE,这两位业界大佬提供的邮箱的反垃圾能力则明显要高一筹。

我也常用YAHOO的邮箱来注册网站BBS,它对垃圾邮件的识别率相当高,我收到的大部分垃圾邮件它都可以准确识别。此外,YAHOO还提供了“替身邮”的功能,就是可以注册一堆虚拟的邮件地址,每个地址其实都是指向你原来的那个。用这些替身地址去注册网站或者留言什么的,所有发到它的邮件都会自动到达原来的邮箱。以后从这个地址来的垃圾邮件多了,就可以把这个替身地址删掉,就再也不会收到从它发来的垃圾了。

这是个好想法。以前我所想到的方法是,注册一个邮箱,专门用来在注册网站用。然后给它设置自动转发,把邮件转到我原来的邮箱地址。替身邮和这个想法真有异曲同工之妙。但是替身邮有个缺点,一旦把替身地址删掉,那些有用的邮件也收不到了。我所希望的是,能为这些替身地址增加“白名单”的功能,只收指定地址寄来的邮件。如果是这样,那就完美了。

另外,SOHU闪电邮件的“自动转发”居然不起作用?开了好几天了,一封都没转发过,真是狂晕!!

posted @ 2006-05-03 18:22 shaofan 阅读(649) | 评论 (1)编辑 收藏

两周休假,不更新咯!休息一下!

posted @ 2006-03-20 10:30 shaofan 阅读(333) | 评论 (0)编辑 收藏