|
查看: 2555|回复: 17
|
[Java]miniblog架构设计,结合了Spring, Hibernate & Wicket.
[复制链接]
|
|
|
最近设计了一个网页架构,想想可能这里的网友有需要,所以我就稍微弄了一个叫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- public interface BaseDao<T extends Identifiable>
- {
- T get( int id );
- void save( T t );
- void update( T t );
- void delete( int id );
-
- void delete( T t);
- List<T> findAll();
- List<T> findAll( FindFilter findFilter );
-
- List<T> find(T filter, FindFilter findFilter );
- int countAll();
-
- Class<T> getTypeClass();
- }
复制代码 UserDao.class- public interface UserDao
- extends BaseDao<User>
- {
- }
复制代码 BlogDao.class- public interface BlogDao
- extends BaseDao<Blog>
- {
- List<Blog> findAll( User user );
- List<Blog> findAll( User user, FindFilter findFilter );
- int countAll( User user );
- }
复制代码 Service Layer
Service Layer在miniblog扮演着中间人(presentation和DAO Layer),它同时也负责管理business logic(例如:validation & contraints), 这layer依靠DAO Layer, 而Spring在这里扮演了一个重要角色,那就是插入DAO layer的implementation. 请看以下service layer的代码:
BlogService.class- public interface BlogService
- {
- int countAll( User user );
- List<Blog> findAll( User user );
- List<Blog> findAll( User user, FindFilter findFilter );
- void updateBlog( Blog blog );
- void saveBlog( Blog blog );
- Blog getBlog( int id );
- void deleteBlog( int blogId );
- }
复制代码 BlogServiceImpl.class- public class BlogServiceImpl
- implements BlogService
- {
- private BlogDao blogDao;
- public BlogServiceImpl( BlogDao blogDao )
- {
- this.blogDao = blogDao;
- }
- public int countAll( User user )
- {
- return blogDao.countAll( user );
- }
- ...
- ...
- }
复制代码 Presentation Layer
这是miniblog最高的layer, 里面有wicket的components,它依靠service layer提供data或者透过它来修改data. 和Service Layer, 这layer也是透过Spring插入Service layer 的implementation. 请看以下的某些代码:
UserRegisterationPage .class- public class UserRegisterationPage extends BasePage
- {
- @SpringBean(name = "userService")
- private UserService userService;
- private BasePage goBackPage;
- public UserRegisterationPage( BasePage goBackPage )
- {
- this.goBackPage = goBackPage;
- initComponents();
- }
- ...
- ...
- }
复制代码 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 编辑 ] |
|
|
|
|
|
|
|
|
|
|
发表于 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好简单哦 |
|
|
|
|
|
|
|
|
|
|
发表于 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, 有很多好料在里面。 |
|
|
|
|
|
|
|
|
|
|
发表于 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啊
- <filter>
- <filter-name>hibernateOpenSession</filter-name>
- <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
- <init-param>
- <param-name>sessionFactoryBeanName</param-name>
- <param-value>mySessionFactory</param-value>
- </init-param>
- <init-param>
- <param-name>singleSession</param-name>
- <param-value>false</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>hibernateOpenSession</filter-name>
- <url-pattern>/*</url-pattern>
- </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 的比较与功能的概括层次 ...
框架在这里会比较冷 |
|
|
|
|
|
|
|
|
|
|
发表于 24-4-2008 04:47 PM
|
显示全部楼层
|
|
|
|
|
|
|
|
|
|
发表于 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了。 |
|
|
|
|
|
|
|
|
| |
本周最热论坛帖子
|