JiveJdon的CRUD流程实现
主题贴/根贴/首贴定义:第一个帖子,没有父贴;一系列帖子的根贴;
回帖:回复帖子,一定有父贴。
一般论坛显示时,从主题贴开始显示一系列的帖子,一系列帖子称为一个Thread;好像这些帖子是穿在一条线上。
模型的区分
前面我们设计了帖子的模型是ForumMessage,现在需要在ForumMessage中进行主题贴或回帖的区分,有多个方法进行区分:
在ForumMessage增加字段isTopic来进行判断,这种设计其实可能为日后增加if else的判断。
我们建立两个模型ForumMessage代表主题贴;而ForumMessage的子类ForumMessageReply代表回帖。这两个模型只有在创建时才严格分开;而在修改删除和查询时,都是以ForumMessage为代表,是否回帖等属性则属于帖子关系范畴,我们后面专门就帖子的树形关系建模(为TreeModel)。
数据库区分
在JiveMessage表中如下结构:
CREATE TABLE jiveMessage (
messageID BIGINT NOT NULL,
parentMessageID BIGINT NULL, //缺省是NULL
threadID BIGINT NOT NULL,
……
}
其中parentMessageID和messageID记录帖子之间的父子关系。如果该贴是根贴,也就是主题贴,那么parentMessageID就表示为NULL。
当是主题贴时,parentMessageID这个字段我们就不插入任何值,让其为缺省值NULL;而是回帖时,则插入parentMessageID值。
因此,在MessageDao中,有两个方法:
//插入主题贴
void createMessage(ForumMessage forumMessage);
//插入回帖
void createMessageReply(ForumMessageReply forumMessageReply);
这两个实现方法唯一区别就是SQL语句中是否有parentMessageID字段。
以后,有必要将表示树形结构的数据库ID和parentID独立出来,专门形成一个数据表,message中已经设计的parentID弃置不用,独立出来从性能上说好处也大,否则查找某个帖子的单独的树形关系,还要在message表中查询,而message表结构是包含body帖子内容大型数据表,应尽量避免。在目前开发工作中进行分离工作会分散重点,只要我们编程时留有可拓展的余地即可。
创建帖子
在进行方法权限访问设计时,尽量将功能需求细分到方法,原来我们设计时,创建新贴都是在ForumMessageService类的createMessage一个方法完成,但是考虑到业务需求,在有些情况下,论坛管理者可能不希望普通注册用户有发言权力,只能有回贴,例如当该系统使用在文章发布系统就存在这样的需求。
因此我们有必要将createMessage划分成两个方法:
//创建一个主题贴
void createTopicMessage(EventModel em);
//创建回帖
void createReplyMessage(EventModel em);
将主题贴创建和回贴创建两个权限分开有利扩展性,有利于权限设置,这样只要我们利用上节对不同方法的角色设置就可以实现对这两个不同权限的实现。
主题贴创建和回帖创建这两种方式主要区别还是处理parentID或parentMessage的区别,在处理这个问题上,如果前期对ForumMessage建模时没有看到这种区分,还是将主题和回帖认为用一个ForumMessage代表,那么就会在Service层产生一些噪音,会多不少if else判断,而且这种判断是危险的。我们首先分析这样的思路:
创建主题贴服务设计:
通过ForumMessageService的createTopicMessage方法实现,前台传入的ForumMessage只要有subject和body等具体内容即可,无需传入有关树形结构的参数,在createTopicMessage方法实现中,我们会将该FourmMessage的parentMessageID设为NULL,表示其是一个主题贴。
回帖创建服务设计:
通过ForumMessageService的createReplyMessage方法实现,前台传入的ForumMessage除了有subject和body等具体内容外,必须传入其父贴的ID号,在createReplyMessage方法内部根据父贴的ID号获得该回帖的其他信息,如回帖所在的ForumThread 所在的论坛Forum等,这些关系信息需要持久化保存到数据库中的。
将createMessage分成两个方法,涉及到表现层设计的变动,那么在Jdon增删改查框架下,如何实现一个Model,两个创建方法呢?
这里,我们还可以加一个前提限制:在不手工编制Action类的前提下如何实现,因为通过编码编写一个ModelHandler或Action是比较容易实现的,那有没有更简便的解决方法呢?
只有通过jdonframework.xml配置了,原来的配置如下:
<model key="messageId"
class="com.jdon.jivejdon.model.ForumMessage">
<actionForm name="messageForm"/>
<handler>
<service ref="forumMessageService">
<getMethod name="findtMessage"/>
<createMethod name="createMessage"/>
<updateMethod name="updateMessage"/>
<deleteMethod name="deleteMessage"/>
</service>
</handler>
</model>
现在我们要将creatMethod name的值改为createTopicMessage,那么createReplyMessage怎么配置呢?
再增加一行Model配置即可,不过注意,在Jdon框架中,相同Model的配置是否可以重复两行呢?所幸的是,Jdon框架中,只以Model配置中ActionForm为标识符,也就是主键的意思,只要ActionForm不一样就可以多行同一个Model配置。
我们将messageForm划分成两个ActionForm:messageForm和messageReplyForm,两个Form对应不同的Action Path,也就是不同名称的*.do,这样外界可以分别调用这个两种.do,当创建主题贴时,我们调用/message/messageAction.do;当创建跟贴是,我们调用/message/messageReplyAction.do。
jdonframework.xml配置一分为二,变成两种配置如下:
<model key="messageId"
class="com.jdon.jivejdon.model.ForumMessage">
<actionForm name="messageForm"/>
<handler>
<service ref="forumMessageService">
<getMethod name=" findtMessage "/>
<createMethod name="createTopicMessage"/>
<updateMethod name="updateMessage"/>
<deleteMethod name="deleteMessage"/>
</service>
</handler>
</model>
<model key="messageId"
class="com.jdon.jivejdon.model.ForumMessage">
<actionForm name="messageReplyForm"/>
<handler>
<service ref="forumMessageService">
<getMethod name=" findtMessage "/>
<createMethod name="createReplyMessage"/>
<updateMethod name="updateMessage"/>
<deleteMethod name="deleteMessage"/>
</service>
</handler>
</model>
当然,这涉及到原来的一个message.jsp需要划分成两个,因为message.jsp的Html:form表单中的Action值需要修改,这里也反应了Strut使用不够灵活。
message.jsp分为message.jsp和messageReply.jsp,将其中相当的表单内容使用include,这样求同存异,Jsp修改维护起来方便。
至此,第一套设计方案描述完毕,我们将其结构意图表现如下:

这个方案是基于一个Model ForumMessage 设计的,在界面段区分两个Action;然后在ForumMessageService中使用两个方法分别处理来自两个Action提交的请求。
这个方案唯一的缺点是:没有进行建立两个业务模型,而是使用一个,这就造成在ForumMessageService的两个方法中,需要对ForumMessage的父节点进行判断,这是危险和杂音,如果我们对主题贴和回帖的区分标志进行更改,将要涉及这段代码的修改,而且不能排除将来在其他地方更多的if else判断,这些其实源自我们的业务建模问题,所以,Service服务的设计其实应该是和Domain Model一起设计,而且如果业务建模正确;会导致Service代码是否简洁清晰。

如图,原来一个Model分为两个,这样改动也非常方便,只要改动一下jdonframework.xml配置就可以。
当然,界面模型ActionForm也可以分离成两个,但是可能比较琐碎,这取决于界面需求,这里ForumMessage的字段是按照ForumMessageReply设计的,因为在界面显示时,可以单独处理对象的每个字段,在这两个Jsp页面我们可以决定是否有ParentMessage这个字段,通过这种选择来决定两种模型的区别。
显示界面这样的字段细化和持久层字段细化也是类似的,一个完整的Domain Model对象在界面显示或数据库持久时,都会细化条目。