让JSF使用Spring和Hibernate!

手头有一个JSF的项目(JSF+Facelets+Richfaces), 现在有要求把他变身一下,结合Spring和Hibernate的优势。这个项目虽然不算很大,但是也不是hello word级别的小app,所以还是实在要费一番事。翻新过程记录如下,为有相同需要的人做一个参考。

  假定你已经添加了所有的JAR。可以参考我之前的一篇关于dependencies的总结笔记。

1. 在web.xml中添加spring listener
   <listener>
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:/spring.xml</param-value>
  </context-param>

2. 改faces-config.xml. 在原来的<application> tag里加<el-resolver>
   <application>
<view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
   </application>

  这样做的目的是让spring去解析EL expression, 因为以后所有的bean都会是spring bean而不是JSF的managed bean。JSF碰到#{},就会去问这个resolver,然后返回一个spring bean。如此一来,JSF里面,除了Navigation的东西,原来bean的内容就都可以,喀嚓咔嚓,删了!

3. 写Spring的configuration file,我这里名字是Spring.xml。这一步先做基础建设= =||||||.....
   先说一下,因为Spring强大的IOC或者叫DI特性,我们实际上可以写很少XML。我在这里将尽可能的不写XML(因为我懒。。。),而是用annotation。为了做到这点,在spring的configuration file中,要加如下东西:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
......
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
......">
<context:component-scan base-package="tst" /> <!-- tst是我的项目名称-->
  .......
</beans>
最重要的当然是context:component-scan这个tag了。这个tag会让你可以很方便在class中直接使用@Component这个annotation去表示这个class是一个bean! 很方便吧!省去很多XML!

这里再介绍一个context的tag:
<context:property-placeholder location="file:conf/tst.properties" />
添加了这个tag之后,就是定义了properties file的位置,之后可以在spring.xml里面使用${some-property}这种方式读取properties文件中的值了。方便!

  这里提一句,建议一开始就用Maven打project的架构,否则,再翻新的时候,后来加maven,classpath这种东西容易出问题。本人就是之前没研究过.classpath那个file,后面把一个开始不是maven的项目,生生加上maven后,很多后患。也为此花时间研究了一下classpath。。。建议这种基础东西还是先学学好。文后会有一些有用的链接供参考。

为了使用AOP,一定还要加的就是aspectj啦!所以,再添加一个namespace:
...
xmlns:aop="http://www.springframework.org/schema/aop
...
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

并且加入 <aop:aspectj-autoproxy />
这个autoproxy的好处是,我们可以直接在class里面使用@Autowired啦!又省打很多code...

其实还有一些这个xml的基础建设,但是目前先这样。遇到的后面再加。

4. 狂改Class....= =

在写如何改之前,先说一下我目前这个不怎么好的JSF project的结构(部分省略),和修改的方向。

-----------------------------------------------------------------------------------------------------------------------------------
src/
dao/ 均为DAO class,只不pro的简单使用了DBCP
*DAO.java
model/  均为business class,基本上是对应Database里面的每个table的,有少数几个没有对应
*.java 
bean/  均为JSF managed bean,这些bean都属于session scope
     *Bean.java
service/  均为service layer的class,但是当时做的时候没有深刻体会到service layer如何与dao layer配合,所以会直接传SQL给DAO
*Service.java
connection/   一些帮助建立DB连接的class,这里使用了DBCP
config.xml                  关于DBCP需要的一些关于DB的参数
   Configuration.java       这个class会parse上面的config.xml,以得到DBCP需要的相关参数
   ConnectionManager.java     建立DBCP connection pool
WebContent/
WEB-INF/
lib/                   众所周知的lib folder
templates/       装facelets的template, 里面的具体file不讲了
faces-config.xml
web.xml
META-INF/
...
...
---------------------------------------------------------------------------------------------------------------     
可以看出,目前的架构并不好。改成适合spring的结构,我们真要做一些不小改动。唯一不用变的就是presentation layer的东西。不再需要的class有connection下的,因为将把这一部分链接DB的工作交给Hibernate。OK,先加Hibernate。

1)在spring.xml里面加上如下
    <beans 
......
xmlns:tx="http://www.springframework.org/schema/tx"
......
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<tx:annotation-driven />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${db.driver}" /> <property name="url" value="${db.url}" /> <property name="username" value="${db.username}" /> <property name="password" value="${db.password}" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" /> <property name="configLocation" value="classpath:/hibernate.cfg.xml" /> </bean>                      <! -- hibernate.cfg.xml 是我的hibernate configuration file -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"> </bean>
. ......
  </beans>

2)将所有model变成spring bean。因为hibernate要使用这些POJO,我们将每个model加上@Entity,并做适当的configuration.
      对于详细的Hibernate Mapping等内容不是本文重点, 这份Hibernate的Documentation还是做得非常不错的

3)将所有dao变成spring bean。用@Repository做annotation
以前在DAO中会链接DB,现在不用费这个事,但是当然还是要连的,不过是用Hibernate。

  一点建议:建立一个GenericDAO class, 然后所有DAO都extends它。在这个GenericDAO里面,包括了SessionFactory (用Spring inject进去),还有一些最基础的处理SQL级的function。其他的DAO只要直接使用这些共用的function就可以了。

4)将所有service变成spring bean。用@Component做annotation
之前,我是在managed bean中把model object传递给service object,然后在service object中使用那个business object来创建SQL,再把SQL递交给DAO。这种方式无疑给service layer增加了没必要的负担,因为service layer应该不知道data是如何存储的,只应该负责单纯的business logic才对。所以,现在,把service改成spring bean之后,service 最终会使用DAO (用spring做injection)然后直接得到由hibernate建立好的business model object。以前从result set转到model要人工一点一点的赋值,现在,hibernate把这一切都做了!我们,什么都不用做了.......= =

5)将所有JSF managed bean变成spring bean。用@Component做annotation
      基本上,改到这一层,除了添加一些annotation,让spring自动帮我们inject一些东西,大体上改动不大(假设你的service API没有什么改变)。


总结到这里,最基础的更改就大概完成。当然,我只是非常简略的做了一个总结,而且是基于某个项目架构基础上的。但是,就算你原来的JSF不是我的这个架构,也没有犯我之前架构上的问题,可能你的翻新工作会更简单。除了上面介绍的,其实Spring还有一个很重要的特征就是AOP。最常用的应该算LOGGING和TRANSACTION会非常有用。详细的内容可能以后我也会总结一下....可能吧..........= =|||||||

很好,今天的笔记就这么多!欢迎板砖!


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值