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

来源:互联网 发布:mac word 替换 编辑:程序博客网 时间:2024/05/01 15:43

        SSH架构是JAVA EE开发中最常见的架构,SSH架构具有服务端代码简单,开发速度快的优点,使用HibernateORM技术可以快速度的开发数据库访问层的代码,SpringAOP可以为我们提供切面事务的功能,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 整合前的准备工作

     分别下载Struts2HibernateSpring的开发包,如下图:

      

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>


 

       配置一个数据源DataSourceIOC),采用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>

      

       配置一个SessionFactoryIOC, SessionFactoryHibernateSession工厂类,使用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注解为主。其实JPAHibernate自带的注解基本上是一样的,只是解析器不一样。为了使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;@Overridepublic void afterPropertiesSet() throws IOException {// TODO Auto-generated method stubClass<?>[] 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

        到目前为止,我们已经完成了SpringHibernate的整合,并且开启了两个框架对注解的支持,接下来需要启动SpringHibernate。我们只需要在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之外,SpringHibernate已经可以正常工作了。

 

       由于字数限制,整合Struts2请看下一篇文章《基于注解的SSH架构整合之一》

 

0 0