SSH 指 Struts2(表現層)+ Spring(業務層)+ Hibernate(資料層)。整合核心在於:Spring 管理 Hibernate SessionFactory、事務與 Bean 生命週期;Struts2 透過插件將 Action 交給 Spring 實例化。
| 模組 | 關鍵 Jar | 數量 |
|---|---|---|
| Struts2 | struts2-core, struts2-spring-plugin-2.3.15.3.jar(整合關鍵) | 14 |
| Spring | spring-orm.jar(Hibernate 整合)、spring-web.jar(Web 容器整合) | 13 |
| Hibernate | hibernate3.jar、ehcache.jar(二級快取) | 10 |
| 資料庫 | mysql-connector-java-5.0.8-bin.jar | 1 |
注意:commons-logging、javassist 等共用包採用較高版本統一。
public interface UserDao { boolean insert(User user); }
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
@Override public boolean insert(User user) {
getHibernateTemplate().save(user);
return true;
}
}
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/>
<property name="user" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<property name="mappingLocations" value="classpath:king/domain/User.hbm.xml"/>
</bean>
<bean id="userDao" class="king.dao.impl.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 宣告式事務 -->
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:advice id="adviceId" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="adviceId" pointcut="execution(* king.dao.impl.*.*(..))"/>
</aop:config>
HibernateDaoSupport 提供 getHibernateTemplate(),底層封裝 Session 操作。LocalSessionFactoryBean 為 FactoryBean,將原 hibernate.cfg.xml 設定移入 Spring 容器。proxy-target-class="true" 強制 CGLIB。SessionFactory,攔截 DAO 方法實現宣告式事務。<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>
<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>
<action name="AddUser" class="king.action.UserAction" method="addUser">
<result name="success" type="redirect">/success.html</result>
</action>
public class UserAction extends ActionSupport implements ModelDriven<User> {
private User user = new User();
private UserDao userDao; // Spring 注入
public void setUserDao(UserDao userDao) { this.userDao = userDao; }
public String addUser() { return userDao.insert(user) ? "success" : "fail"; }
}
struts2-spring-plugin.jar 內的 struts-plugin.xml 將 Struts 的 ObjectFactory 替換為 Spring,使 Action 的依賴由 Spring 注入。ContextLoaderListener(來自 spring-web.jar)啟動時載入 applicationContext.xml,建立所有單例 Bean,Action 獲取時直接從容器取得。@Test public void test1(){
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao user = app.getBean(UserDao.class);
User u = new User(); u.setAge(1); u.setName("King");
user.insert(u); app.close();
}
至此 SSH 三層整合完成,後續擴展僅需在 Service 層注入 DAO、在 Action 注入 Service,遵循依賴倒置原則即可。
