`
huangyungang
  • 浏览: 8037 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

SCA(Tascany)+Spring+Hibernate开发与使用范例

阅读更多
1. 概述
本文档描述了基于Eclipse3.5和Apache Tascany基础之上的Spring快速入门的使用范例。感兴趣的朋友MSN:huangyungang@hotmail.com交流,也可mail说明。
本文将着手了解或解决如下内容:
 Spring 开发 SCA 组件时需要掌握的一些基本设计原则。
 如何将 Spring beans 公开为 SCA 服务,
 如何在 Spring 应用程序中访问 SCA 服务和属性。
 如何使用 Spring Framework 和 Apache Tuscany SCA Java 运行时来设计和开发 SCA 组件。。
 如何结合 SCA 与 Spring 来创建分布式服务应用程序。

2. 开发环境
2.1. 环境准备
为了在实践中完成下面文中描述的内容,您需要以下工具:


表1-开发环境要素
2.2. 环境搭建(参考SCA(Tascany)环境搭建和使用范例)


3. SCA 与 Spring 两者相结合的优势
  Spring Framework 与 SCA 采用许多相同的设计原则。SCA 将 Spring 视为其组件的一种实现技术。SCA Sprig Component Implementation Specification 定义了如何采用这种方式来使用 Spring。
与 Spring bean 类似,SCA 组件可以包含到其他组件所提供的服务的引用,并且有一些属性可供配置。
与 Spring 形成对比的是,SCA 是一种跨语言的分布式组件架构,它支持多种组件通信机制。通过将 Spring beans 发布为可由其他组件访问的服务并为 Spring beans 提供关联到其他(可能为远程)组件的服务的引用,SCA 可以扩展 Spring 组件的功能。
4. SCA与Spring 结合的原则
要将 SCA 与 Spring 相结合,一种有效的方法是使用 Spring 来构建 “粗粒度” 的服务组件实现,并引入到 SCA 中以便公开服务、关联服务组件以及处理异构和分布式系统。SCA 可以在使用 Spring 实现的应用程序中添加一些有用的功能,比如说:
 对远程组件以及多种协议的扩展支持
 支持使用不受 JVM 支持的各种编程语言来编写组件
 支持 WS-Policy 针对安全性和事务等活动指定的策略
 易于测试组件是 Spring 的一项优异的特性。
缺少 API 和注入技术导致您只能使用简单的模拟对象进行测试。SCA 在服务方面对此进行了补充,因为关于服务组件的 SCA 复合集可以方便地切换到模拟配置以进行测试。
5. Tuscany SCA与Spring结合的步骤
5.1. 将 Spring 应用程序定义为 SCA 组件
创建一个包含一个 Spring 组件的 SCA 复合集
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" 
   xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0" 
   targetNamespace="http://calc" 
   xmlns:c="http://calc" 
   name="Calculator"> 
  <component name="CalculatorServiceComponent"> 
       <implementation.spring location="targetURI"/> 
  </component> 
</composite> 

其中:
<implementation.spring> 元素的位置属性可以指定目标 URI 指向某个存档文件 (.jar) 或 目标,或者 直接指向 Spring 应用程序上下文。
以下列表给出了指定 <implementation.spring> 位置属性的目标 URI 的可能方法。


一个 Spring 应用程序可被定义为 SCA 复合集(即 SCDL:SCDL is used to describe SCA elements such as modules, references, imports, and exports)内的一个 SCA 组件。其形式如下图所示:




其中<implementation.spring>用于指定实现component的Spring bean配置文件。而location则指定的bean文件的位置或目录(关于目录下面的示例中包含)。



6. 示例程序(WebService+SCA+Spring+Hibernate)
下面我们来开发一个示例程序。在本示例中,您将看到如何利用SCA集成现有的Spring组件,并对其进行向外发布。

6.1. 创建工程
首先我们在d:\TuscanyWorkspace\工作区下,创建一个名为SpringDemo “Dynamic Web Project”的工程。加载TuscanyLibrary(在开发环境建立一文中已经指出)。并将apache-tuscany-sca-1.6.zip的lib目录中的.jar文件COPY到工程的lib目录中。
以上是一个Java Application中对OSOA包的使用。当然对于Java Web Application需要将这些包加到Web Application的lib目录下。同时本示例还需要将hibernate和c3p0的JAR包加入到lib目录下。
6.2. 代码
下面的我们要实现的是基于Apache Tomcat来发布一个tuscany的SCA组件。
程序代码的包结构如下图所示:


图6-示例程序的包结构
6.2.1. 创建基于Hibernate的数据访问程序
6.2.1.1. 创建Hibernate工具类—HibernateUtil.java
此类主要用于实现对数据库的CRUD基本操作,需要注意的是hibernate.cfg.xml文件是通过注入的方式来实现的。
package net.jite.waf.persistent.util;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.hbm2ddl.SchemaUpdate;

/**
* desc: Hibernate的通用类 <br/>
* 用于对Hibernate SessionFactory的初始化以及Hibernate Session的管理
* @author <a href="mailto:huangyungang@hotmail.com">huangyungang </a>
*
*/
public class HibernateUtil {
    private SessionFactory _sf;
    private static final ThreadLocal session = new ThreadLocal();
    private String configFile;
    /**
* 设置默认的配置文件名
*
* @param cfgFile
*/
public void setConfigFile(String cfgFile){
    configFile=cfgFile;
}
/**
* 初始化此对象
*
*/
public void init(){
    try {
            Configuration config = new Configuration().configure(configFile);
            if ("true".equals(config.getProperty("createtable"))) {
                new SchemaExport(config).create(true, true);
            }
            if ("true".equals(config.getProperty("updatetable"))) {
            new SchemaUpdate(config).execute(true, true);
            }
            _sf = config.buildSessionFactory();
        } catch (HibernateException e) {
            throw new RuntimeException("初始化Hibernate SessionFactory失败", e);
        }
}
    /**
     * 获取一个Session
     * @return Session
     * @throws HibernateException
     */
    public Session currentSession() throws HibernateException {
        Session s = (Session) session.get();
        if (s == null) {
            s = _sf.openSession();
            session.set(s);
        }
        return s;
    }
    /**
     * 关闭Session
     *
     * @throws Exception
     */
    public void closeSession() throws HibernateException {
        Session s = (Session) session.get();
        if (s != null)
            s.close();
        session.set(null);
    }
}

6.2.1.2. 创建一个CommonDao类
CommonDao实现了基本的数据访问操作,这里的CommonDao可以被Service层去调用。代码如下:
import java.io.Serializable;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import user.util.HibernateUtil;

public class CommonDao {
private Session _session;
private HibernateUtil util;

public Session get_session() {
return _session;
}
public void set_session(Session session) {
_session = session;
}
public HibernateUtil getUtil() {
return util;
}
private boolean isOSIV;
//***********************增加的内容********************************
/**
* 根据主键ID删除obj
*
* @throws Exception
*             删除时出错则抛出
*/
public void deleteById(Class po, String id) throws Exception {
// Object obj = getById(po, id);
// delete(obj);
_session=getSession();
Transaction  tx = _session.beginTransaction();
try
{

_session.delete(_session.get(po,id));
tx.commit();
}
catch (HibernateException e) {
// 在目前的HRibernate版本中当无对应的id的主键记录存在时抛出的异常
tx.rollback();
} finally {
closeSession();
}
}
/**
*
* desc:新添加的方法,用于匹配CMS数据库中的字符串主键
* @author huangyg
*
**/

public Object getById(Class po,String id) throws Exception {
_session = getSession();
try {
//return _session.load(po,id);
return _session.get(po, id);
} catch (HibernateException e) {
// 在目前的Hibernate版本中当无对应的id的主键记录存在时抛出的异常
return null;
} finally {
closeSession();
}
}
//***************************end*************************************
//***************************************************************
/**
* 设置获取Hibernate Session的通用类
*/
public void setUtil(HibernateUtil util) {
this.util = util;
}

/**
* 持久化obj
*
* @throws Exception
*             持久化过程时出错则抛出
*/
public void save(Object obj) throws Exception {
_session = getSession();
Transaction tx = _session.beginTransaction();
try {
_session.save(obj);
tx.commit();
} catch (HibernateException e) {
tx.rollback();
// log.error("Hibernate进行持久化Object时错误", e);
throw new Exception("Hibernate进行持久化Object时错误");
} finally {
closeSession();
}
}

/**
* 更新obj
*
* @throws Exception
*             更新时出错则抛出
*/
public void update(Object obj) throws Exception {
_session = getSession();
Transaction tx = _session.beginTransaction();
try {
_session.update(obj);
tx.commit();
} catch (HibernateException e) {
tx.rollback();
// log.error("Hibernate更新Object时错误", e);
throw new Exception("Hibernate更新Object时错误");
} finally {
closeSession();
}
}

/**
* 删除obj
*
* @throws Exception
*             删除时出错则抛出
*/
public void delete(Object obj) throws Exception {
_session = getSession();
Transaction tx = _session.beginTransaction();
try {
_session.delete(obj);
tx.commit();
} catch (HibernateException e) {
tx.rollback();
// log.error("Hibernate删除Object时错误", e);
throw new Exception("Hibernate删除Object时错误");
} finally {
closeSession();
}
}

/**
* 根据主键ID删除obj
*
* @throws Exception
*             删除时出错则抛出
*/
public void deleteById(Class po, int id) throws Exception {
Object obj = getById(po, new Integer(id));
delete(obj);
}

/**
* 清空某po所有的数据 强烈建议尽量不要使用此方法,一般来说不要物理删除数据,置状态比较合适
*
* @param po
* @throws Exception
*/
public void deleteAll(Class po) throws Exception {
_session = getSession();
Transaction tx = _session.beginTransaction();
try {
_session.createQuery("delete from " + po.getName()).executeUpdate();
tx.commit();
} catch (HibernateException e) {
tx.rollback();
// log.error("Hibernate清空PO中数据时错误", e);
throw new Exception( "Hibernate清空PO中数据时错误");
} finally {
closeSession();
}
}

/**
* 根据为int型的主键ID获取对应的Object
*
* @param obj
* @param id
* @return Object
* @throws Exception
*/
public Object getById(Object obj, int id) throws Exception {
return getById(obj.getClass(), new Integer(id));
}

/**
* 根据主键ID获取对应的Object
*
* @param obj
* @param id
* @return Object
* @throws Exception
*/
public Object getById(Object obj, Serializable id) throws Exception {
return getById(obj.getClass(), id);
}

/**
* 根据为int型的主键ID获取对应的Object
*
* @param obj
* @param id
* @return Object
* @throws Exception
*/
public Object getById(Class po, int id) throws Exception {
return getById(po, new Integer(id));
}

/**
* 根据主键ID获取对应的Object
*
* @param obj
* @param id
* @return Object
* @throws Exception
*/
public Object getById(Class po, Serializable id) throws Exception {
_session = getSession();
try {
return _session.get(po, id);
} catch (HibernateException e) {
// 在目前的Hibernate版本中当无对应的id的主键记录存在时抛出的异常
return null;
} finally {
closeSession();
}
}

// For Business Method

/**
* 根据需执行的hql返回List <br>
* 建议对于数据量小或一次进行频繁查询的使用
*
* @param hql
* @return java.util.List
* @throws Exception
*/
public List getListByHql(String hql) throws Exception {
return  null;
}


/**
* 获取Session
*
* @throws Exception
*/
public Session getSession()  {
return util.currentSession();
}
/**
* 关闭Session
*
* @throws Exception
*/
public void closeSession()  {
// Use Open Session In View,so we don't close session
if (!isOSIV) {
util.closeSession();
}
}

// ============================== get/set

public void setOSIV(boolean isOSIV) {
this.isOSIV = isOSIV;
}

}

6.2.1.3. 创建一个POJO类和Hibernate的.hbm.xml映射文件
POJO类代码如下:
package user.domain;

public class User {
private Integer id;
private String username;
private String password;
private int sex;
private String address;
public String toString(){
return null;
}
public Integer getId(){
return this.id;
}
public void setId(Integer id){
this.id=id;
}
public String getUsername(){
return this.username;
}
public void setUsername(String username){
this.username=username;
}
public String getPassword(){
return this.password;
}
public void setPassword(String password){
this.password=password;
}
public void setSex(int sex){
this.sex=sex;
}
public int getSex(){
return this.sex;
}
public void setAddress(String address){
this.address=address;
}
public String getAddress(){
return this.address;
}
}

User.hbm.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping
>
    <class
        name="user.domain.User"
        table="userinfo"
    >
        <id
            name="id"
            column="ID"
            type="java.lang.Integer"
            length="10"
            unsaved-value="0"
           
        >
            <generator class="increment" />
        </id>
        <property
            name="username"
            type="java.lang.String"
            update="true"
            insert="true"
            column="username"
            not-null="false"
            unique="false"
        />
        <property
            name="password"
            type="java.lang.String"
            update="true"
            insert="true"
            column="password"
            not-null="false"
            unique="false"
        />
        <property
            name="address"
            type="java.lang.String"
            update="true"
            insert="true"
            column="address"
            not-null="false"
            unique="false"
        />
    </class>

</hibernate-mapping>


6.2.1.4. 创建hibernate.cfg.xml文件
hibernate.cfg.xml内容如下:
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/soademo?useUnicode=true&amp;
characterEncoding=GBK</property>
   <property name="connection.username">root</property>
<property name="connection.password">admin</property>
<!-- org.hibernate.dialect.OracleDialect -->
<!-- org.hibernate.dialect.MySQLDialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="jdbc.fetch_size">50</property>
<property name="show_sql">true</property>
<property name="createtable">false</property>
<property name="updatetable">true</property>
<property name="c3p0.min_size">1</property>
<property name="c3p0.max_size">30</property>
<property name="c3p0.max_statements">100</property>
<property name="c3p0.idle_test_period">5000</property>
<!--浮标管理-->
<mapping resource="user/domain/User.hbm.xml" />
<!--缓存配置-->
</session-factory>
</hibernate-configuration>

6.2.2. 创建基于SCA容器并集成Spring的Composite
6.2.2.1. 在web.xml中添加tuscany过滤器
<filter>
<filter-name>tuscany</filter-name>
<filter-class>org.apache.tuscany.sca.host.webapp.TuscanyServletFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>tuscany</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

需要注意的是,这里不需要添加Spring ContextLoaderListener,SCA具备自已独立的容器,直接访问Spring容器内部的Beans比较困难,因为它们不在同一容器内。下面的代码我们是不需要加到web.xml文件中的。
<!--
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
-->

6.2.2.2. 创建Spring Bean配置
Spring bean的配置共包括三部分内容:
 Bean的自身定义
 供外部调用Service定义
 聚合其它Service的引用定义

在WebContent/spring-context目录下创建beans-user.xml文件,内容如下

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sca="http://www.springframework.org/schema/sca"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/sca http://www.osoa.org/xmlns/sca/1.0/spring-sca.xsd"
>
  <sca:service name="UserService"
        type="user.service.UserService"
        target="userServiceBean"/>
       
<bean id="userServiceBean" class="user.service.UserServiceImpl">
<property name="dao" ref="CommonDaoService"/>
</bean>
  <sca:reference name="CommonDaoService" type="user.dao.CommonDao" ></sca:reference>
</beans>

创建beans-commondao.xml,内容如下:
<?xml version="1.0" encoding="gbk"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sca="http://www.springframework.org/schema/sca"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/sca http://www.osoa.org/xmlns/sca/1.0/spring-sca.xsd"
>
<!--Bean对外提供  -->
  <sca:service name="CommonDaoService"
        type="user.dao.CommonDao"
        target="commonDaoBean"/>
<!--Bean自身定义  -->     
     <bean id="commonDaoBean" class="user.dao.CommonDao">
<property name="util" ref="HibernateUtilService"></property>

</bean>
<!--Bean引用别的  -->
  <sca:reference name="HibernateUtilService" type="user.util.HibernateUtil" ></sca:reference>
</beans>

创建beans-hibernate-util.xml
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sca="http://www.springframework.org/schema/sca"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/sca http://www.osoa.org/xmlns/sca/1.0/spring-sca.xsd"
>
<sca:service name="HibernateUtilService"
        type="user.util.HibernateUtil"
        target="HibernateUtilBean"/>
<bean id="HibernateUtilBean" class="user.util.HibernateUtil" init-method="init">
<property name="configFile" value="/hibernate.cfg.xml"/>
</bean>
</beans>


6.2.2.3. 创建SCA包装
User.composite文件
<?xml version="1.0" encoding="UTF-8"?>
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
    xmlns:t="http://tuscany.apache.org/xmlns/sca/1.0"
    xmlns:c="http://User"
    targetNamespace="http://User"
    name="User">
    <service name="UserService" promote="UserServiceComponent">
    <binding.ws></binding.ws>
    </service>
    <component name="UserServiceComponent">
        <implementation.spring location="spring-context/beans-user.xml"/>
        <reference name="CommonDaoService" target="CommonDaoServiceComponent"></reference>
    </component>
</composite>
其中:
 spring-context/beans-user.xml的完全路径是WebContent/Spring-context/beans-user.xml
 此处使用<binding.ws></binding.ws>将UserService发布成了一个WebService
 Component的引用关系注意描述,由于UserService中需要使用CommonDao的内容,在SCA的Component层面也需要进行定义。例如<reference name="CommonDaoService" target=
"CommonDaoServiceComponent"></reference>。
CommonDao.composite
<?xml version="1.0" encoding="UTF-8"?>
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
    xmlns:t="http://tuscany.apache.org/xmlns/sca/1.0"
    xmlns:c="http://User"
    targetNamespace="http://User"
    name="CommonDao">
    <service name="CommonDaoService" promote="CommonDaoServiceComponent">
    </service>
    <component name="CommonDaoServiceComponent">
        <implementation.spring location="spring-context/beans-commondao.xml"/>
        <reference name="HibernateUtilService" target="HibernateUtilServiceComponent"></reference>
    </component>
</composite>

HibernateUtil.composite

<?xml version="1.0" encoding="UTF-8"?>
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
    xmlns:t="http://tuscany.apache.org/xmlns/sca/1.0"
    xmlns:c="http://User"
    targetNamespace="http://User"
    name="HibernateUtil">
    <service name="HibernateUtilService" promote="HibernateUtilServiceComponent">
   
    </service>
    <component name="HibernateUtilServiceComponent">
        <implementation.spring location="spring-context/beans-hibernate-util.xml"/>
    </component>
</composite>


6.2.2.4. 创建MySQL数据表
在本机的MySQL数据库soademo中,建一张userinfo表。
/*
Navicat MySQL Data Transfer
Source Host     : localhost:3306
Source Database : soademo
Target Host     : localhost:3306
Target Database : soademo
Date: 2010-04-19 17:35:13
*/

SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for userinfo
-- ----------------------------
DROP TABLE IF EXISTS `userinfo`;
CREATE TABLE `userinfo` (
  `id` int(11) NOT NULL default '0',
  `username` varchar(200) default NULL,
  `password` varchar(100) default NULL,
  `sex` int(2) default NULL,
  `address` varchar(200) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of userinfo
-- ----------------------------
INSERT INTO `userinfo` VALUES ('1', '1', '1', null, '1');

6.2.3. 执行情况
在SOAPUI工具中调用已经发布的WebService,运行http://localhost:8080/springdemo/UserService?wsdl得到如下结果:


SOAPUI调用情况如下(SOAPUI工具可从网络中下载):



Tomcat结果如下图所示:


最终显示Hibernate完成了向MySQL数据库添加一行记录。
  • 大小: 16.1 KB
  • 大小: 20.2 KB
  • 大小: 6.1 KB
  • 大小: 31.8 KB
  • 大小: 64.7 KB
  • 大小: 35.5 KB
  • 大小: 15.9 KB
分享到:
评论
2 楼 zyp731 2011-12-08  
全是代码,没啥内涵~
1 楼 hamlzf 2011-10-19  
寻找很久了

相关推荐

Global site tag (gtag.js) - Google Analytics