要整合SSH,简言之:将struts的Action交由Spring的容器来管理,hibernate的sessionFactory交由Spring容器来管理,而让web container启动时自动加载相关的Spring容器。
说是很简单,但我在进行整合时也是遇到了一些问题,主要是相关的jar包导入不全或导入的版本不相兼容所至,所以特别的在最后用图的形式贴出来。
如下图:
Struts (Web page) <---> Spring DI <--> Hibernate (DAO) <---> Database the summary is:
To integrate all those technologies together, you should..
- Integrate Spring with Hibernate with Spring’s “LocalSessionFactoryBean” class.
- Integrate Spring with Struts via Spring’s ready make Struts plug-in – “ContextLoaderListener“. 如下为项目结构图:见projectView.jpg, 项目用到的lib:见projectViewLibs.jpg。 主要步骤如下: 1,新建一web project后,修改web.xml如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
- http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
- <display-name>java_eBooking</display-name>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- <!--
- 1、指定spring的配置文件,默认从webroot根目录(即webroot/WEB-INF/,跟web.xml要并列同级目录)寻找配置文件,
- 我们可以通过spring提供的classpath*:前缀指定从类路径下寻找 contextConfigLocation
- -->
- <!--
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>/WEB-INF/classes/applicationContext.xml
- </param-value>
- </context-param>
- -->
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath*:applicationContext.xml</param-value>
- </context-param>
- <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>
- </web-app> 2,在src下新建struts.xml.具体如下:
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
- "http://struts.apache.org/dtds/struts-2.0.dtd">
- <struts>
- <constant name="struts.objectFactory" value="spring" />
- <constant name="struts.devMode" value="true" />
- <package name="product" extends="struts-default">
- <action name="list" class="hellowordAction" method="execute">
- <result>ebooking/list.jsp</result>
- <result name="input">ebooking/list.jsp</result>
- </action>
- <action name="remove" class="hellowordAction" method="remove">
- <result>ebooking/list.jsp</result>
- <result name="input">ebooking/list.jsp</result>
- </action>
- <action name="save" class="hellowordAction" method="save">
- <result>ebooking/list.jsp</result>
- <result name="input">ebooking/list.jsp</result>
- </action>
- </package>
- </struts> 3,在src下新建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"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-2.5.xsd">
- <bean id="productService"
- class="com.ebooking.service.EbookingService" />
- <bean id="hellowordService"
- class="com.ebooking.service.HelloWordService">
- <property name="helloWordDao" ref="helloWordDao"></property>
- </bean>
- <bean id="eBookingAction"
- class="com.ebooking.web.struts.action.EbookingAction"
- scope="prototype">
- </bean>
- <bean id="hellowordAction"
- class="com.ebooking.web.struts.action.HelloWordAction"
- scope="prototype">
- <constructor-arg ref="hellowordService" />
- </bean>
- <bean id="helloWordDao"
- class="com.ebooking.dao.impl.HelloWordDaoImpl">
- <property name="sessionFactory" ref="sessionFactory" />
- </bean>
- <!--加载PropertyPlaceholderConfigurer后,就可以使用${jdbc.username}占位符了-->
- <bean
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="locations">
- <value>classpath:conn/jdbc.properties</value>
- </property>
- </bean>
- <bean id="sessionFactory"
- class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
- <property name="dataSource" ref="dataSource" />
- <property name="mappingResources">
- <list>
- <value>com/ebooking/model/ebooking.hbm.xml</value>
- </list>
- </property>
- <property name="hibernateProperties">
- <props>
- <prop key="hibernate.dialect">
- org.hibernate.dialect.SQLServerDialect
- </prop>
- <prop key="hibernate.show_sql">true</prop>
- <prop key="hibernate.generate_statistics">true</prop>
- </props>
- </property>
- </bean>
- <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="minPoolSize" value="2" />
- <property name="initialPoolSize" value="3" />
- <property name="maxPoolSize" value="10" />
- <property name="maxIdleTime" value="1800" />
- <property name="acquireIncrement" value="2" />
- <property name="maxStatements" value="3" />
- <property name="idleConnectionTestPeriod" value="1800" />
- <property name="acquireRetryAttempts" value="3" />
- </bean>
- </beans> 4,在“src/conn/”新建jdbc.properties:
- jdbc.driverClassName=net.sourceforge.jtds.jdbc.Driver
- jdbc.url=jdbc:jtds:sqlserver://localhost:1433/jpetstore
- jdbc.username=sa
- jdbc.password=db*888 5,src目录下新建log4j.xml,具体如下:
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
- <log4j:configuration>
- <appender name="logs"
- class="org.apache.log4j.RollingFileAppender">
- <param name="Encoding" value="GBK" />
- <param name="File" value="logs/logs.log" />
- <param name="MaxBackupIndex" value="300" />
- <param name="MaxFileSize" value="100000" />
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern"
- value="%d{ISO8601} %p - %m %n" />
- </layout>
- <filter class="org.apache.log4j.varia.LevelRangeFilter">
- <param name="LevelMin" value="info" />
- <param name="LevelMax" value="error" />
- <param name="acceptOnMatch" value="true" />
- </filter>
- </appender>
- <logger name="com.ebooking.service" additivity="false">
- <level value="info" />
- <appender-ref ref="logs" />
- </logger>
- <root>
- <priority value="info" />
- <appender-ref ref="logs" />
- </root>
- </log4j:configuration>
- 注意: 由于 我并没有用到事务,所有在web.xml中并没有配置 openSessionInView这个filter, 如有用到或者当进行session.load(id)时必须在web.xml中作如下配置,否则会报错。 报错信息大致如下: org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition. 当有用到事务,但并没有指定用 openSessionInView时,spring就会将所有的事务当作是只读事务来处理,当进行hibernateTemplate.save(ebooking)时就会报一个说是当前session处理于 read only状态,禁止进行写操作。 <filter> <filter-name>openSessionInView</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>sessionFactoryBeanName</param-name> <param-value>sf</param-value> </init-param> </filter> <filter-mapping> <filter-name>openSessionInView</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>