OSGI下的web应用开发(5)

这一节将对Dao Interface Bundle 和 Dao implementation Bundle进行开发。

 


  
上图是Dao层的设计。为了尽可能的还原真实的设计架构,这里设计了一个BaseDao,用来定义最基本的Dao操作。
然后有一个HibernateBaseDao的抽象类继承它并实现这些基本操作。然后定义了一个ContactDao,这个dao就是联系人相关业务的Dao接口,以及它的实现ContactDaoImpl。图中我们可以看到模块的划分情况,接口是一个bundle,实现是另一个bundle。

  • Dao Interface Bundle的开发
(1)首先创建一个Bundle Project项目(创建的详细过程已经在前面的章节给出,请参考前面),定义项目名称为net.georgezeng.test.dao。

(2)定义上面图中的两个接口

BaseDao的定义:

package net.georgezeng.test.dao;

import java.util.List;

public interface BaseDao<T> {
  void save(T t);
  T get(Long id);
  List<T> findList(T t); 
}
 
ContactDao的定义如下:

package net.georgezeng.test.dao;

import net.georgezeng.test.domain.Contact;

public interface ContactDao extends BaseDao<Contact> {
}

(3)MANIFEST.MF的定义
import:
当前的Bundle中有用到了domain bundle下的包,因此需要引入net.georgezeng.test.domain,如图


 
export:
我们还需要把接口进行export才能让Dao Implementation Bundle进行引用,如图


 
注意:这里在引入的时候可能会有问题,因为bundle的引用默认是通过在Virgo server的repository目录中获取的,但是目前我们自己开发的bundle是不可能放在那个目录下面的,这个时候就没办法找到那个需要import的包了,所以我们需要做一点小操作,让IDE可以找到这个包。具体操作步骤如下:
1)在Package Explorer中选中当前的项目,如图


 
我这里的项目名称是net.georgezeng.test.dao2, 然后右键点击弹出菜单,选择最下面的Properties选项,进入下图



 
选中Project References,然后在勾选上net.georgezeng.test.domain进行项目关联,这样就可以使import搜索到需要的package了。

2)这个应该是属于IDE工具本身的一个小bug,有的时候我们引入项目关联后虽然可以import需要的包了,但是还是提示找不到这个包,这个时候我们可以先将之前已经import的内容remove,再重新import一次就可以了。(后面讲到的项目间的引用都是通过这种方式实现)

这样我们的Dao Interface Bundle就开发完毕了,接下来我们来开发Dao Implementation Bundle

  • Dao Implementation Bundle
新建Bundle Projecton工程,命名为net.georgezeng.test.dao.impl。
(1)Dao的实现
(1.1)HibernateBaseDao的定义

package net.georgezeng.test.dao.hibernate;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import net.georgezeng.test.dao.BaseDao;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public abstract class HibernateBaseDao<T> extends HibernateDaoSupport implements BaseDao<T> {
  protected Class<T> entityClass;

  @Autowired
  public void init(SessionFactory sessionFactory) {
    super.setSessionFactory(sessionFactory);
  }

  public HibernateBaseDao() {
    entityClass = getEntityClass();
  }

  @Override
  public void save(T t) {
    getHibernateTemplate().save(t);
  }

  @Override
  public T get(Long id) {
    return getHibernateTemplate().get(entityClass, id);
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<T> findList(T t) {
    return getHibernateTemplate().findByExample(t);
  }

  @SuppressWarnings("unchecked")
  protected Class<T> getEntityClass() {
    Type type = getClass().getGenericSuperclass();
    Class<T> result = null;
    if (type instanceof ParameterizedType) {
      ParameterizedType pType = (ParameterizedType) type;
      result = (Class<T>) pType.getActualTypeArguments()[0];
    }
    return result;
  }

}
 
(1.2) ContactDaoImpl的定义

package net.georgezeng.test.contact.dao;

import net.georgezeng.test.dao.ContactDao;
import net.georgezeng.test.dao.hibernate.HibernateBaseDao;
import net.georgezeng.test.domain.Contact;

import org.springframework.stereotype.Repository;

@Repository("ContactDao")
public class ContactDaoImpl extends HibernateBaseDao<Contact> implements ContactDao {
}
 
这里我们需要给ContactDaoImpl定义一个bean id,这样才能在后面曝露服务的时候引用到这个bean,即@Repository里的"ContactDao"

(2)MANIFEST.MF定义

import:


 

export: 这个bundle没有需要export的内容

(3)spring配置

(3.1)osgi-context.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd"
	xmlns:osgi="http://www.springframework.org/schema/osgi">

	<osgi:reference id="dataSource" interface="javax.sql.DataSource" />

	<osgi:service ref="transactionManager" interface="org.springframework.transaction.PlatformTransactionManager" context-class-loader="service-provider" />
	
	<osgi:service ref="ContactDao" interface="net.georgezeng.test.dao.ContactDao" />



</beans>
 
 在前面的章节中Datasource Bundle已经曝露了dataSource的服务,这里我们需要引入,通过

<osgi:reference id="dataSource" interface="javax.sql.DataSource" />
我们就把服务引入了


(3.2)appContext.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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

	<context:annotation-config />
	<context:component-scan base-package="net.georgezeng.test" />
	
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
		<property name="schemaUpdate" value="false"></property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
			</props>
		</property>
		<property name="annotatedClasses">
			<list>
				<value>net.georgezeng.test.domain.Contact</value>
			</list>
		</property>
	</bean>

	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>


</beans>
 
我们需要定义一个sessionFactory用于对Hibernate进行管理,请看其中对dataSource的引入

<property name="dataSource">
			<ref bean="dataSource" />
		</property>
这里的bean 属性的值引用的是上面定义的osgi:reference标签中的id属性的值

接着我们还要定义一个transactionManager,用来对事务进行控制。这个transactionManager将会以服务的方式发布到OSGI中,让service层可以使用这个服务。
在回头看osgi-context.xml中对服务的定义,

<osgi:service ref="transactionManager" interface="org.springframework.transaction.PlatformTransactionManager" context-class-loader="service-provider" />
这里有一个很重要的属性需要设置,就是context-class-loader,需要设置为service-provider,目的是让service调用这个服务的时候使用的是服务提供者(即Dao Implementation Bundle)的classloader,这样就可以正确的调用hibernate的API,否则将会抛错提示hibernate的API不可见。
其实我们也可以让transactionManager单独作为一个模块,但是意义不大,这里不做讨论。

我们还看到曝露了一个ContactDao的服务,这里ContactDao的id值正是与@Repository中的值相对应的,这样service层就可以使用DAO的服务了

至此dao层的开发就结束了

附上该项目的源码



猜你喜欢

转载自georgezeng.iteye.com/blog/1130886
今日推荐