佳礼资讯网

 找回密码
 注册

ADVERTISEMENT

查看: 2557|回复: 17

[Java]miniblog架构设计,结合了Spring, Hibernate & Wicket.

[复制链接]
发表于 17-11-2007 02:37 PM | 显示全部楼层 |阅读模式
最近设计了一个网页架构,想想可能这里的网友有需要,所以我就稍微弄了一个叫miniblog,先说明你一点,我会以我的知识乱乱胡扯一番,请你用你的智慧去读,如有不对的地方欢迎多多批评及赐教。在此我先谢过了,客气的话就不多说了,开始咯!

miniblog 介绍
==========
Blog 是什么?相信大家都知道,而miniblog是一个超级简单版本,你可以建一个用户,然后你就可以写blog. 就只有这些功能而已?对,没错,因为这篇文章主要不是建一个完整的blog程序,而是讲解一个网页设计架构,这包括了如何结合Spring[1], wicket[2]和hibernate[3]的应用,layering技术,还有一些包装(maven[4])等等。注意:这片文章不会有很详细的解说spring, wicket和hibernate, 只是带过而已,因为它们很广,不是三言两语就能搞定。

Spring
Spring的核心是Dependency Injection(DJ), 我将会用Spring在layering上,把layers的关系做到loosely coupled. 以下会有更详细的解说。

Wicket
wicket是web application framework的新贵,在于html和代码有非常好的区分,support markup inheritence, 还有很强的Ajax功能等等(太多了,我也不一一介绍)。我在这论坛提过wicket无数次,应该有人留意到吧?

Hibernate
Hibernate虽然不是出自于豪门(jcp.org),但无可否认它的独特,超强功能已经成了市场上最红的ORM(Object Relationship Mapping),迎头而来自于豪门的JPA(e.g OpenJPA)看来还需时间融入市场吧。我本人超讨厌openJPA的enhancer. No way, man!

Maven
用它的人对它真的又爱又恨,但铁一般的事实是它还是目前最好的software project Management tool.恨它的人通常在做复杂的customizing build, 还有有时它会break. 我个人对它没意见,因为我是小鸟用它的地方不会很复杂,它还应付的来. 好了,把这些重要的东东一一介绍后,我们向Domain Model出发吧。

[1]http://www.springframework.org/
[2]http://wicket.apache.org/
[3]http://www.hibernate.org/
[4]http://maven.apache.org/

Domain Model
===========
先说一小段故事。身为programmer, 我们有一种习惯就是对App(Application)的domain缺乏兴趣,常常把domain也忽略了甚至把它留给商业专家去从顾客那里拿domain的资料,我们呢就是爱把大部分时间专注于technology,用technology解决domain的问题,没有好好去理解domain和modeling domain。讽刺的是,一个App的成败往往在于你和你的team对domain的理解有多少,因为每个App都是帮用户解决domain相关的问题。如果App的domain模糊不清,你别想能满足你的用户!最近市场上,人人都热烈地讨论着Domain Driven Design[1](DDD), DDD不是新东西已经是N年前的事了,只是最近越来越多人开始认同DDD. 说到DDD我非提不可Eric Evan[2]的DDD书[3],强力推介给大家,这可是一本经典图书啊!值得一提的是,Qi4j[4] 和Naked Objects[5] 都是以DDD为中心点。看来,新的programming的方式即将到来。

把话题转回miniblog, 我是miniblog的开发者也是用户,所以我可以完完全全地把domain忽略掉,这有意思是吧?哈!哈!哈!miniblog的domain是超简单的啦,只有user和blog, 每个user可以写很多blog, 他们的关系是one-to-many. 就这些而已,看来我是无需给更多的解释了,搞定!我们转下一个主题吧!

[1]http://www.infoq.com/presentations/model-to-work-evans
[2]http://domainlanguage.com/about/ericevans.html
[3]http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215
[4]http://www.qi4j.org/
[5]http://www.nakedobjects.org/

Layering设计
=========
说到layering这玩意,miniblog需要嚒?当然,我这miniblog小东西是不需要的啦,因为设计方面需要下点功夫还有一定的难度,对于小东东有一点不过实际而且浪费时间,但对于大的程序这是非常重要的一部分。等下我给理由。那为什么要layering呢?Layering的主要的好处是可以把复杂的东西变成简单,把东西分成几个layers,上面的layer依靠下面的layer, 这样一来就没有所谓的循环关系(circular dependencies)。通常我们是用interfaces加package区分来做到这点,而implementation是hidden的,但自从DI面世后,用DI在这方面设计是最理想不过了。在这里我会用到Spring, 请看以下图片:



我把miniblog的core分成三个layers:

DAO Layer
这个layer很有趣,它是用来隐藏DAO的implementation, 这样你可以用hibernate, JDO, JPA,或者Spring 的DAO Support 等等. 这对于大的App是很重要的,例子:你负责一个realTime app, 需把大量的realtime data存进database, 你在犹豫着hibernate是否能胜任,万一不行的话,是否有另一个方案?如果改的话,又会影响到多少个地方?我可以肯定如果你的App没有layering的话,会很多代码需要更改,有layering,你无需担心,因为只有DAO layer需要更改而已,其它的layer原地不动。你能抓到这点吗?

以下是miniblog的DAO layer 的代码:

BaseDao.class
  1. public interface BaseDao<T extends Identifiable>
  2. {
  3.     T get( int id );

  4.     void save( T t );

  5.     void update( T t );

  6.     void delete( int id );
  7.    
  8.     void delete( T t);

  9.     List<T> findAll();

  10.     List<T> findAll( FindFilter findFilter );
  11.    
  12.     List<T> find(T filter, FindFilter findFilter );

  13.     int countAll();
  14.    
  15.     Class<T> getTypeClass();
  16. }
复制代码
UserDao.class
  1. public interface UserDao
  2.     extends BaseDao<User>
  3. {
  4. }
复制代码
BlogDao.class
  1. public interface BlogDao
  2.     extends BaseDao<Blog>
  3. {
  4.     List<Blog> findAll( User user );

  5.     List<Blog> findAll( User user, FindFilter findFilter );

  6.     int countAll( User user );
  7. }
复制代码
Service Layer
Service Layer在miniblog扮演着中间人(presentation和DAO Layer),它同时也负责管理business logic(例如:validation & contraints), 这layer依靠DAO Layer, 而Spring在这里扮演了一个重要角色,那就是插入DAO layer的implementation. 请看以下service layer的代码:

BlogService.class
  1. public interface BlogService
  2. {
  3.     int countAll( User user );

  4.     List<Blog> findAll( User user );

  5.     List<Blog> findAll( User user, FindFilter findFilter );

  6.     void updateBlog( Blog blog );

  7.     void saveBlog( Blog blog );

  8.     Blog getBlog( int id );

  9.     void deleteBlog( int blogId );
  10. }
复制代码
BlogServiceImpl.class
  1. public class BlogServiceImpl
  2.     implements BlogService
  3. {
  4.     private BlogDao blogDao;

  5.     public BlogServiceImpl( BlogDao blogDao )
  6.     {
  7.         this.blogDao = blogDao;
  8.     }

  9.     public int countAll( User user )
  10.     {
  11.         return blogDao.countAll( user );
  12.     }
  13.   ...
  14.   ...
  15. }
复制代码
Presentation Layer
这是miniblog最高的layer, 里面有wicket的components,它依靠service layer提供data或者透过它来修改data. 和Service Layer, 这layer也是透过Spring插入Service layer 的implementation. 请看以下的某些代码:

UserRegisterationPage .class
  1. public class UserRegisterationPage extends BasePage
  2. {
  3.     @SpringBean(name = "userService")
  4.     private UserService userService;

  5.     private BasePage goBackPage;

  6.     public UserRegisterationPage( BasePage goBackPage )
  7.     {
  8.         this.goBackPage = goBackPage;

  9.         initComponents();
  10.     }
  11. ...
  12. ...
  13. }
复制代码
Layering看以很好,但不是绝对的,做layering时,应该考虑以下问题,例如:

- 在DAO Layer, 换hibernate去jdbc的几率有多高?
- 到底你和你的team能layering到有多好?有多效率?

Next, 结尾。

结尾
====
这网页设计架构是非常普遍,你可以在网络找到很多类似的app。手累了,我也不多说了。不管写的好不好,欢迎大家comment.你们的热情是我写下去的动力。当然我也希望大家也能分享你们的知识!

参考
- Pro Wicket
   http://www.amazon.com/Pro-Wicket-Experts-Voice-Java/dp/1590597222
- Spring in Action, Second Edition
   http://www.manning.com/walls3/
- DDD
   http://www.amazon.com/Domain-Dri ... tware/dp/0321125215

代码下载
========

代码基本要求
- jdk1.5 or above
- Maven 2.0 4 or above (别忘了加入你的path)
- Eclipse 3.0 or above (你可以用maven 来generate netbeans或者IDEA 的project file. e.g mvn idea::idea)

代码下载地址
http://rapidshare.com/files/70275363/miniblog.rar.html

注意项目
-下载了, 打开command prompt, 然后execute command, mvn clean install, maven会把所需要的jar dependencies一一下载到你的maven m2 repository.

- 如果你是用Eclipse打开这miniblog的话,别忘了加Classpath Variables

  e.g Window->Preferences->Java->Build Path->Classpath Variables->New..
  
  Name = M2_REPO
  Path = C:/Documents and Settings/blackwood/.m2/repository

-在org.miniblogpackage里面有一个MiniBlogLauncher,你可以直接run它。这miniblog是用jetty  erver,database 是hsqldb(In memory mode), 所以你省去很麻烦, 直接可以run。

- 有问题的话,post上来,我或者有经验的网友会帮你们解决问题。

谢谢!

[ 本帖最后由 黑木头 于 17-11-2007 02:39 PM 编辑 ]
回复

使用道具 举报


ADVERTISEMENT

发表于 18-11-2007 01:22 AM | 显示全部楼层
终于看到你发功了,黑兄。 今天佳礼很卡,一直没办法回复,觉得佳礼可以考虑一下升级至企业级的系统了。
我一直对Web框架的选择举棋不定,Struts, WebWork, Tapestry, Wicket, JSF... 没办法选择。所以,我目前只是JSP+Spring MVC+Ext,对于我来说,SpringMVC已经很够了。

至于DI,还是最爱Spring,Spring重来没有什么东西是让我觉得不满意的... 几乎想到什么他就能给到什么... 也很少会出现问题。虽然说,Bob Lee的Google Guice也有很高的评价而且证明效能比Spring快,但是还是爱他... 而且超级期待2.5.... 效能将会获得提升而且加入了OSGI支持.... 有一个超有潜力的技术,有机会再讨论它.

我看过Pro Spring这本书,你的miniblog的idea是来自那里吗?
回复

使用道具 举报

 楼主| 发表于 18-11-2007 08:51 PM | 显示全部楼层
原帖由 苦瓜汤 于 18-11-2007 01:22 AM 发表
终于看到你发功了,黑兄。 今天佳礼很卡,一直没办法回复,觉得佳礼可以考虑一下升级至企业级的系统了。我一直对Web框架的选择举棋不定,Struts, WebWork, Tapestry, Wicket, JSF... 没办法选择。所以,我目 ...


什么终于看到你发功了,你满会搞笑的!哈!哈!你真有意思!对,市场上java的Web框架真的太多了,就看你和你的team专那一个就用那一个,因为它们都是各有千秋,各有各的好,很难判断!虽然我是这么说,但我还是老样子,极力推荐Wicket, 因为Wicket真的太好用了,你不妨看看考虑一下。顺便一提,terracotta 也有Wicket的integration[1], 看来Wicket还真的不赖哟!

至于DI,还是最爱Spring,Spring重来没有什么东西是让我觉得不满意的... 几乎想到什么他就能给到什么... 也很少会出现问题。虽然说,Bob Lee的Google Guice也有很高的评价而且证明效能比Spring快,但是还是爱他... 而且超级期待2.5.... 效能将会获得提升而且加入了OSGI支持.... 有一个超有潜力的技术,有机会再讨论它.


Spring真的是超强, 我也爱用它, 对它除了XML file之外(现在已经有annotation了),其它的都没问题。不懂你有留意到吗,Google Guice已经有persistence support(hibernate3 和JPA)[2], 还真快, 看来Spring将会面对越来越多来至于Google Guice 的挑战, 对用户而言,这当然是一件好事!期待着。。

我对OSGi也有一点认识,虽然谈不上精通,但也可以吹吹牛。OSGI在Enterpise App上还没有很完善的support, 例如:OSGi没有object serializable的spec, 这对RMI(Remote Method Invocation)这样的Technology来说是有问题存在,但这很快就会成为过去,因为OSGI有了一个叫Enterprise Group team, 专门研发/解决这方面的问题。另外,OSGI缺乏IDE plugin, 除了Eclipse对自家Equinox PDE,其他的像Felix和knoplerfish就没有。有趣的是,有人把OSGI plugin 放在Intellij IDEAL Plugin Contest 2007 的wishList[3].看来,OSGI用户真的需要这东东。Em..要把app真真的用OSGi modularize化,还是挺吃力,不简单,OSGI spec 还需要简明化及方便化,不然市场上的接受度还需要时间。

我看过Pro Spring这本书,你的miniblog的idea是来自那里吗?


苦瓜汤,你好眼光啊。对,在Pro Spring 的例子也是用非常类似的设计,就如我说的这网页设计架构是非常普遍,但我的idea不是来自那里,因为我写miniblog的时候是没有参考它。我读它已经是一到两年的是事吧。本人觉得这本书不太好有一点乱,建议还是Spring in Action比较详细和建设性。

[1]http://www.terracotta.org/confluence/display/integrations/Home
[2]http://www.wideplay.com/guicewebextensions2
[3]http://plugins.intellij.net/wishlist/item/?wid=93

[ 本帖最后由 黑木头 于 18-11-2007 08:59 PM 编辑 ]
回复

使用道具 举报

发表于 20-11-2007 07:33 PM | 显示全部楼层
有个Wicket的小疑问,我用maven的jetty plugin来run wicket的app,若是我的Application configuration是DEVELOPMENT的话,jetty应该会定时自动帮我加载所有的class的变动是吗?为何我的jetty在我更改了一些源码之后没有动静,搞到我每次都要restart jetty....
回复

使用道具 举报

 楼主| 发表于 20-11-2007 09:48 PM | 显示全部楼层
原帖由 苦瓜汤 于 20-11-2007 07:33 PM 发表
有个Wicket的小疑问,我用maven的jetty plugin来run wicket的app,若是我的Application configuration是DEVELOPMENT的话,jetty应该会定时自动帮我加载所有的class的变动是吗?为何我的jetty在我更改了一些源码 ...


Jetty是不会加载所有变动class的,因为这是classloading的问题,Jetty还不是OSGI化,如果是的话可能吧。 在Wicket里Application configuration=DEVELOPMENT是指html files.

它有这个指令,如果我没记错的话是方便你debug(因为有error出现时,会有很详细的线索例如:那一个added component忘了加markup id在html file等等, 另一个原因就是reload变动(根据最后更新时间)的html files 。Wicket只在DEVELOPMENT mode会reload变动的html files是因为这项目会很消耗时间,例如:parsing, 还有store 在secondaryCache里等等。这也是为何当你的application是development mode时, 它会给你警告“千万别用development mode 在production application".

顺便一提, Pro Wicket 这本书不是很好,等Wicket In Action 这本书吧!快要出了!

看来你已经开始看wicket了,欢迎!
回复

使用道具 举报

发表于 22-11-2007 10:19 AM | 显示全部楼层
原帖由 黑木头 于 20-11-2007 09:48 PM 发表


Jetty是不会加载所有变动class的,因为这是classloading的问题,Jetty还不是OSGI化,如果是的话可能吧。 在Wicket里Application configuration=DEVELOPMENT是指html files.

它有这个指令,如果我没记错的 ...


对啊,我觉得还满容易用的... Customize Component也只是一个JavaCode和HTML模板... 而且没有XML...
对了,用Annotation调用SpringBean好简单哦
回复

使用道具 举报

Follow Us
发表于 22-11-2007 10:50 AM | 显示全部楼层
黑兄,看来Spring在这里的知名度还不高... 想请你开个Spring专区推广一下
回复

使用道具 举报

 楼主| 发表于 22-11-2007 03:23 PM | 显示全部楼层
原帖由 苦瓜汤 于 22-11-2007 10:19 AM 发表


对啊,我觉得还满容易用的... Customize Component也只是一个JavaCode和HTML模板... 而且没有XML...
对了,用Annotation调用SpringBean好简单哦

黑兄,看来Spring在这里的知名度还不高... 想请你开个Spring专区推广一下


尽力而为,哪怕你是唯一的读者。

对Wicket的Spring annotation是做到非常方便,Wicket的开发者在这方面真的下了不少功夫,为什么这样说呢?原因是,Wicket的component全都是serializable, 在serializable环境里下,只有两种方法可以逃过被serialized, 第一是你用transient, 第二是把你的class variable改成static variable, 这样就能避免被serialized。

话说回来,Wicket的Spring support 是用第二种方法加proxy解决not serializable bean, 这样你就能少去了很多不必要的serializable的问题。

建议你看看wicket-ioc(Inversion of Control)还有Component的IComponentInstantiationListener, 有很多好料在里面。
回复

使用道具 举报


ADVERTISEMENT

发表于 26-11-2007 09:52 PM | 显示全部楼层
惨了,越来越爱上Wicket了... 太好用了。
遗憾的是还想不到要如何跟ext结合... 尝试做一个ExtDataGridView....但是太眼高手低了... 我的ext

黑兄,想请教一个问题,请问Hibernate的session在Wicket内是如何运作的?为何我没有遇到和SpringMVC结合时session expired的问题?
回复

使用道具 举报

 楼主| 发表于 28-11-2007 10:00 AM | 显示全部楼层
原帖由 苦瓜汤 于 26-11-2007 09:52 PM 发表
惨了,越来越爱上Wicket了... 太好用了。
遗憾的是还想不到要如何跟ext结合... 尝试做一个ExtDataGridView....但是太眼高手低了... 我的ext

黑兄,想请教一个问题,请问Hibernate的session在Wicket内是如何运作的?为何我没有遇到和SpringMVC结合时session expired的问题?


看来只有去试才有新发现. 恭喜你!

我没用过SpringMVC, 也不大清楚你的问题。你说的session expired 是指[size=-1]HttpSession还是hibernate 的session, 据我所知,hibernate的session 是不会expired的, 但是hibernate的second level cache 是有这样的东西 (Expiry Policy?).

不过没关系,我还是可以回答你问题。 在miniblog里hibernate session的life time 是long running,简单地说是每当有form submit 时,Spring会用回同样的hibernate session. 我是用Spring的HibernateDaoSuppor加TransactionProxyFactoryBeant帮我做到这点. 非常方便.Long running Session 的好处是,它会帮我们的object放到cache里面,这样就能提高效力.

如果你所遇到的问题是httpsession expired, 我可以说这也和SpringMVC无关,那是问题出在tomcat或者是Jetty的configuration. 因为只有servletcontainer是负责建httpsession,而不是web application framework (包括了Wicket,Spring MVC, struts etc).

以上都是从我所知道回答,没经过证实,错了请见谅!
回复

使用道具 举报

发表于 28-11-2007 10:52 AM | 显示全部楼层
我想起来了,如果Entity内的mapping有用到Lazy Fetch的话就有问题。这一点我觉得很奇怪,在需要到child entity的时候hibernate session就已经closed了。

刚刚用Spring的OpenSessionInViewFilter解决了 好可爱的Spring啊
  1.     <filter>
  2.         <filter-name>hibernateOpenSession</filter-name>
  3.         <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
  4.         <init-param>
  5.             <param-name>sessionFactoryBeanName</param-name>
  6.             <param-value>mySessionFactory</param-value>
  7.         </init-param>
  8.         <init-param>
  9.             <param-name>singleSession</param-name>
  10.             <param-value>false</param-value>
  11.         </init-param>
  12.     </filter>
  13.     <filter-mapping>
  14.         <filter-name>hibernateOpenSession</filter-name>
  15.         <url-pattern>/*</url-pattern>
  16.     </filter-mapping>
复制代码
回复

使用道具 举报

发表于 11-12-2007 10:20 AM | 显示全部楼层
我最拿手的是Struts
现在给你们讲到Samyukyuk想去看Wicket
回复

使用道具 举报

发表于 19-4-2008 06:57 PM | 显示全部楼层
对不起打扰了, 有个个人要求, 希望各位Java高手好像 黑木炭,苦瓜汤, netmercury,  amadeus82, winmxaa 开一个帖来讨论 wicket , tapestry , struts ..
hibernate, openjpa  .. spring 的比较与功能的概括层次 (UI framework , ORM framework , MVC framework etc)

目前正为了选择这些东西头疼, 我是想开发一个 Web-based ERP 系统。希望大家可以抛砖引玉, 让我这个Java 新手, 了解这些的pro & con , 未来的方向与潜能等等。。我相信集大家的意见,帖子必定能成为cari 的 Java 精华。
回复

使用道具 举报

发表于 21-4-2008 09:30 AM | 显示全部楼层
我很喜欢wicket,真的好难得在这里可以看见wicket的帖子!miniblog.rar好像下载不到哦,可以弄弄它吗?顺便介绍一下databinder ->> http://databinder.net/.
wicket本身必须通过spring或其他方法来连接hibernate, databinder是其中之一, 而且databinder提供了一些很好用的component,大家不妨去试试!
回复

使用道具 举报

发表于 21-4-2008 09:40 AM | 显示全部楼层
如果要让wicket 自动 reload classes(不需要restart server),可以用 ReloadingWicketFilter.

ReloadingClassLoader.includePattern("com.*");
ReloadingClassLoader.excludePattern("com.session*");
ReloadingClassLoader.excludePattern("com.bo.*");

必须exclude你的bo和session class.
回复

使用道具 举报

发表于 24-4-2008 04:45 PM | 显示全部楼层
原帖由 jangancari 于 19-4-2008 06:57 PM 发表
对不起打扰了, 有个个人要求, 希望各位Java高手好像 黑木炭,苦瓜汤, netmercury,  amadeus82, winmxaa 开一个帖来讨论 wicket , tapestry , struts ..
hibernate, openjpa  .. spring 的比较与功能的概括层次  ...

框架在这里会比较冷
回复

使用道具 举报


ADVERTISEMENT

发表于 24-4-2008 04:47 PM | 显示全部楼层
原帖由 hanyiGhost 于 21-4-2008 09:40 AM 发表
如果要让wicket 自动 reload classes(不需要restart server),可以用 ReloadingWicketFilter.

ReloadingClassLoader.includePattern("com.*";
ReloadingClassLoader.excludePattern("com.session*";
Reloa ...


要不是Wicket的Testing Framework做得很好,我觉得我会吐血(其实吐了很多)。每次要看看result都要restart... 再加上Spring的loading
回复

使用道具 举报

发表于 28-4-2008 09:49 AM | 显示全部楼层
我觉得wicket真的很好玩,mvc太闷了。。。我准备换工作了,很想在工事上运用wicket。。。现在我的公司用的是jsf + spring...
要不是Wicket的Testing Framework做得很好,我觉得我会吐血(其实吐了很多)。每次要看看result都要restart... 再加上Spring的loading

wicket integrate with spring也可以自动reload classes的, 不过需要exclude你的spring classes.因为spring已经有本身的classLoader了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

 

ADVERTISEMENT



ADVERTISEMENT



ADVERTISEMENT

ADVERTISEMENT


版权所有 © 1996-2023 Cari Internet Sdn Bhd (483575-W)|IPSERVERONE 提供云主机|广告刊登|关于我们|私隐权|免控|投诉|联络|脸书|佳礼资讯网

GMT+8, 29-12-2025 05:46 AM , Processed in 0.294742 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表