如何分离个人信息,缓存动态页面(转帖)

下面是一个用于php中的静态缓存加入动态个人信息的方案,我觉得他的思路是可以借鉴的,就转帖在这里了。

正文

****************************************************************************

转自:(http://nio.infor96.com/archives/283

如何分离个人信息,缓存动态页面

肖理达 (KrazyNio AT hotmail.com), 2005.06.07, 转载请注明出处

一直想写一篇关于动态页面 cache 的文章,但每次?提笔?却又放弃,因为总是觉得准备得

还不够充分。今天埋头写下,只是希望对自己的工作做一些笔录。

1、问题起源

我们经常会在一个动态页面中加入很多个人信息,以 CMS 首页为例,用户登录之前显示登

录框,登录之后显示其用户名,并根据权限显示其可用模块的链接。由于每个用户登录之

后,显示出来的动态信息都是不一样的,所以这部分无法进行 cache,我们将这部分信息

定义为?个人信息?,它的特性是根据登录用户进行动态改变。

现在问题来了,就是一个 CMS 的首页,访问者的登录概率并不是百分百的,应该说有一大

部分人访问首页是没有登录的,这个时候的首页是一个公共的页面,没有任何个人信息,

或者说这时候首页的任何动态信息都是可以转换成静态的,也就是说这部分是可 cache 的

2、使用 JavaScript 分离个人信息

解决这个问题的方法有很多种,一种是将个人信息和其他信息进行分离,如在 CMS 首页中

加入一个外部的 JavaScript 文件,而这个文件的内容实际上是由 PHP 动态生成的。CMS

首页 index.php 代码片段:

<script language="JavaScript" src="/js/personal.php"></script>

?.

<script language=?JavaScript?>

document.write(sUser);

document.write(sLinks);

</script>

personal.php 代码片段:

<?php

session_start();

header(?Cache-Control: no-store, no-cache, must-revalidate?);

?>

sUser = ?<?php echo $_SESSION['USER']; ?>?;

sLinks = ?<?php echo addslashes($_SESSION['LINKS']); ?>?;

这种方法比较适合个人信息较少,易于集中显示的情况。通过 JavaScript 外挂代码实现

个人信息分离之后,personal.php 是永不 cache 的,这样也就可以放心地对 CMS 首页进

行 cache 了,具体的 cache 方法可采用 304 HTTP 头与 Cache_Lite 相结合的方式,这

在后边有详细代码示例。

3、选择性分离个人信息

一旦个人信息较多,很难对其进行分离的时候,上述方法实现起来就会比较麻烦了。接下

来介绍一种比较放宽的 cache 方式,就是只对用户未登录的 CMS 首页进行 cache,一旦

发现用户处于登录状态,则跳过 cache 部分,直接运行相关代码,我把这种方法称为?

选择性 cache
?。这种方法中,我们牺牲了一部分可 cache 的情况,但很大程度上提

高了个人信息的可扩充性,也就是说个人信息的多少、显示的位置等等都不再受到限制,

这是值得的,毕竟修改服务端代码要比修改大量的 JavaScript 代码要来得方便,而且

JavaScript 的调试也会比较麻烦。

分析一下这种 cache 方式,概要流程图如下:

image

代码片段如下:

<?php

session_cache_limiter(?must-revalidate?);

session_start();

if (empty($_SESSION['USER'])) { //未登录时才使用 cache

    ?.    //输出 cache

} else {

    //  直接输出页面内容,此条件下与未使用 cache 时一样

    $data =& get_data();

    echo $data;

}   //end if

?>

这里需要说明的一点是,由于 PHP 在使用 SESSION 时,php.ini 中默认设置的

session.cache_limiter 为 nocache,所以需要修改 cache_limiter,设置成

must-revalidate,使得客户端再次浏览当前页时必须发送相关 HTTP 头信息到服务器进行

验证,然后才决定是否加载客户端本地 cache。不要把客户端本地 cache 与服务器端

cache 搞混,之后的代码片段中会充分利用客户端 cache 和服务器端 cache 机制达到缓

存的目的。关于 must-revalidate,请参考 HTTP 规格说明书 RFC 2612 的 14.9.4 章节

上边的代码并不完整,接下来是更加深入的探讨客户端 cache 机制了,利用客户端 cache

,可以有效地减轻服务器端负载。首先了解一下 HTTP 头:Last-Modified 与

If-Modified-Since。简单的说,Last-Modified 与If-Modified-Since 都是用于记录页面

最后修改时间的 HTTP 头信息,只是 Last-Modified 是由服务器往客户端发送的 HTTP 头

,而 If-Modified-Since 则是由客户端往服务器发送的头,其工作原理图如下:

image

可以看到,再次请求本地存在的 cache 页面时,客户端会通过 If-Modified-Since 头将

先前服务器端发过来的 Last-Modified 最后修改时间戳发送回去,这是为了让服务器端进

行验证,通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回新的

内容,如果是最新的,则返回 304 告诉客户端其本地 cache 的页面是最新的,于是客户

端就可以直接从本地加载页面了,这样在网络上传输的数据就会大大减少,同时也减轻了

服务器的负担。想要详细查看 HTTP 头信息,可以在 Firefox 中安装 LiveHTTPHeaders

插件,安装完成之后按 Alt+L 就可以在 Sidebar 中看到了。

现在再来完善之前的 index.php 代码:

<?php

session_cache_limiter(?must-revalidate?);

session_start();

function &get_data()

{

    //此函数用于获取本页面的输出内容

    //?.

}   //end function

if (empty($_SESSION['USER'])) { //未登录时才使用 cache

    //====================================================

    //  1. 检查 HTTP 头是否符合 304 的条件

    //====================================================

    //get_last_modified() 函数需要另外单独实现,此函数用于获取服务器端 cache 文件的最后修改时间,可将时间戳保存在数据库中。

    $last_modified = get_last_modified();

    $headers = getallheaders();

    if (strtotime($headers['If-Modified-Since']) == $last_modified) {

        //  返回 304 并结束程序运行

        header('HTTP/1.1 304 Not Modified');

        exit;

    }   //end if

    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $last_modified) . ' GMT');

    //====================================================

    //  2. 检查 cache 文件是否存在

    //====================================================

    require_once 'Cache/Lite.php';

    //  参数设置

    $options = array(

        'cacheDir' => './cache/',

        'lifeTime' => 86400, //最大 cache 一天时间

        'fileNameProtection'   => false //使用 CMS 自身提供的 id 作为名字

    );

    $cache = new Cache_Lite($options);  //创建 Cache_Lite 对象

    $id = md5($_SERVER['REQUEST_URI']); //生成对应于 cache 文件的 ID

    if ($data = $cache->get($id)) {   //存在 cache 文件,获取内容,直接输出

        echo $data;

    } else {

        $data =& get_data();

        echo $data;

        flush();

        $cache->save($data);    //保存 cache

    }   //end if

} else {

    $data =& get_data();

    echo $data;

}   //end if

?>

测试时可以使用 LivHTTPHeaders 插件,你将会看到第一次访问时是返回 200,第二次到

第N次访问时则返回了 304,而登录之后,则一直都返回 200,因为我们选择性 cache 之

后,对登录之后一律运行程序输出,而不使用 cache,如果之后需要对输出的个人信息进

行修改,只需要改函数 get_data() 即可,也避免了 JavaScript 的调试。

总结

除此之外,还有其它方法可以实现分离个人信息,缓存动态页面的目的。而且为了提高服

务器运行效率,还可以使用数据库 cache、Squid 反向代理等,如 ADOdb 的 cache。目前

用的比较多的 Drupal 应用的就是本文中提到的第二种方法。

参考资料

HTTP Caching & Cache-Busting for Content Publishers

Hypertext Transfer Protocol ? HTTP/1.1

PHP Anthology, Volume 2: Applications. Chapter 5: Caching

Caching Tutorial for Web Authors and Webmasters

Drupal 源代码

Comments RSS | Trackback URL

4 Comments on ?关于 Cache(4)?

By zeal. June 13th, 2005 at 3:25 pm

我们目前采用的是oracle cache server以及squid。对于不能cache的内容采取分目录存放

。在代码设计的时候就考虑可cache性。对于大量需要用户交互的内容,似乎cache的作用

不大。

By Nio. June 13th, 2005 at 5:02 pm

嗯,如果内容本身全都是个人信息的话或者必须登录才能浏览的页面,就用不到这种cache

方法了,需要看登录与不登录的概率比而定 🙂

By nc. July 17th, 2006 at 12:43 pm

感谢你文章的提示,非常不错.

By ahu. October 8th, 2006 at 5:10 pm

zeal的公司貌似有些money~

**************************************************************************

                                                           转载完毕

另一段静态页面计数代码:


<script language="javascript" src="/data/include/count.php?id=$id"></

script>

转摘自:(http://www.mephp.com/view.php?tid=1&id=44

JAVA学习日记页面静态化方案

JAVA学习日记页面静态化方案(借鉴了:http://www.agilejava.org/space/?233的 生成静态页面技术解决方案系列,见我的转帖:一个实现将JSP动态页面转为静态的方案(转帖)

1、首页和帖子页面静态化,帖子列表不静态化;

2、列表上的帖子用静态化链接;

3、隐私帖子页面不静态化;用户登录后用动态化链接,所以可以看到隐私帖子;

4、静态化时机:

  1)、发公开帖子;

  发公开目标:静态化目标和首页;

  公开日记:静态化日记、目标和首页;

  公开评论:评论日记:静态化日记、目标、首页;评论目标:静态化目标、首页;

  发私人日记:不作任何静态化;

  2)、修改公开帖子;

  修改目标(目标不能修改隐私属性):

  修改公开目标:目标、首页;

  修改私有目标:不作任何静态化;

  修改日记(日记可以修改隐私属性):

  修改公开日记,并且修改后仍是公开帖子:静态化日记、目标、首页;

  修改公开日记,但是修改后的日记是私有帖子:删除已经静态化日记,重新静态化目标、首页;

  修改私有日记,并且修改后仍是私有帖子:不作任何静态化;

  修改私有日记,但是修改后成了公开日记:静态化日记、目标、首页; 

  修改评论(评论的隐私属性与被它评论的目标或日记一致)

  修改公开目标的评论:静态化目标、首页;

  修改公开日记的评论:静态化日记、目标、首页;

  修改私有目标的评论:不作任何静态化;

  修改私有日记的评论:不作任何静态化;

  3)、删除帖子(私有帖子是不能被删除的);

  删除公开目标:删除目标会删除此目标下的评论和日记和日记的评论,所以要:删除已静态化的目标、删除已静态化的目标的日记、重新静态化首页;

  删除公开日记:删除日记会删除此日记下的评论,所以要:删除已经静态化的日记、重新静态化首页;

  删除公开评论:删除目标的公开评论:重新静态化目标、首页;删除日记的公开评论:重新静态化日记、日记的目标、首页;

 

  4)、静态化种类:

  手动静态化:由管理员执行手动全面静态化及维护工作:包括:对数据库和静态化文件储存目标扫描,重新静态化应该静态化的帖子;如果某个不应该静态化的私有目标或日记被静态化了则删除已静态化的文件,并且作下记录,分析原因;

  定时静态化:同手动静态化一样的功能,只不过由系统定时进行,比如每晚12:00点;

  帖子变动时的静态化:如上面的列表;

5、其它注意事项:

  1)、为了统一静态化页面和简要设计和增加系统灵活性,现对登录用户和游客用户(包括搜索引擎)的静态化作一区别:

  登录用户:全部用动态化,也就是说与现在动态化的系统没有区别;从各论坛和网站的统计情况来看:登录用户占全部用户的比例一般在5%左右,所以不会系统有什么大的影响;

  未登录用户(包括搜索引擎):首页和帖子全部用静态化,游客提交评论后通过Action的301跳转进入已静态化的最新页面,但是提交评论的表单已经静态化了,所以不能记住用户,这可以放在以后解决,同屏蔽垃圾留言的设计一起进行,可能会用<frame>内嵌表单来做。

  2)、类的设计:

  1个执行实际静态化的类:ToHtml.java;1个模拟游客访问,调用静态化的工具类:CallHtml.java;再增加一个静态化文件管理类:HtmlsManager.java,用于封装各种静态化时机的操作,包括:

  1>,提交帖子:doPostArt(),传入提交的帖子作为参数,即为doPostArt(ArticleInfo postedArt);

  2>,修改帖子:doEditArt(),传入修改前的帖子和修改后的帖子作为参数,即为:doEditArt(ArticleInfo oldArt, ArticleInfo newArt);

  3>,删除帖子:doDelArt(),传入被删除的帖子作为参数,即为:doDelArt(ArticleInfo);

  4>,检测是否相应静态化文件的方法:isExist(String phyFullName),传入系统路径的包含路径的全文件名作为参数;

  5>,删除一个相应静态化文件的方法:delete(String phyFullName),传入系统路径的包含路径的全文件名作为参数;

添加游客评论功能设计之测试计划

今天,添加游客评论功能设计所计划的功能已经基本实现。

1、实现过程中的改动:

  GuestArtInfo.java用原有的ArticleInfo.java代替;CookieManager.java因为所需要的代码少,另开一个类反而麻烦,功能直接写在了Action中;在util包中添加了一个处理解析存储在帖子正文头部的游客信息的工具类:GuestArtProcessor.java

2、一点心得:

  原来以为struts-config.xml中的“input="/disGoalContentAction.do"”只能用jsp文件,结果证明用*.do的路径也行,而且有时还必须如此。如下面:


        <action

            attribute="guestArtForm"

            input="/disGoalContentAction.do"

            name="guestArtForm"

            path="/postGuestArtAction"

            scope="request"

            type="com.learndiary.website.action.disgoal.PostGuestArtAction">

           

            <!--forward name="goalSuccess" path="/processGoalAction.do" /-->

           

            <!-- forward name="diarySuccess" path="/disall/disgoal/afterPostDiarySelect.jsp" /-->

            <forward name="goalSuccess" path="/toSendMailOfGoalAction.do" />

            <forward name="diarySuccess" path="/toSendMailOfGoalAction.do" />

            <forward name="isBackSubmit" path="/processGoalAction.do" />

            <forward name="isBackSubmit1" path="/disGoalContentAction.do" />

            <forward name="isBackSubmitGoal" path="/processGoalAction.do" />

            <forward name="adviceSuccess" path="/disGoalContentAction.do" />

            <forward name="adviceOfDiarySuccess" path="/disGoalContentAction.do" />

            <forward name="adviceOfGoalSuccess" path="/toSendMailOfGoalAction.do" />

            <forward name="messageSuccess" path="/main.do" />

            <forward name="failure" path="/disall/disgoal/disGoalContent.jsp" />

            <forward name="nonUser" path="/main.do" />

            <forward name="noParentArt" path="/main.do" />

        </action>

自己感觉有必要写个测试列表,进行逐项测试:

1,每项功能经过游客、注册用户、管理员的测试;每项功能在日记的评论和目标的评论中都要经过测试;

2,理想状态功能使用:

填写所有字段,无无效字符串。

3,用户信息为空,或只填用户名、邮件、网址其中一项或多项;

4,帖子内容或标题为空;

5,填写了字段,但是格式错误;

6,测试在其它页面游客发的帖子是否显示正常;

7,测试有游客发帖时的邮件发送内容是否正常;

8,测试有游客发帖时的RSS订阅内容是否正常。

9,传到网上公开测试;

例外:

1,因为软件暂时没有想到解决办法或麻烦,下列项暂时搁置:

1),网址格式过滤;

2),重复提交问题;

添加游客评论功能设计

本来,这个站根本没有朋友来回复(见:停止guest公共帐号,启用公共测试帐号),我又怕麻烦,又想学点东西,近段时间就不打算写网站的程序了。但是,我想,万一有某个朋友有心发表点意见,一看还要注册、登录,结果想在这里留点我认为弥足珍贵的文字也打退堂鼓了。基于“不怕一万,就怕万一”的理论,万一有朋友来访,我们不能拒朋友于门外吧。

1、基本功能:

就是一般博客站的游客回复功能(如http://www.jiehoo.comhttp://www.chinamyhosting.com等),具体为:

1),回复表单在显示帖子内容的下方;

2),字段包括:

名字(必须),邮件(必须),网站(可选),标题(必须,系统自动给出re:....的标题,可以修改),内容(必须);

3),朋友在提交评论后,写入cookie,以后再次访问时不用输入除标题和内容的字段;

2,以上功能在本站实现的要点:

1),回复表单在显示帖子内容的下方:

可以参考上传文件使用的frame结构,为了简化实现,游客回复去掉上传文件功能,但可以使用UBB语法;

2),因为本站已有的数据结构和为了简化实现,所有游客的回复在系统中划为一个游客帐号的帖子;但是,为了显示上述字段,可以把上面的“名字(必须),邮件(必须),网站(可选)”字段加在内容前面,并加入特殊的分隔符,把上述字段连同内容存入数据库;要显示游客的回复的时候,把从数据库中取出的内容字段分离出“名字(必须),邮件(必须),网站(可选)”字段用于显示相关内容。

这样,在取出一篇日记或目标的评论列表,并把它们显示出来的时候,对划归游客帐号的帖子的显示格式有所变化;

3),游客发表的帖子不能被普通用户修改,但管理员可以修改和删除(例如有可能出现的垃圾信息)。

4),因为游客帐号需要保存的cookie信息没有密码,也用不着把游客的相关历史信息存入数据库。

3,具体实现:

1),jsp页面文件:只有一个显示日记或目标内容的页面需要在下部加一个游客留言的frame;

2),java文件:传递游客信息需要增加一个GuestArtInfo.java,一个相应的FormBean:GuestArtForm.java,一个提交游客评论的Action:PostGuestArtAction.java,一个游客每次提交评论成功后的cookie写入方法,可以把这个方法归入到util包,为了高效,单独建一个类CookieManager.java,方法的名字就是writeCookie(Ojbect cookieInfo),然后,在用户以后来访问的时候,有一个读取cookie信息的方法:Object readCookie()也放在CookieManager中,同样。在这里,读了cookie还有一个传入游客评论frame页面的过程,这时,又需要建立一个保持cookie信息的GuestInfo.java

3),为了把游客的评论归入系统的单独一个游客帐户统一管理和简化实现,关健是要把“名字(必须),邮件(必须),网站(可选)”字段以特殊的标记加在内容前面,要显示时再把这些字段分离出来(日记的作者和管理员可以看见这些特殊内容),而且这个过程对用户来说是透明的。

初步设想如下:

存入数据库格式:


[guest]

 [name]

   littlebat

 [/name]

 [gemail]

   mdx-xx@tom.com

 [/gemail]

 [site]

   http://java.learndiary.com

 [/site]

[/quest]

评论内容

分离数据方式:

用正则表达式分离[guest]和[/guest]之间的内容,再用正则表达式把各个字段分离出来封装进上面保持游客cookie信息的GuestInfo.java类中。这个类的对象传入显示页面再读出来进行显示。

游客评论的显示格式为:标题  <a href=游客网站>游客名字</a> 发表时间

4、实现步骤:

1),依次完成GuestArtInfo.java,GuestInfo.java,CookieManager.java,GuestArtForm.java,PostGuestArtAction.java

2),完成jsp页面

3),测试和发布

5、时间:

想做就做,做完为止。

学习日记网站新导航系统设想

1年前冒失的搞一个Struts动态导航系统,现在看来是一个错误的设计。这里把新的导航系统的大概构思理一下。

1、需要导航的页面:

1)显示目标内容的页面:

如“ 学习日记开发小组需求分析设计区”。需要:首页,目标下的所有日记列表,目标下的我的日记列表,按当前选定排序的“上一目标”和“下一目标”;写作目标下的日记,评论目标,修改目标的评论,修改目标内容。这里,写作目标下的日记完成后,如果选择查看日记,系统就进入了日记内容的导航,目标页面的导航条目消失;评论目标,修改目标的评论,修改目标内容,这3个都是直接返回的目标内容页面,仍然是目标的导航条;

2)显示目标下的所有日记列表:

如: 学习日记开发小组需求分析设计区的相关日记 。需要:首页,所在目标,目标下的我的日记列表,按当前选定排序的“上一目标”和“下一目标”的日记列表;还有写作日记的导航,作目标下的日记完成后,如果选择查看日记,系统就进入了日记内容的导航,目标页面的导航条目消失;

3)显示目标下的我的日记列表:

如: 学习日记开发小组需求分析设计区的我的相关日记。需要:首页,所在目标,目标下的所有日记列表,按当前选定排序的“上一目标”和“下一目标”的我的日记列表;还有写作此目标下的日记的导航类上;

4)显示日记的内容:

如:学习日记网站新导航系统设想。需要:首页,所在目标,所在目标下的所有日记列表,所在目标下的我的日记列表,写作所在目标下的日记,修改日记,添加日记的评论,修改日记的评论。其中修改日记,添加日记的评论,修改日记的评论完成后会回到显示日记的页面。另外,还有按当前选定的日记排序方式的同在一个目标的上一篇日记和下一篇日记。为了提供一个日记页面导航的一致性,减少复杂度,就不要提供所在目标的我的日记列表的上一篇和下一篇日记了。

2、设计方法:

1)原来导航系统里可以利用的方法就利用,如果改动较大就重写;

2)重写的部分要注意一个问题,不要在java文件里写生成页面的html元素的代码,这个错误是我前几天看一篇好像是jsp编码规范之类的文章看见的,大概意思是java文件和jsp文件的功能要尽量分开;

3)生成的导航系统的各种导航条目不要集成在一起,一个一个的分散开来,到时可以任意组合和修改。而且要考虑有可能进行的页面美化操作和导航部分代码不要发生冲突。

3、时间:

星期天之前完成并上线运行。因为我始终没有想好这次动态导航部分代码的剔除怎样在版本控制中进行,这些代码的改动暂时不提交到cvs库。或许,可以把剔除原来动态导航之前的代码作成一个release?当然,这个release是不能见人的,初学者也不能看,看了要中毒,只能自己收藏。

昨天去掉了网站的动态导航参数并做301定向

昨天,早上花了三个小时,晚上还花了大约两个小时,终于把原来网址中的动态导航参数暂时去掉.并把原来带参数的网址301重定向到http://java.learndiary.com中的不带参数的网址.因为原来动态导航部分与原来的代码的耦合还算小,直接把那部分注释掉就行了.基本上没有作其它改动.原来导航用的一些方法都还在里面,只不过没有调用罢了.

这些改动还没有反映到cvs库中去,因为对版本控制不熟,我在考虑究竟怎么处理这种改动.

下面还有一个问题是主页的302定向问题没有解决,可以把现在的首页写成index.jsp,输入域名后系统直接定向到这个jsp文件,不经过Struts框架的重定向处理.这样就可以返回200 OK状态码.

但是在新的index.jsp文件中怎样把原来Index2Action.java中处理的全部代码都放在index.jsp处理,或者去调用一个javabean来处理,或者可以在index.jsp中能否直接调用Struts的Index2Action.java?我不知道,只有现学现用.我的编程知识的极度缺乏就暴露出来了.

还有,向空间商问一下,可以把我们的首页直接换成indexAction.do,这样,我就可以省了这一步了,因为我试了一下,如果直接调用http://java.learndiary.com/indexAction.do,就会返回200 OK状态码.

还有,现在看来,原来的URL调用路径还是没有处理对,像什么disGoalContentAction.do什么的应该尽量简化成:disGoal.do什么的.这样好记又好看,可能对用户和搜索引擎也更加友好.

我是否应该把这样的路径都改一下,然后把原来的网址都重定向到这个新路径,借着这次去掉动态导航参数的机会,不如把事情做彻底点.

简述怎样用argouml把学习日记的源代码反向生成类图

这里以学习日记的learndiaryV0.9.0.4为例,结合最新版的ArgoUML0.22简述一下怎么样从学习日记源代码反向生成类图。其它环境为:操作系统:redhat linux9.0,jdk1.4.2_12-b03(最新的jdk6在ArgoUML0.22下工作起来据我使用好像有点问题)。

1、选择档案->汇入原始码:

2、在出现的“汇入原始码...”浏览对话框中选定源代码顶层目录:./learndiary/src/com:

3、在出现的“setup the import classpath”对话框中手工逐个把学习日记涉及到的类库加进去:



我加了的类库有:

1)Tomcat5.0中common目录下的:common/lib/servlet-api.jar

2)学习日记源码涉及到的类库,都在 ./learndiary/web/WEB-INF/lib下面,包括(保险起见,都加吧:)):

activation.jar          commons-logging.jar    jstl.jar                             standard.jar

antlr.jar               commons-validator.jar  log4j-1.2.12.jar                     struts-el.jar

commons-beanutils.jar   CVS                    mail.jar                             struts.jar

commons-digester.jar    jakarta-oro.jar        mysql-connector-java-3.1.12-bin.jar

commons-fileupload.jar  jdom.jar               rome-0.8.jar

(注:这是现在cvs库中的最新版,里面有些类库是learndiaryV0.9.0.4没有的,你如果用learndiaryV0.9.0.4的话就可以不加。)

这个过程有点麻烦,也是argouml需要改进的地方,还有,加了第一个路径后,你会发现对话框跑到主界面后面去了,你加下一个的时候需要在任务栏上的相应图标上点一下才能使它成为当前对话框继续添加classpath。

4、把classpath添加完后,点击OK,你就可以把源代码反向成类图了,这个过程可能要花几分钟,可要耐心点哟:)

这样,完成反向工程了。但是,因为argouml现在还在开发中,还没有达到一个成熟的V1.0版,据我的经验,反向的类图如果再正向生成代码是通不过编译的,比如,在类com.learndiary.website.util.Util.java中

反向后的类文件头部为:


package com.learndiary.website.util;

import byte[];

import String[];

而真正的原始文件头部为:


package com.learndiary.website.util;

import java.security.MessageDigest;

import java.util.Random;

这显然是不对的。但是,其它的绝大多数类是正确的。所以我认为,ArgoUML现在作为一个uml基础知识的学习工具和一些不需要双向生成类图和类的简单应用中可用。也就是说,我认为ArgoUML还不是一个可用的生产版本!

下面征对一个朋友的提问“servlet和struts的包是如何导入到ArgoUML中”来说一下怎样单独把这些类库反向工程成类图。

1、同上面的第1步同;

2、在同样的“汇入原始码...”浏览对话框中的“select language for import”中选择“java from classes” :

3、在出现的“汇入原始码...”浏览对话框中选定你要反向工程的类库,比如下面的struts.jar:

4、在出现的“setup the import classpath”对话框中手工逐个把编译这个类库涉及到的其它类库加进去,因为我不清楚struts.jar都需要依赖什么其它类库,所以把Struts的lib目录下的所有jar文件都加进去了,外加Tomcat5.0下面的那个:common/lib/servlet-api.jar(我也不知道是不是该用J2EE中的servlet相关的那个类库?或者用这个就行了?)

因为,我对UML的应用仅限于非常基础的类分析和活动分析,用于在后来加入的部分模块的设计中理清思路。我觉得对我来说ArgoUML已经够用了。而且,我的使用过程中也有一些肯定不正规的甚至错误的UML应用,还希望看到的朋友能够指点一二。我的电子邮件为:mdx-xx@tom.com,你最好是在网上给我留言。谢谢。

提交事件21,建了数据库表和bean,database 操作类

思路来自: 明确网站定位,增加学习日记目标分组功能

向开源社区提交了issue 21:

http://learndiary.tigris.org/issues/show_bug.cgi?id=21

The all different goals can be organized by group, in this way, user can get the

outline of a website which running LearnDiary.

Add some Top 10 statistical data of website, such as top 10 newly created

diaries, top 10 most posting diaries' user, etc..

今天完成了相关数据库表建立,一个bean模型,和bean模型的数据库存取类。延续原来的入门级设计方法,快速实现需要的功能。

还是以前的思路,软件应用为先。

学习日记的目标分组功能和Top10日记分类功能设计

根据思路: 明确网站定位,增加学习日记目标分组功能 ,现对学习日记的目标分组功能和Top10日记分类功能进行设计描述。

1、目标分组的建立应该由网站的管理员进行,应该包括下列功能:

1)、创建分组;2)删除分组;3)修改分组;4)分组有优先级别,也可以修改优先级别;

分组的数据表结构:

分组ID(groupID), 分组名称(groupName),分组描述(groupDetail),分组优先级(groupPriority),分组目标数(groupGoalsNum),分组创建日期(createDate),分组修改日期(modifyDate)。以后,还可以添加分组组长的分类组织者;

为了简化实现,初步可以只有创建功能,只要3个必要字段:groupID, groupName, groupPriority。分组的排列以groupPrior为准。

然后,在目标帖子的表中添加一个字段(groupID),因为目标帖子有一个parentID是没有意义的,看是否可以把这个字段来作为groupID;

这样,需要管理员对目标帖子有编辑权限,可以把原来的目标帖子归入分组,没有归入的加入未分类分组。

2、TOP10日记功能:

1)、最新10篇日记,最热门的10篇日记,随机的10篇日记,这些可以通过数据库查询实现。

其中,前两个可以通过那个只返回ID和名称的好像叫getCPageList()的方法来实现;后面的那个可能需要新加一个方法,来返回随机10篇帖子的ID和名称。

3、实现以上功能需要严格测试是否会暴露私人帖子。人的隐私权(人权)优先嘛。

4、由于以上改动,目标内容页面也需要精心设计,把目标相关的内容都要一目了然的呈现给用户,这个页面的广告位设计也要好好考虑一下。

能够想到的都写上了。没有想到的希望看见这篇帖子的朋友提一下。

原来的列表式目标可以作为另一个老的视图保留。