首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

基于 struts+spring+ibatis 的轻量级 J2EE 开发(2)

基于 struts+spring+ibatis 的轻量级 J2EE 开发(2)

3.          JPetStore 的改造3.1.         改造后的架构其中红色部分是要增加的部分,蓝色部分是要修改的部分。下面就让我们逐一剖析。
3.2.          Spring Context 的加载为了在 Struts 中加载 Spring Context,一般会在 struts-config.xml 的最后添加如下部分:
1
2
3
4
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/applicationContext.xml" />
</plug-in>




Spring 在设计时就充分考虑到了与 Struts 的协同工作,通过内置的 Struts Plug-in 在两者之间提供了良好的结合点。但是,因为在这里我们一点也不改动 JPetStore 的控制层 ( 这是 JpetStore4.0 的精华之一 ),所以本文不准备采用此方式来加载 ApplicationContext。我们利用的是 spring framework 的 BeanFactory 机制 , 采用自定义的工具类(bean 工厂类)来加载 spring 的配置文件,从中可以看出 Spring 有多灵活,它提供了各种不同的方式来使用其不同的部分 / 层次,您只需要用你想用的,不需要的部分可以不用。
具体的来说,就是在 com.ibatis.spring 包下创建 CustomBeanFactory 类,spring 的配置文件 applicationContext.xml 也放在这个目录下。以下就是该类的全部代码,很简单:
1
2
3
4
5
6
7
8
9
10
11
public final class CustomBeanFactory {
    static XmlBeanFactory factory = null;
    static {
        Resource is = new InputStreamResource(
            CustomBeanFactory.class.getResourceAsStream("applicationContext.xml"));
        factory = new XmlBeanFactory(is);            
    }
    public static Object getBean(String beanName){
        return factory.getBean(beanName);
    }
}




实际上就是封装了 Spring 的 XMLBeanFactory 而已,并且 Spring 的配置文件只需要加载一次,以后就可以直接用 CustomBeanFactory.getBean("someBean") 来获得需要的对象了 ( 例如 someBean),而不需要知道具体的类。CustomBeanFactory 类用于 { 耦合 1} 的解耦。
CustomBeanFactory 类在本文中只用于表现层的 form bean 对象获得 service 类的对象,因为我们没有把 form bean 对象配置在 applicationContext.xml 中。但是,为什么不把表现层的 form bean 类也配置起来呢,这样就用不着这 CustomBeanFactory 个类了,Spring 会帮助我们创建需要的一切?问题的答案就在于 form bean 类是 struts 的 ActionForm 类!如果大家熟悉 struts,就会知道 ActionForm 类是 struts 自动创建的:在一次请求中,struts 判断,如果 ActionForm 实例不存在,就创建一个 ActionForm 对象,把客户提交的表单数据保存到 ActionForm 对象中。因此 formbean 类的对象就不能由 spring 来创建,但是 service 类以及数据层的 DAO 类可以,所以只有他们在 spring 中配置。
所以,很自然的,我们就创建了 CustomBeanFactory 类,在表现层来衔接 struts 和 spring。就这么简单,实现了另一种方式的 { 耦合一 } 的解耦。
3.3.         表现层上面分析到,struts 和 spring 是在表现层衔接起来的,那么表现层就要做稍微的更改,即所需要的 service 类的对象创建上。以表现层的 AccountBean 类为例:
原来的源代码如下
1
2
  private static final AccountService accountService = AccountService.getInstance();
private static final CatalogService catalogService = CatalogService.getInstance();




改造后的源代码如下
1
2
3
4
private static final AccountService accountService =
    (AccountService)CustomBeanFactory.getBean("AccountService");
private static final CatalogService catalogService =
    (CatalogService)CustomBeanFactory.getBean("CatalogService");




其他的几个 presentation 类以同样方式改造。这样,表现层就完成了。关于表现层的其它部分如 JSP 等一概不动。也许您会说,没有看出什么特别之处的好处啊?你还是额外实现了一个工厂类。别着急,帷幕刚刚开启,spring 是在表现层引入,但您发没发现:
  • presentation 类仅仅面向 service 类的接口编程,具体"AccountService"是哪个实现类,presentation 类不知道,是在 spring 的配置文件里配置。(本例中,为了最大限度的保持原来的代码不作变化,没有抽象出接口)。Spring 鼓励面向接口编程,因为是如此的方便和自然,当然您也可以不这么做。
  • CustomBeanFactory 这个工厂类为什么会如此简单,因为其直接使用了 Spring 的 BeanFactory。Spring 从其核心而言,是一个 DI 容器,其设计哲学是提供一种无侵入式的高扩展性的框架。为了实现这个目标,Spring 大量引入了 Java 的 Reflection 机制,通过动态调用的方式避免硬编码方式的约束,并在此基础上建立了其核心组件 BeanFactory,以此作为其依赖注入机制的实现基础。org.springframework.beans 包中包括了这些核心组件的实现类,核心中的核心为 BeanWrapper 和 BeanFactory 类。
3.4.         持久层在讨论业务层之前,我们先看一下持久层,如下图所示:
在上文中,我们把 iface 包下的 DAO 接口归为业务层,在这里不需要做修改。ibatis 的 sql 配置文件也不需要改。要改的是 DAO 实现类,并在 spring 的配置文件中配置起来。
1、修改基类
所有的 DAO 实现类都继承于 BaseSqlMapDao 类。修改 BaseSqlMapDao 类如下:
1
2
3
4
5
6
public class BaseSqlMapDao extends SqlMapClientDaoSupport {
protected static final int PAGE_SIZE = 4;
protected SqlMapClientTemplate smcTemplate = this.getSqlMapClientTemplate();
public BaseSqlMapDao() {
    }
}




使 BaseSqlMapDao 类改为继承于 Spring 提供的 SqlMapClientDaoSupport 类,并定义了一个保护属性 smcTemplate,其类型为 SqlMapClientTemplate。关于 SqlMapClientTemplate 类的详细说明请参照附录中的"Spring 中文参考手册"
2、修改 DAO 实现类
所有的 DAO 实现类还是继承于 BaseSqlMapDao 类,实现相应的 DAO 接口,但其相应的 DAO 操作委托 SqlMapClientTemplate 来执行,以 AccountSqlMapDao 类为例,部分代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public List getUsernameList() {
    return smcTemplate.queryForList("getUsernameList", null);
}

public Account getAccount(String username, String password) {
    Account account = new Account();
    account.setUsername(username);
    account.setPassword(password);
    return (Account) smcTemplate
        .queryForObject("getAccountByUsernameAndPassword", account);
}
   
public void insertAccount(Account account) {
    smcTemplate.update("insertAccount", account);
    smcTemplate.update("insertProfile", account);
    smcTemplate.update("insertSignon", account);
}




就这么简单,所有函数的签名都是一样的,只需要查找替换就可以了!
3、除去工厂类以及相应的配置文件
除去 DaoConfig.java 这个 DAO 工厂类和相应的配置文件 dao.xml,因为 DAO 的获取现在要用 spring 来管理。
4、DAO 在 Spring 中的配置(applicationContext.xml)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName">
        <value>org.hsqldb.jdbcDriver</value>
    </property>
    <property name="url">
        <value>jdbc:hsqldb:hsql://localhost/xdb</value>
    </property>
    <property name="username">
        <value>sa</value>
    </property>
    <property name="password">
        <value></value>
    </property>
</bean>   
<!-- ibatis sqlMapClient config -->
<bean id="sqlMapClient"
    class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
    <property name="configLocation">
        <value>
        classpath:com\ibatis\jpetstore\persistence\sqlmapdao\sql\sql-map-config.xml
        </value>
    </property>
    <property name="dataSource">
        <ref bean="dataSource"/>
    </property>   
</bean>
<!-- Transactions -->
<bean id="TransactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource">
        <ref bean="dataSource"/>
    </property>
</bean>
<!-- persistence layer -->
<bean id="AccountDao"
    class="com.ibatis.jpetstore.persistence.sqlmapdao.AccountSqlMapDao">
    <property name="sqlMapClient">
        <ref local="sqlMapClient"/>
    </property>
</bean>

返回列表