spring4.0.2+hibernate4.3.5+struts2.3.16.1+c3p0集成SSH入门精简official

之前写过一篇类似的文章,现在回过头来看很糟糕。 很多人在第一次大框架的时候感到很迷茫,包括本人。尤其是jar包的问题,那么多,到底哪些该加,哪些不该加。网上虽然有很多教程和文章,但都是把一堆jar包垒上,然后给出一个demo。诺,照这样做,框架就搭好了。看,我还加了cglib,aspectj呢。

其实,新手应该从搭一个SSH的最小系统开始,以后熟练了,再玩点高大上的,用aspectj,cglib之类的。

什么是最小系统?

计算机或计算机相关专业都学过单片机,单片机有个最小系统,它由三个部分组成:单片机+晶振电路+复位电路。它用最少的元件组成了可以工作单片机系统。 此处省略一些字。

那么我们的SSH最小系统是什么呢?

在我心目中,SSH的最小系统应该是这样:

很简单,就是MVC分层,实现基本的增删改查操作。 难点就在于事务的理解和配置。涉及到更新操作(增,删,改)是要开启事务的,请知悉。没有jdbc编程基础,知道这点就足够了。

准备工作:从官网下载这些:

spring-framework-4.0.2.RELEASE-dist.zip,

hibernate-release-4.3.5.Final.zip,

struts-2.3.16.1-all.zip,

aopalliance.zip spring-aop.jar依赖这个jar包,spring没有给出这个jar包很可恶,官方文档也不提),

aspectj-1.8.0.M1.jar 将此jar包解压,拿出aspectjweaver.jar。spring自己的AOP 虽然没有使用AspectJ功能,但是复用了这个jar的某些类,没有给出这个jar包很可恶,官方文档也不提。这个链接很重要,一定要看看,http://stackoverflow.com/questions/11446893/spring-aop-why-do-i-need-aspectjweaver

C:\Program Files\MySQL\MySQL Connector J\mysql-connector-java-5.1.34-bin.jar  (装mysql的时候注意勾选上MySQL Connector J,这样才能拿到mysql驱动jar包。以前可以直接下载到,现在不行了


准备完毕,我们开始:

①新建一个Dynamic Web Project。注意,如果你选择的web module version是3.0,请在向导最后一步勾选上Generate web.xm deployment descriptor。这样才会自动生成一个web.xml。

②拷贝这些jar包到WEB-INF/lib下。

spring4.0.2+hibernate4.3.5+struts2.3.16.1+c3p0集成SSH入门精简official_第1张图片


具体过程是这样的:

struts2的jar包:

 解压struts-2.3.16.1-all\struts-2.3.16.1\apps\struts2-blank.war. 这是struts2的最小系统。这里有struts2需要的最少jar包。log4j也配置好了,spring官方文档提到spring唯一依赖的一个外部jar包是Log4j.jar。(其实不对还有aopalliance.jar和aspectjweaver.jar) 直接使用这个“空工程”能省我们很多事。 搭SSH我更倾向于从 Struts开始,因为它的jar包最简单。

Hibernate的jar包:

 hibernate的jar包还好理解。就是required和optional\c3p0文件夹下的jar包全部拷贝,很贴心不是。有一点需要注意,hibernate里和struts2里有一个重复的jar包——javassist-3.18.1-GA.jar。选择hibernate里的就可以了。  c3p0是Hibernate推荐的数据库连接池,spring推荐的连接池是dbcp,却没有给出jar包。  拷贝c3p0的jar包同时,也请把驱动jar包mysql-connector-java-5.1.34-bin.jar一并拷贝,免得忘了。

spring的jar包:

关键就在这里。不知道该怎么下手,管他3721,Ctrl+A?这样不好,没有用到的功能没必要加冗余jar包。其实理解了spring的结构也很简单,看:

这是spring的结构。

    ①是spring容器的核心,这4个jar包都要。

    ②我们是web工程,这个jar包必不可少。

    ③我们要连数据库,进行增删改查操作。所以jdbc,orm这两个Jar包需要。jdbc需要数据库连接池,所以我们用了一个连接池c3p0。 orm是关系映射对象,是Hibernate干的事,但是spring既然是容器,所以它必须提供这个接口。

    ④.注意这一块的理解: 增删改需要开启事务。spring提供声明式事务(declarative transaction)。可以是xml-based,也可以是annotation-based。 开启事务是要在方法执行前就要开始的。就是说我们要拦截方法后开启事务,所以需要AOP的支持。AOP和Aspect是分不开的。所以这两个Jar包也是需要的。由于spring-aop.jar依赖aoplliance.jar,而且spring自带 的AOP用了aspectjweaver.jar里的某些类,所以这两个个jar也是需要的(spring给的jar包漏了这两个jar包,实在是不应该)。      强烈建议spring把我提到的这些jar包放在一个required包下,跟Hibernate一样,这样多好。我说的这些已经是最基础的功能了,用的也是最少的jar包,没有半点冗余 。

再强调最后一个jar包。是struts里的一个jar包叫struts2-spring-plugin-2.3.16.1.jar。 因为我们把struts交给spring这个容器管理了,所以需要这个东东。

至此,所有Jar包都解释清楚了。读者不应该再对SSH需要哪些jar包感到疑惑


struts的配置文件:在解压完struts2-blank这个工程的时候已经有了。 spring说需要唯一一个外部的jar包 log4j.jar 。在这个工程里也有了。 


下面开始配置spring和hibernate。 spring和hibernate都配置在一个叫ApplicationContext.xml里。


从哪开始呢。 打开spring官方文档:spring-framework-4.0.2.RELEASE-dist\spring-framework-4.0.2.RELEASE\docs\spring-framework-reference\htmlsingle\index.html


1)Ctrl+F 搜索 ApplicationContext.xml ,我们来到这里

Common configuration

在web.xml里加这个:

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/conf/beans/applicationContext.xml</param-value>
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
 
 

这样我们的web工程就使用上了spring。

2)我们知道ApplicationContext.xml其实就是一个bean的集合。 这个配置文件里配置都是各种bean。所以我们搜索beans

来到这里:

The following example shows the basic structure of XML-based configuration metadata:

把这些拷贝到 ApplicationContext.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">

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>


这样我们就有了一个最简单的spring配置文件了。


3)关键步骤:这样考虑:

    连数据库 ->配置dataSouce

     使用hibernate的session->配置sessionFactory

    请spring帮我们管理事务->配置txManager   

如果我们使用注解形式开启事务,只需配置 打开注解模式 即可。如果我们使用xml形式配置事务,那么我们还要配置aop。

  

我们的dataSouce使用c3p0,直接搜索c3p0.找到这

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="${jdbc.driverClassName}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
    <property name="user" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="jdbc.properties"/>

这就是我们第一步要配的dataSource。连接数据库需要配这些。

然后搜索sessionFactory找到这里:

<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

因为我们使用Hibernate4.x所以改成:

<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">


稍作修改:

<context:property-placeholder location="/WEB-INF/conf/db/jdbc.properties"/>

    <bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="myDataSource" />
        <property name="mappingResources">
            <list>
                <value>cn/ahau/ssh/domain/Event.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=${hibernate.dialect}
                hibernate.show_sql=${hibernate.show_sql}
                hibernate.hbm2ddl.auto=${hibernate.hbm2ddl.auto}
            </value>
        </property>
    </bean>


然后搜索jdbc.properties。 最后这个文件是这样的:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root

hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update


下面是最难的事务:(两种方式:xml-based; annotation-based)

搜索 transaction来到这里:

When the above POJO is defined as a bean in a Spring IoC container, the bean instancecan be made transactional by adding merelyone line of XML configuration:

<!-- from the file '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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd

    <!-- this is the service object that we want to make transactional -->
    <bean id="fooService" class="x.y.service.DefaultFooService"/>

    <!-- enable the configuration of transactional behavior based on annotations -->
    <tx:annotation-driven transaction-manager="txManager"/>
    <!-- a PlatformTransactionManager is still required -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- (this dependency is defined somewhere else) -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- other <bean/> definitions here -->

</beans>


i) 注解形式开启事务:其实就一句话, 它是最简单的。我们一般都用这种形式。

<tx:annotation-driven transaction-manager="txManager"/>
 
 

然后在service层里的方法上加上这个即可:

@Transactional(rollbackFor = Exception.class, propagation=Propagation.REQUIRED)


注意这回命名空间多了这些:

xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"

 
 

知道这一大坨东西怎么来的了吧。就是这样一点一点加上来的。 网上给的都是完整的一大坨,也不知道怎么来的。

ii) xml方式开启事务是这样的:

<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!-- the transactional semantics... -->
        <tx:attributes>
            <!-- all methods starting with 'get' are read-only -->
            <tx:method name="get*" read-only="true"/>
            <!-- other methods use the default transaction settings (see below) -->
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <!-- ensure that the above transactional advice runs for any execution
        of an operation defined by the FooService interface -->
    <aop:config>
        <aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
    </aop:config>

最终的ApplicationContext.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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${jdbc.driverClassName}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <context:property-placeholder location="/WEB-INF/conf/db/jdbc.properties"/>

    <bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="myDataSource" />
        <property name="mappingResources">
            <list>
                <value>cn/ahau/ssh/domain/Event.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=${hibernate.dialect}
                hibernate.show_sql=${hibernate.show_sql}
                hibernate.hbm2ddl.auto=${hibernate.hbm2ddl.auto}
            </value>
        </property>
    </bean>

    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="mySessionFactory" />
    </bean>
    
    
    <!-- declarative transaction annotation-based -->
    <!-- enable the configuration of transactional behavior based on annotations -->
<!--     <tx:annotation-driven transaction-manager="txManager"/> -->



    <!-- declarative transaction XML-based -->
    <!-- the transactional advice (what happens; see the <aop:advisor/> bean below) -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
<!--         the transactional semantics... -->
        <tx:attributes>
<!--             all methods starting with get are read-only -->
            <tx:method name="query*" read-only="true"/>
<!--             other methods use the default transaction settings (see below) -->
            <tx:method name="update*" read-only="false" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!-- ensure that the above transactional advice runs for any execution
        of an operation defined by the FooService interface -->
    <aop:config>
        <aop:pointcut id="serviceOperation" expression="execution(* cn.ahau.ssh.service.impl.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
    </aop:config>


    <!-- other <bean/> definitions here -->
    <bean id="baseAction" class="cn.ahau.ssh.common.action.BaseAction" />
    
    <bean id="eventAction" class="cn.ahau.ssh.action.EventAction">
        <property name="eventService" ref="eventService"/>
    </bean>
    
    <bean id="eventService" class="cn.ahau.ssh.service.impl.EventServiceImpl">
        <property name="eventDao" ref="eventDao"/>
    </bean>
    
    <bean id="eventDao" class="cn.ahau.ssh.dao.impl.EventDaoImpl">
        <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>

</beans>

最后解释一下这句话:

<bean id="eventDao" class="cn.ahau.ssh.dao.impl.EventDaoImpl">
        <property name="sessionFactory" ref="mySessionFactory"/>
</bean>

因为我们的daoimpl里有这个

    private HibernateTemplate hibernateTemplate;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.hibernateTemplate = new HibernateTemplate(sessionFactory);
    }

我们让spring管理hibernate。所有session都让spring帮我们打开和关闭。 spring的HibernateTemplate类需要sessionFactory。所以这里只用一个setter注入sessionFactory即可。这段代码在spring的文档里也有。这文档写的到位。

至此SSH配置完毕。也许还有没说清楚的地方。 源码奉上。 希望大家养成看文档的好习惯,也许一开始我们并不知道从哪下手,没关系,先弄清楚我们要做什么,做这些东西我们需要什么。摸清楚了大致流程,就只管Ctrl+F往文档上招呼。笔者当初在搭这个框架的时候感觉很棘手,搭了很多次,写点心得希望对你有帮助。

最后一个小插曲。 如果用annotation-based方式开启事务 aspectjweaver.jar可以不加。 但是用xml-based方式配置事务,这个jar必须要加。读者可以自己试一下。 在maven工程中aspectjweaver.jar是必须要加的,不然启动报错。

这是下载链接:

http://download.csdn.net/detail/ahau10/8951449



你可能感兴趣的:(spring,Hibernate,c3p0,struts,ssh)