Spring4.0.2+Hibernate4.5.1+struts2.3.16.1

本文转载于http://blog.csdn.net/JackieLiuLixi/article/details/37910743


Spring4.0.2+Hibernate4.5.1+struts2.3.16.1。这三个目前都是官网上最新的且是稳定版的(Stable)。建议大家去官网上下,其中spring的连接有些慢,为了下载它我还特地开了个迅雷会员呢。

虽然这些包都是官网下载的,但是集成SSH还需要些额外jar包。建议大家也都到官网上下载。我的全都是从官网上下载的,而且还是最新的可用版本。我上传到这里了wwwwwwww。大家可以直接下载。

 

 

1.新建Dynamic Web Project,注意Dynamic web module version要选2.5。如果你用了默认的3.0。刚建好的工程下WEB-INF/下将没有web.xml。 但是这样会导致新建的工程默认使用Jdk1.5。这会导致你的项目中不能使用@Resource。

 

解决办法。 右键工程-->build path-->configure build path,选择libraries标签,双击JRE System Library ,选中workspace default jre。我的是jdk1.7。

 

 

2.集成spring与Hibernate。这一步集成好了,可以用Junit先测试一下。我们开始:

 

 

 将如下包拷贝到WEB-INF/lib下,并add to buid path。就这么个看似简单的加jar包都会出问题。我看到有些人只把jar 包加入到WEB-INF/lib下就完了,myeclipse会自动将jar包加入到环境变量中,但咱们免费的eclipse没有那么智能要自己右键 build path-->add to build path才行。 这个倒还好,更重要的是 不 要 右击 项目名,直接 build path-->configure build path。 我之前就是这么干的。这样看起来很好,好像不会占用太多空间,可是这是要付出代价的,直接报错! 这点空间咱省不得。

 

Spring4.0.相关jar包:

 

spring-framework-4.0.2.RELEASE-dist\spring-framework-4.0.2.RELEASE\libs 目录下拷贝这些:

 

Hibernate4.5.1相关jar包:

 

在hibernate-search-4.5.1.Final-dist\hibernate-search-4.5.1.Final\dist\lib\required目录下拷贝这些必需的jar包

(BB:这里required的一些jar包跟4.5.0有些不一样,而且4.5.0有些包跟struts2.3.16.1里的重复了,重复了就用Hibernate里的。到4.5.1重复的就少了,好像就一个javassist-3.x.x.GA.jar重复了,hibernate里的版本高些,我们就用它的)

 

 

 

在hibernate-search-4.5.1.Final-dist\hibernate-search-4.5.1.Final\dist\lib\provided目录下拷贝这些(YY:这些是必需的,不然启动的时候就报错,大家可以试试,我就是看了启动错误信息才去加它们的):

 

 

 

 

接下来数据库驱动包,我用的是mysql5.6.14(Select @@Version使用此命令可查看数据库版本),驱动jar用的是mysql-connector-java-5.1.10.jar。

 

数据库连接池我用的是c3p0。

在c3p0-0.9.5-pre8.bin\c3p0-0.9.5-pre8\lib目录下拷贝:

 

 

 

还需要两个额外jar包(aspectjweaver.jar和aopalliance.jar):

①从官网下载的竟然是一个jar包叫aspectj-1.8.0.M1.jar。用好压解压出来,在aspectj-1.8.0.M1\lib可以看到如下jar包:


拷贝aspectjweaver.jar,以前的教程中还要加入aspectjrt.jar。我看过一篇关于spring和Hibernate集成的文章,那位印度大神没有用aspectjrt.jar。我自己试了很多遍,不用这个的确可以。而且我根据错误信息提示只加入aspectjweaver.jar这一个jar包问题就解决了。这里我们也就只用这一个jar包。我感觉jar包这东西并不是多多益善的,能精简咱尽量精简一下。

 

② 官网上下载的比较新的版本是aopalliance.zip,解压后就可以看到aopalliance.jar。用以前的aopalliance-1.0.jar亲测也是可以的。 但是用最新版的aopalliance-alpha1.jar就不行!

 

另外如果用最新版的jstl-1.2.1。可以到官网上下载。已经不是以前的jstl.jar和standard.jar了。 如果只用目前最新版的功能,不想兼容以前的版本,只需要下载这个两个jar包:taglibs-standard-spec-1.2.1.jar,taglibs-standard-impl-1.2.1.jar。

目前为止,除了struts相关jar包没有加入之外,该加的我们都加完了。为了用最新的jar包搭一个框架,我真的是殚精竭虑呀。太曲折了,说出来都是泪呀,正因为如此我才要把这些贴出来。

 

下面开始最麻烦的配置了。 配置的时候大家尽量从官网上下载的文档中拷贝。

这样不容易错,而且官方文档也会使用最新的和最合理的配置方式。这里就不跟大家说如果从手册上找了。

 

我看到网上好多直接拷贝的配置文件,感觉好乱,而且几乎都是同一个结构。

 

这里给出自认为较合理的配置方式,并把自己在配置过程中遇到的问题说一下。

 

大家知道hibernate有个hibernate.cfg.xml。网上好多人直接把c3p0和Hibernate的相关属性都配在spring里了。 我感觉这样乱不说,spring的配置文件也有些臃肿。事实上这样

并没有使spring的配置文件减小,但我个人感觉上是的,因为把许多东西都配在jdbc.properties文件里了,然后在applicationContext.xml里引用它,这样感觉上就不那么臃肿

了。而且想查看什么属性直接点开jdbc.properties就能很清楚的看到,不会跟spring的事务和bean搅在一起,这样阅读的时候心里会好受些。

 

 在src下新建jdbc.properties文件。

内容如下:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///ahau
jdbc.username=root
jdbc.password=root

hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.hbm2ddl.auto=update
hibernate.show_sql=true
hibernate.format_sql=false
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=false
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext

c3p0.acquireIncrement=5
c3p0.idleConnectionTestPeriod=60
c3p0.initialPoolSize=10
c3p0.maxIdleTime=60
c3p0.maxPoolSize=30
c3p0.maxStatements=200
c3p0.maxStatementsPerConnection=30
c3p0.minPoolSize=5


注意这里有一个巨大插曲。就在这里我已经吃过两次亏了。 这是第一次:http://blog.csdn.net/ahau10/article/details/21515453。

我这次学乖了在每个属性前面都加上前缀了,几乎所有的官方文档上也都是这么写的。  我以为这回这样写总不会错了吧。

请看下面的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-4.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.0.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
           http://www.springframework.org/schema/tx 
           http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
         
         <context:annotation-config/>
         <context:component-scan base-package="cn.ahau"/>
            
         <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}"/>
            
            <!-- <property name="acquireIncrement" value="${c3p0.acquireIncrement}"/> -->
            <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}"/>
            <property name="initialPoolSize" value="${c3p0.initialPoolSize}"/>
            <property name="maxIdleTime" value="${c3p0.maxIdleTime}"/>
            <property name="maxPoolSize" value="${c3p0.maxPoolSize}"/>
            <property name="maxStatements" value="${c3p0.maxStatements}"/>
            <property name="maxStatementsPerConnection" value="${c3p0.maxStatementsPerConnection}"/>
            <property name="minPoolSize" value="${c3p0.minPoolSize}"/>
        </bean>


        <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="mappingResources">
            <list>
                <value>cn/ahau/domain/User.hbm.xml</value>
            </list>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="dialect">${hibernate.dialect}</prop>
                    <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                    <prop key="show_sql">${hibernate.show_sql}</prop>
                    <prop key="format_sql">${hibernate.format_sql}</prop>
                    <prop key="cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
                    <prop key="cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
                    <prop key="cache.provider_class">${hibernate.cache.provider_class}</prop>
                    <prop key="hibernate.current_session_context_class">${hibernate.current_session_context_class}</prop>
                </props>
            </property>
        </bean>
        <context:property-placeholder location="classpath:jdbc.properties"/>
    
    
    
    <!-- 第一种方法配置事务 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    <bean id="userDao" class="cn.ahau.dao.impl.UserDaoImpl"/>
  
</beans>


我用红色标记的地方就是我第二次栽的地方。   开始的时候我写成这样:<prop key="hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>,我以为这个key随便写写没什么嘛,毕竟后面都写对了,启动的时候也不报错。可是在我开始保存对象的时候报错了,总是说表不存在!我想当然的以为Hibernate会自动创建表呢。谁知道这里的key不加前缀它就识别不了啊。。。


下面依次在src下建 包、表、对象映射文件。


User.java

package cn.ahau.domain;

public class User {
    private int id;
    private String name;
    private String password;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public User() {
        super();
    }
    
}

UserDao.java


package cn.ahau.dao;

import cn.ahau.domain.User;

public interface UserDao {
    void add(User user);
    User query(String fieldName);
}


UserDaoImpl.java

package cn.ahau.dao.impl;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cn.ahau.dao.UserDao;
import cn.ahau.domain.User;

@Transactional
public class UserDaoImpl implements UserDao{
    
    @Resource
    private SessionFactory sessionFactory;

    public void add(User user) {
        sessionFactory.getCurrentSession().save(user);
        
    }

    @Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
    @SuppressWarnings("unchecked")
    public User query(String fieldName) {
        Criteria c = sessionFactory.openSession().createCriteria(User.class);
        c.add(Restrictions.eq("name", fieldName));
        User u = (User) c.uniqueResult();
        return u;
    }
}


注意这里又有巨大插曲了。  先看query方法,只是查询因此不希望开启事务,这里为什么是openSession。而不是跟save方法一样采用sessionFactory.getCurrentSession()这种方式。  解决这个问题实在是太曲折了。如果采用sessionFactory.getCurrentSession()这种方式,则报:createQuery is not valid without active transaction。网上好多都说改这个配置(这个在jdbc.properties里)hibernate.current_session_context_class,改成thread和其他的都不行。改成thread则引报其他错误。最后终于找到一篇文章,解决办法就是用openSession。  原文地址如下:

http://blog.csdn.net/wzk527/article/details/8543480

在看看save方法。以前的教程用jta的时候是用persist()方法的。现在使用persist方法时,第一次表单提交时保存能成功,浏览器点击回退时再次保存就会报

detached entity passed to persist。改成save方法时问题解决。 关于session这一块儿我还不大清楚,也许还有其他的解决办法。


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 package="cn.ahau.domain">
    <class name="User" table="user">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name" unique="true"/>
        <property name="password" column="password"/>
    </class>
</hibernate-mapping>


这里也有个小插曲。如果保存不成功,报类似于如下错误:

Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister

仔细检查实体类的字段例如password name 等名称可能是数据库保留字,所以最好取个别名。


下面在src下新建一个junit testcase。

UserTest.java

package cn.ahau.test;

import static org.junit.Assert.*;

import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.ahau.dao.UserDao;
import cn.ahau.domain.User;

public class UserTest {
    
    private static UserDao userDao;
    
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        try {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
            userDao = (UserDao)applicationContext.getBean("userDao");
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
    }
    
    @Test
    public void testAddUser() {
        User user = new User();
        user.setName("hh");
        user.setPassword("aa");
        userDao.add(user);
    }

}


运行后出现绿条,检查数据库user表已经创立。SH已经搭好了,现在只剩下最好一步了。


在WEB-INF/下,web.xml文件下

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>ssh2</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
    <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!-- 对Spring容器进行实例化 -->
    <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
      <!-- 配置struts2 -->
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <filter>  
    <filter-name>openSessionInViewFilter</filter-name>  
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>  
    <init-param>  
    <param-name>singleSession</param-name>  
    <param-value>true</param-value>  
    </init-param>  
</filter> 
</web-app>


在src下,新建cn.ahau.action包,UserAction 类。

UserAction.java

package cn.ahau.action;

public class UserAction {
    public String test(){
        return "home";
    }
}


在src下新建struts.xml

struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
    
<struts>
    <!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 -->
    <constant name="struts.i18n.encoding" value="UTF-8"/>
    <!-- 该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理。
    如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。 -->
    <constant name="struts.action.extension" value="do,action"/>
    <!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 -->
    <constant name="struts.serve.static.browserCache" value="false"/>
    <!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 -->
    <constant name="struts.configuration.xml.reload" value="true"/>
    <!-- 开发模式下使用,这样可以打印出更详细的错误信息 -->
    <constant name="struts.devMode" value="true" />
     <!-- 默认的视图主题 -->
    <constant name="struts.ui.theme" value="simple" />
    <!-- action对象由spring负责创建 -->
    <constant name="struts.objectFactory" value="spring" />
    
     <package name="user" namespace="/user" extends="struts-default">
        <action name="action_*" class="userList" method="{1}">
            <result name="home">/index.jsp</result>
        </action>
    </package>
</struts>


小插曲: <constant name="struts.objectFactory" value="spring" />这一句表明把action交由spring管理。因此要确保1)struts2-spring-plugin-2.3.16.1.jar已经加入到build path中。 2) applicationContext.xml中配置了相关的bean。 这里要在此xml下追加<bean id="userList" class="cn.ahau.action.UserAction"/>


然后在WebCotent目录下新建一个index.jsp。


将项目加入到服务器中,启动服务器后,出现片红色信息,最后几句类似于如下:

四月 29, 2014 11:59:30 下午 org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-apr-8080"]
四月 29, 2014 11:59:30 下午 org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-apr-8009"]
四月 29, 2014 11:59:30 下午 org.apache.catalina.startup.Catalina start
INFO: Server startup in 10803 ms

恭喜你启动成功了。 在浏览器地址栏输入:http://localhost:8080/cjbssh2/user/action_test.do

回车后你就能看到index.jsp里的内容了。  这里为了省事并没有写service层。 说的有些乱,又有些粗糙。主要是跟大家分享一下心得。本文最大的价值恐怕也就是这个几个jar包了。我将这个小Demo传上来了,虽然没什么价值,但是xml配置都是我一点一点垒起来的,很多都是是从官方手册上拷贝下来的。 本人也是第一次搭框架,有什么错误的地方还请指出,以免误导他人,写写。

 

 demo地址:http://download.csdn.net/detail/ahau10/7273531

 

 

New-->other-->搜索框输入Junit,选择junit test case ,输入名称UserTest,

注意勾选上setUpBeforeClass


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值