您的位置:首页 > 运维架构 > 网站架构

基于注解的SSH架构整合之一

2015-03-25 20:53 471 查看
SSH架构是JAVA EE开发中最常见的架构,SSH架构具有服务端代码简单,开发速度快的优点,使用Hibernate的ORM技术可以快速度的开发数据库访问层的代码,Spring的AOP可以为我们提供切面事务的功能,IOC/D可以让我们自由的在工程中任意的一个JavaBean中注入另一个JavaBean。我认为这是IOC/DI最大的优点之一,有很多类似的业务场景,例如有一个类我们只需要实例化一次,但需要在多个类中使用,例如数据源(DataSource),你不可能把数据源初始化多次,这样访问数据库的性能也太慢了。Struts2可以简化MVC层的开发,将多个客户端的请求动作集成在一个Action中。

使用注解开发代码的好处在于比配置文件简单,易于维护,JAVA注解的原理类似于C#中的特性,是JAVA EE的新特性之一,早在08年的时候,我们就开始在项目中使用注解,在近几年里,注解在JAVA
EE中的应用也越来越广泛,已经成为一种标准技术,所以,本文重点讲解SSH架构中的注解应用。

注:IOC/DI技术是一个很难理解的技术,我觉得可能是框架服务商为了展示他们的框架有多牛,而把这项技术说的很高深,另一个原因可能是翻译的问题,翻译后的内容没法和原文意思100%匹配。我在做招聘的时候经常会问到这个问题,发现90%的开发人员都不能完全理解这个技术,甚至把IOC/DI、AOP的概念混淆。IOC为控制反转,其实就是委托Spring为我们实例化JAVA代码,而我们自己则不再实例化代码了。DI为依赖注入,什么是依赖注入呢?简单点说就是比如Service类要调用一个Dao类,来保存一个对象,通常情况下我们会在Service中实例化一个DAO类,然后调用DAO类中的一个方法。有一个说法叫这种编程方式是紧偶合的,所以要用IOC/DI,我最初听到这个说法也是深信不疑,因为是老师教的,网上也有很多这样的说法。而在多年的开发实践中,我越来越怀疑这个说法的准确性。难道你在Service中注入一个DAO类就解偶了吗?仅仅是你把实例化的功能交给了Spring而已,而你要在Service中取出这个DAO。难道你不用注入DAO类就可以保存数据了吗?这也是不能的。这就好比你租房子,本来你可以和房东直接签合同,但房东觉得麻烦,把房子交给了中介,由中介来和你签合同,然后你的合同里就有了甲、乙、丙三方。你和房东是解偶了,但是你和中介、中介和房东又直接偶合在一起了,离了谁都不行,偶合的关系反而多了一层。这其实是一个哲学问题,而不是技术问题。

虽然松偶合这个说法未必那么贴切,但用IOC/DI还是有很多好处的。很多只需要初始化一次的类,你可以在工程中任意使用,而不用再重复初始化,确实省了很多代码。很多典型的用应,例如如果没有Spring,你可能会自己启动Hibernate,如果没有做特别的控制,可能每次访问数据库你都要启动一次Hibernate。而用了Spring的好处是,在服务启动的时候就把所有需要初始化的工作都做好了,并且sessionFactory已经给你保存在容器里了,你每次访问数据库,只需要调用sessionFactory得到一个Session就可以,并且你可以在任意的JavaBean中使用sessionFactory。从这个角度来看,IOC/DI确实实现了一定程度的松偶合。

AOP技术比较好理解,就是面像切面编程,在你的纵向代码中横向的插入一些其他代码。简单点说,就是在你编译好的代码里动态插装字节码。这确实是一个很有用的技术,可以实现一些特定功能,例如事务控制,代理模式等。AOP可以拦截方法执行的过程,在方法的开始和结尾加入你自己的代码,实现你想要的功能。另外AOP技术可以用于各种监控工具。

1 整合前的准备工作

分别下载Struts2、Hibernate、Spring的开发包,如下图:



2 新建一个WEB项目,你可以选用你熟悉的IDE,我使用的是Eclipse。



3 把下载好的JAR拷贝到WEB项目的lib目录下,并不是所有的JAR包都需要,我们只复制开发必须的JAR包。



4 编写ApplicaContext.xml文件

ApplicaContext.xml是启动Spring框架的必备文件,也是Spring整合其他框架的描述文件,该文件放置在src目录下。因为我们的架构是使用注解开发,不使用配置文件,所以需要开启注解配置和自动扫描Bean的功能。

<!--自动扫描BEAN -->
<context:component-scan base-package="com.mcs"></context:component-scan>
<!-- 开启注解配置 -->
<context:annotation-config></context:annotation-config>


我们可能需要编写一些AOP的代码,例如日志功能,所以把AOP也开启

<!-- 开启AOP -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>


配置一个数据源DataSource(IOC),采用DBCP数据库连接池作为数据源

<bean class="org.apache.commons.dbcp.BasicDataSource" id="DataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="123456"/>
</bean>


配置一个SessionFactory(IOC), SessionFactory是Hibernate的Session工厂类,使用spring初始该类,初始化之后我们可以得到利用SessionFactory得到session。

<bean id="sessionFactory"
class="com.mcs.core.hibernateFactory.AnnotationLocalSessionFactoryBean">
<property name="dataSource" ref="DataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="current_session_context_class">thread</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_structured_entries">true</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</prop>
<prop key="hibernate.net.sf.ehcache.configurationResourceName">ehcache.xml</prop>
<prop key="hibernate.jdbc.batch_size">50</prop>
</props>
</property>
</bean>


配置由Spring管理Hibernate事务

<!-- 事物管理 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager"
abstract="false" lazy-init="default" autowire="default"
dependency-check="default">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>


开启注解事务,开启注解事务后,我们可以在方法使用@Transactional来声明事务。

<!--使用注解配置事物-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>


在AppliactionContext中我们使用了hibernate缓存配置,所以要配置缓存文件。这不是必须的,你也可以把Hibernate中的缓存属性去掉。新建一个ehcache.xml文件(该文件放置在src目录下),加入如下内容。

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../main/config/ehcache.xsd" name="tc"
updateCheck="false">
<defaultCache
maxElementsInMemory="30000"
eternal="true"
overflowToDisk="false">
</defaultCache>
</ehcache>


5 支持Hibernate的使用注解的SessionFactory

Hibernate的注解有两种,一种是JPA,一种是Hibernate自带的注解,本文我们以JPA注解为主。其实JPA和Hibernate自带的注解基本上是一样的,只是解析器不一样。为了使Hibernate可以支待JPA注解,并且不在ApplicationContext中配置POJO类,我们定义了一个AnnotationLocalSessionFactoryBean类,在该类中注入了一个接口IPojoModuls,在IPojoModuls接口中负责添加POJO类。

AnnotationLocalSessionFactoryBean类:

<span style="font-size:14px;">/**
* 在Session中添加POJO类,不使用配置文件,本工程是零配置工程
* @author 山人
*
*/
public class AnnotationLocalSessionFactoryBean extends LocalSessionFactoryBean {

@Resource(name = "pojoModuls")
IPojoModuls pojoModuls;

@Override
public void afterPropertiesSet() throws IOException {
// TODO Auto-generated method stub
Class<?>[] pojos = new Class<?>[pojoModuls.getAnnotatedClasses().size()];
pojoModuls.getAnnotatedClasses().toArray(pojos);
super.setAnnotatedClasses(pojos);
super.afterPropertiesSet();
}

}
</span>

IPojoModuls接口:

/**
* POJO模块接口
* <p>
* <h2>
* 如果要进行分模块开发,实现些接口</h2>
* </p>
*
* @author 山人
*
*/
public interface IPojoModuls {
/**
* 得到注解类,该方法用得添加POJO类,支持JPA注解驱动,详情请参见JPA API
*
* @return 迭代
*/
public List<Class<?>> getAnnotatedClasses();
}


PojoModuls实现类:

@Component("pojoModuls")
public class PojoModuls implements IPojoModuls {

public List<Class<?>> getAnnotatedClasses() {
List<Class<?>> pojolist=new ArrayList<Class<?>>();
pojolist.add(PersonPojo.class);
pojolist.add(CardType.class);
pojolist.add(Card.class);
pojolist.add(Site.class);
pojolist.add(OperatorSet.class);
pojolist.add(MenuPanel.class);
pojolist.add(Menu.class);
return pojolist;
}
}


6 在WEB工程中启动Spring和Hibernate

到目前为止,我们已经完成了Spring和Hibernate的整合,并且开启了两个框架对注解的支持,接下来需要启动Spring和Hibernate。我们只需要在web.xml增加一些配置就可以了。

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:ApplicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


现在,除了Struts2之外,Spring和Hibernate已经可以正常工作了。

由于字数限制,整合Struts2请看下一篇文章《基于注解的SSH架构整合之一》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: