期待JForum3的到来!!JForum3火速前瞻
2008-05-31 22:30
393 查看
相信在项目中如果遇到必须使用java平台的论坛,很多人都会选择jforum。原因可简单归结为:
使用BSD许可证基于java平台,能在几乎所有的servlet容器上跑
支持多种类型数据库,还具有傻瓜式的安装方式
使用了缓存技术,表示层使用freemarker,运行速度相当快
支持SSO,可以自定义SSO实现,通过配置文件即可进行调整
为此我想我们应该感激Rafael Steil。因为项目需求,我开始了对jforum的二次开发和bug修改等工作,对它的框架、代码结构也在不断的理解。虽然项目暂时告一段落了,但是我还是很热衷关注jforum的发展,今天到官方网站上兜了几圈,找到了jforum3的svn代码库,最近2个月Rafael Steil的开发还是很活跃的http://fisheye2.atlassian.com/browse/jforum/trunk。为此虽然本人功力不深,但也很想写点什么表达自己看到jforum3的感受。
jforum3技术纵览
使用VRaptor2实现WEB MVC
页面渲染可能使用jsp+jstl+jforum-tags
bean管理终于用了spring
持久层使用hibernat,原来的缓存技术暂时没有在代码中看到
使用了流行的action/service/dao三层结构
从web.xml开始了解jforum3
<context-param>
<param-name>org.vraptor.url.LogicLocator</param-name>
<param-value>net.jforum.core.support.vraptor.DefaultLogicLocator</param-value>
</context-param
前面有提到过使用了VRaptor 2,关于这个框架,国内使用的人不多。但事实上,当我到它的官方网站去了解后,发现文档还是做的不错的,例子也很简单明了。LogicLocator是用来把request URI进行特殊解析后,得到LogicMethod的类。因为VRaptor 2默认的uri是person.add.logic这种形式的,而jforum经典的形式是/forums/list.page这种以"/"分隔的。LogicLocator.locate()返回一个LogicMethod,拿个和struts2相对应的比喻来说,就是action中的一个方法,一个url请求过来,执行action里面的一个方法。
<context-param>
<param-name>org.vraptor.url.ViewLocator</param-name>
<param-value>net.jforum.core.support.vraptor.DefaultViewLocator</param-value>
</context-param>
这个是LogicMethod执行完成后,返回的视图控制器,以forward、redirect等形式返回的视图选择就在这里面进行具体实现。
<filter>
<filter-name>hibernateSessionViewFilter</filter-name>
<filter-class>net.jforum.core.support.hibernate.OpenSessionInViewFilter</filter-class>
</filter>
这是大家熟悉的hibernate session管理方式,在chain.doFilter()前让sessionFactory为当前线程分配一个session,打开事务,chain.doFilter()之后如果操作正常着提交事务,关闭session。在jforum2.18中,类似的功能由servlet来完成,既执行具体的command前获得connection,放到JForumExecutionContext中(其实就是一个ThreadLocal),执行command结束后,如果启用了事务,则关闭事务,关闭connection。
当然,sessionFactory是有spring来管理的,这是一个AnnotationSessionFactoryBean,也就没有了hibernate 的mapping文件了,mapping都使用Annotation写在entity类里面。
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="annotatedClasses">
<list>
<value>net.jforum.entities.Category</value>
......
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
.......
</props>
</property>
<property name="eventListeners">
<map>
<entry key="load"><ref local="ForumRepositoryLoadListener"/></entry>
</map>
</property>
</bean>
<bean id="ForumRepositoryLoadListener" class="net.jforum.core.support.hibernate.ForumRepositoryLoadListener"/>
值得关注的是sessionFactory的eventListeners,这是为dao类注入sessionFactory属性的:
@Override
public void onLoad(LoadEvent event, LoadType type) throws HibernateException {
super.onLoad(event, type);
if (event.getEntityClassName().equals(Forum.class.getName())) {
this.dao.setSessionFactory(event.getSession().getSessionFactory());
((Forum)event.getResult()).setRepository(dao);
}
}
jforum3使用了hibernate做持久层,那么原来繁琐的dao编码将少了很多,若是需要进行数据库迁移,也是相当容易的事情了。关于dao类的分析,其实没什么可说的,和平常大家看到的spring+hibernate的代码没什么区别。下面再回到web.xml这个文件来,说说jforum3的核心控制器:
<servlet>
<servlet-name>jforum</servlet-name>
<servlet-class>net.jforum.JForumServlet</servlet-class>
<init-param>
<param-name>configuration.directory</param-name>
<param-value>/WEB-INF/jforumConfig</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>jforum</servlet-name>
<url-pattern>*.page</url-pattern>
</servlet-mapping>
从配置上来说,乍一看和jforum2.18没什么,都是一个servlet。但读到它的源代码,你会发现原来forum2.18在启动过程中超级复杂而乱七八糟的关系,一下子变得明了多了:
public class JForumServlet extends VRaptorServlet {
/**
* 初始化springContext、jforum的其他配置,以及VRaptor视图配置
* @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
*/
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
JForumBootstrap bootstrap = new JForumBootstrap();
bootstrap.run(this.getServletContext(), config);
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Introspector introspector = (Introspector)this.getServletContext().getAttribute(Introspector.class.getName());
VRaptorServletRequest wrappedRequest = new VRaptorServletRequest(request, introspector);
ApplicationContext springContext = (ApplicationContext)this.getServletContext()
.getAttribute(ConfigKeys.SPRING_CONTEXT);
ControllerUtils controllerUtils = (ControllerUtils)springContext.getBean(ControllerUtils.class.getName());
UserSession userSession = controllerUtils.refreshSession(request, response);
request.setAttribute("userSession", userSession);
request.setAttribute(UserSession.class.getName(), userSession);
request.setAttribute(ViewPropertyBag.class.getName(), new ViewPropertyBag(request));
request.setAttribute(ViewService.class.getName(),
new ViewService(request, response, (JForumConfig)springContext.getBean(JForumConfig.class.getName())));
super.service(wrappedRequest, response);
userSession.setRequestAndResponse(null, null);
}
}
这里可以看到,这个servlet基础了VRaptor框架的VRaptorServlet。所有的jforum论坛相关配置完全由JForumBootstrap.run()完成,其实就是读取SystemGlobals.properties等重要的配置文件,所有的配置信息其实由JForumConfig来操作,然后JForumConfig又是有spring来管理的,那么JForumBootstrap.run()算是对JForumConfig的初始化吧。
在执行具体的Component(Action)前,servlet都会初始化UserSession对象,以供在Component需要判断用户权限等操作时使用。不管是cookie登陆还是SSO功能仍然由controllerUtils.refreshSession()负责完成。原来command的恐怖代码在使用了这些技术后,可以大大的减少,下面这个是TopicComponent.list()方法,既负责完成浏览主题:
public void list(@Parameter(key = "topic_id") int topicId) {
Topic topic = this.topicRepository.get(topicId);
List<Post> posts = this.postRepository.getAllPosts(topic, 0,
this.config.getInt(ConfigKeys.POST_PER_PAGE));
this.propertyBag.put("posts", posts);
this.propertyBag.put("topic", topic);
this.propertyBag.put("forum", topic.getForum());
this.propertyBag.put("categories", this.categoryRepository.getAllCategories());
}
可以看到技术在这个方法里面完成权限控制功能,代码也不会很多,不过由于VRaptor也有拦截器,估计Rafael Steil不会把代码写在每个方法里面。
后记:
希望大家对jforum3的开发也多多关注,让jforum3以更快的脚步到来。附上jforum3目录结构:
└─jforum
├─compile-lib
├─src
│ ├─main
│ │ ├─java
│ │ │ └─net
│ │ │ └─jforum
│ │ │ ├─actions
│ │ │ │ └─misc
│ │ │ ├─api
│ │ │ ├─bbcode
│ │ │ ├─core
│ │ │ │ ├─exceptions
│ │ │ │ ├─hibernate
│ │ │ │ ├─support
│ │ │ │ │ ├─hibernate
│ │ │ │ │ └─vraptor
│ │ │ │ └─tags
│ │ │ ├─entities
│ │ │ │ └─util
│ │ │ ├─repository
│ │ │ ├─services
│ │ │ ├─sso
│ │ │ ├─startup
│ │ │ └─util
│ │ └─resources
│ └─test
│ ├─java
│ │ └─net
│ │ └─jforum
│ │ ├─actions
│ │ ├─bbcode
│ │ ├─core
│ │ │ ├─hibernate
│ │ │ └─support
│ │ │ └─vraptor
│ │ ├─entities
│ │ ├─services
│ │ └─util
│ └─resources
│ └─i18n
├─target
│ └─tests
│ ├─i18n
│ └─net
│ └─jforum
│ ├─actions
│ ├─bbcode
│ ├─core
│ │ ├─hibernate
│ │ └─support
│ │ └─vraptor
│ ├─entities
│ ├─services
│ └─util
└─webapp
├─images
│ ├─avatar
│ └─smilies
├─META-INF
├─templates
│ ├─agreement
│ ├─default
│ │ ├─admin
│ │ ├─admin.old
│ │ │ ├─images
│ │ │ ├─js
│ │ │ └─macros
│ │ ├─adminBanning
│ │ ├─adminCategories
│ │ ├─adminForums
│ │ ├─adminGroups
│ │ ├─adminRankings
│ │ ├─adminSmilies
│ │ ├─adminUsers
│ │ ├─forums
│ │ ├─images
│ │ │ ├─de_DE
│ │ │ ├─en_US
│ │ │ ├─es_ES
│ │ │ ├─fr_FR
│ │ │ ├─pl_PL
│ │ │ ├─pt_BR
│ │ │ ├─pt_PT
│ │ │ ├─ru_RU
│ │ │ ├─zh_CN
│ │ │ └─zh_TW
│ │ ├─js
│ │ ├─posts
│ │ ├─styles
│ │ ├─topics
│ │ └─user
│ ├─macros
│ └─mail
│ ├─de_DE
│ ├─hu_HU
│ ├─pt_BR
│ ├─pt_PT
│ └─zh_TW
└─WEB-INF
├─classes
│ └─net
│ └─jforum
│ ├─actions
│ │ └─misc
│ ├─api
│ ├─bbcode
│ ├─core
│ │ ├─exceptions
│ │ ├─hibernate
│ │ ├─support
│ │ │ ├─hibernate
│ │ │ └─vraptor
│ │ └─tags
│ ├─entities
│ │ └─util
│ ├─repository
│ ├─services
│ ├─sso
│ ├─startup
│ └─util
├─jforumConfig
│ ├─database
│ │ ├─generic
│ │ └─mysql
│ └─languages
└─lib
使用BSD许可证基于java平台,能在几乎所有的servlet容器上跑
支持多种类型数据库,还具有傻瓜式的安装方式
使用了缓存技术,表示层使用freemarker,运行速度相当快
支持SSO,可以自定义SSO实现,通过配置文件即可进行调整
为此我想我们应该感激Rafael Steil。因为项目需求,我开始了对jforum的二次开发和bug修改等工作,对它的框架、代码结构也在不断的理解。虽然项目暂时告一段落了,但是我还是很热衷关注jforum的发展,今天到官方网站上兜了几圈,找到了jforum3的svn代码库,最近2个月Rafael Steil的开发还是很活跃的http://fisheye2.atlassian.com/browse/jforum/trunk。为此虽然本人功力不深,但也很想写点什么表达自己看到jforum3的感受。
jforum3技术纵览
使用VRaptor2实现WEB MVC
页面渲染可能使用jsp+jstl+jforum-tags
bean管理终于用了spring
持久层使用hibernat,原来的缓存技术暂时没有在代码中看到
使用了流行的action/service/dao三层结构
从web.xml开始了解jforum3
<context-param>
<param-name>org.vraptor.url.LogicLocator</param-name>
<param-value>net.jforum.core.support.vraptor.DefaultLogicLocator</param-value>
</context-param
前面有提到过使用了VRaptor 2,关于这个框架,国内使用的人不多。但事实上,当我到它的官方网站去了解后,发现文档还是做的不错的,例子也很简单明了。LogicLocator是用来把request URI进行特殊解析后,得到LogicMethod的类。因为VRaptor 2默认的uri是person.add.logic这种形式的,而jforum经典的形式是/forums/list.page这种以"/"分隔的。LogicLocator.locate()返回一个LogicMethod,拿个和struts2相对应的比喻来说,就是action中的一个方法,一个url请求过来,执行action里面的一个方法。
<context-param>
<param-name>org.vraptor.url.ViewLocator</param-name>
<param-value>net.jforum.core.support.vraptor.DefaultViewLocator</param-value>
</context-param>
这个是LogicMethod执行完成后,返回的视图控制器,以forward、redirect等形式返回的视图选择就在这里面进行具体实现。
<filter>
<filter-name>hibernateSessionViewFilter</filter-name>
<filter-class>net.jforum.core.support.hibernate.OpenSessionInViewFilter</filter-class>
</filter>
这是大家熟悉的hibernate session管理方式,在chain.doFilter()前让sessionFactory为当前线程分配一个session,打开事务,chain.doFilter()之后如果操作正常着提交事务,关闭session。在jforum2.18中,类似的功能由servlet来完成,既执行具体的command前获得connection,放到JForumExecutionContext中(其实就是一个ThreadLocal),执行command结束后,如果启用了事务,则关闭事务,关闭connection。
当然,sessionFactory是有spring来管理的,这是一个AnnotationSessionFactoryBean,也就没有了hibernate 的mapping文件了,mapping都使用Annotation写在entity类里面。
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="annotatedClasses">
<list>
<value>net.jforum.entities.Category</value>
......
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
.......
</props>
</property>
<property name="eventListeners">
<map>
<entry key="load"><ref local="ForumRepositoryLoadListener"/></entry>
</map>
</property>
</bean>
<bean id="ForumRepositoryLoadListener" class="net.jforum.core.support.hibernate.ForumRepositoryLoadListener"/>
值得关注的是sessionFactory的eventListeners,这是为dao类注入sessionFactory属性的:
@Override
public void onLoad(LoadEvent event, LoadType type) throws HibernateException {
super.onLoad(event, type);
if (event.getEntityClassName().equals(Forum.class.getName())) {
this.dao.setSessionFactory(event.getSession().getSessionFactory());
((Forum)event.getResult()).setRepository(dao);
}
}
jforum3使用了hibernate做持久层,那么原来繁琐的dao编码将少了很多,若是需要进行数据库迁移,也是相当容易的事情了。关于dao类的分析,其实没什么可说的,和平常大家看到的spring+hibernate的代码没什么区别。下面再回到web.xml这个文件来,说说jforum3的核心控制器:
<servlet>
<servlet-name>jforum</servlet-name>
<servlet-class>net.jforum.JForumServlet</servlet-class>
<init-param>
<param-name>configuration.directory</param-name>
<param-value>/WEB-INF/jforumConfig</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>jforum</servlet-name>
<url-pattern>*.page</url-pattern>
</servlet-mapping>
从配置上来说,乍一看和jforum2.18没什么,都是一个servlet。但读到它的源代码,你会发现原来forum2.18在启动过程中超级复杂而乱七八糟的关系,一下子变得明了多了:
public class JForumServlet extends VRaptorServlet {
/**
* 初始化springContext、jforum的其他配置,以及VRaptor视图配置
* @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
*/
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
JForumBootstrap bootstrap = new JForumBootstrap();
bootstrap.run(this.getServletContext(), config);
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Introspector introspector = (Introspector)this.getServletContext().getAttribute(Introspector.class.getName());
VRaptorServletRequest wrappedRequest = new VRaptorServletRequest(request, introspector);
ApplicationContext springContext = (ApplicationContext)this.getServletContext()
.getAttribute(ConfigKeys.SPRING_CONTEXT);
ControllerUtils controllerUtils = (ControllerUtils)springContext.getBean(ControllerUtils.class.getName());
UserSession userSession = controllerUtils.refreshSession(request, response);
request.setAttribute("userSession", userSession);
request.setAttribute(UserSession.class.getName(), userSession);
request.setAttribute(ViewPropertyBag.class.getName(), new ViewPropertyBag(request));
request.setAttribute(ViewService.class.getName(),
new ViewService(request, response, (JForumConfig)springContext.getBean(JForumConfig.class.getName())));
super.service(wrappedRequest, response);
userSession.setRequestAndResponse(null, null);
}
}
这里可以看到,这个servlet基础了VRaptor框架的VRaptorServlet。所有的jforum论坛相关配置完全由JForumBootstrap.run()完成,其实就是读取SystemGlobals.properties等重要的配置文件,所有的配置信息其实由JForumConfig来操作,然后JForumConfig又是有spring来管理的,那么JForumBootstrap.run()算是对JForumConfig的初始化吧。
在执行具体的Component(Action)前,servlet都会初始化UserSession对象,以供在Component需要判断用户权限等操作时使用。不管是cookie登陆还是SSO功能仍然由controllerUtils.refreshSession()负责完成。原来command的恐怖代码在使用了这些技术后,可以大大的减少,下面这个是TopicComponent.list()方法,既负责完成浏览主题:
public void list(@Parameter(key = "topic_id") int topicId) {
Topic topic = this.topicRepository.get(topicId);
List<Post> posts = this.postRepository.getAllPosts(topic, 0,
this.config.getInt(ConfigKeys.POST_PER_PAGE));
this.propertyBag.put("posts", posts);
this.propertyBag.put("topic", topic);
this.propertyBag.put("forum", topic.getForum());
this.propertyBag.put("categories", this.categoryRepository.getAllCategories());
}
可以看到技术在这个方法里面完成权限控制功能,代码也不会很多,不过由于VRaptor也有拦截器,估计Rafael Steil不会把代码写在每个方法里面。
后记:
希望大家对jforum3的开发也多多关注,让jforum3以更快的脚步到来。附上jforum3目录结构:
└─jforum
├─compile-lib
├─src
│ ├─main
│ │ ├─java
│ │ │ └─net
│ │ │ └─jforum
│ │ │ ├─actions
│ │ │ │ └─misc
│ │ │ ├─api
│ │ │ ├─bbcode
│ │ │ ├─core
│ │ │ │ ├─exceptions
│ │ │ │ ├─hibernate
│ │ │ │ ├─support
│ │ │ │ │ ├─hibernate
│ │ │ │ │ └─vraptor
│ │ │ │ └─tags
│ │ │ ├─entities
│ │ │ │ └─util
│ │ │ ├─repository
│ │ │ ├─services
│ │ │ ├─sso
│ │ │ ├─startup
│ │ │ └─util
│ │ └─resources
│ └─test
│ ├─java
│ │ └─net
│ │ └─jforum
│ │ ├─actions
│ │ ├─bbcode
│ │ ├─core
│ │ │ ├─hibernate
│ │ │ └─support
│ │ │ └─vraptor
│ │ ├─entities
│ │ ├─services
│ │ └─util
│ └─resources
│ └─i18n
├─target
│ └─tests
│ ├─i18n
│ └─net
│ └─jforum
│ ├─actions
│ ├─bbcode
│ ├─core
│ │ ├─hibernate
│ │ └─support
│ │ └─vraptor
│ ├─entities
│ ├─services
│ └─util
└─webapp
├─images
│ ├─avatar
│ └─smilies
├─META-INF
├─templates
│ ├─agreement
│ ├─default
│ │ ├─admin
│ │ ├─admin.old
│ │ │ ├─images
│ │ │ ├─js
│ │ │ └─macros
│ │ ├─adminBanning
│ │ ├─adminCategories
│ │ ├─adminForums
│ │ ├─adminGroups
│ │ ├─adminRankings
│ │ ├─adminSmilies
│ │ ├─adminUsers
│ │ ├─forums
│ │ ├─images
│ │ │ ├─de_DE
│ │ │ ├─en_US
│ │ │ ├─es_ES
│ │ │ ├─fr_FR
│ │ │ ├─pl_PL
│ │ │ ├─pt_BR
│ │ │ ├─pt_PT
│ │ │ ├─ru_RU
│ │ │ ├─zh_CN
│ │ │ └─zh_TW
│ │ ├─js
│ │ ├─posts
│ │ ├─styles
│ │ ├─topics
│ │ └─user
│ ├─macros
│ ├─de_DE
│ ├─hu_HU
│ ├─pt_BR
│ ├─pt_PT
│ └─zh_TW
└─WEB-INF
├─classes
│ └─net
│ └─jforum
│ ├─actions
│ │ └─misc
│ ├─api
│ ├─bbcode
│ ├─core
│ │ ├─exceptions
│ │ ├─hibernate
│ │ ├─support
│ │ │ ├─hibernate
│ │ │ └─vraptor
│ │ └─tags
│ ├─entities
│ │ └─util
│ ├─repository
│ ├─services
│ ├─sso
│ ├─startup
│ └─util
├─jforumConfig
│ ├─database
│ │ ├─generic
│ │ └─mysql
│ └─languages
└─lib
相关文章推荐
- 期待Delphi2009的到来
- CES 2018前瞻:这三个领域的变革最令人期待! | 分析
- 静静期待 Windows 7 的到来
- 静静期待 Windows 7 的到来
- EPLAN Electric P8 2.0即将到来,着实令人期待-转caodaping
- 21号冬瓜哥有两场活动期待您到来
- 期待Win 7 的到来
- 静静期待 Windows 7 的到来
- 期待着那一天的到来
- “期待”第十一跳的到来[10-48]
- WWDC2012前瞻:iOS 6,新的Mac和美洲狮等值你期待
- 静静期待 Windows 7 的到来
- DNF.CF牛B辅助,会让你每天惊喜不断,我们期待你的到来。http://wgz.5d6d.com
- 期待java 10 的到来
- WWDC2012前瞻:iOS 6,新的Mac和美洲狮等值你期待
- 期待php的到来。
- 期待着offer的到来
- “云端”前瞻 泛云计算终端时代的到来
- 10位程序员前瞻2007:充满期待的一年
- CEF的C#实现,可以实现用Chrome来渲染UI,期待已久的UI解决方案。