首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

SSH 整合經典教學:Struts 2.3.24 + Spring 4.1.6 + Hibernate 4.3.11 + MySQL 5.5 完整搭建與核心機制驗證

     編輯:Java 相關知識

前言:為什麼還要學習傳統 SSH?

雖然 Spring Boot 早已統一江湖,但「Struts 2 + Spring + Hibernate」這套經典整合架構完整展示了:MVC 分層、IOC 容器管理、AOP 事務/切面、Hibernate ORM 映射、二級快取、連線池、攔截器鏈等企業級開發核心機制。透過手動搭建並驗證每個功能點,能建立扎實的底層認知,為後續排查 Spring Boot 自動配置問題、設計微服務架構奠定堅實基礎。本文將從零搭建並驗證六大核心目標。


六大驗證目標

  1. SSH 基礎整合跑通 (增刪查)
  2. C3P0 連線池配置與調優
  3. Hibernate 二級快取 (Ehcache) 驗證
  4. Spring 聲明式事務 (AOP) 驗證
  5. Spring IOC 管理 Struts Action (單例/多例)
  6. Spring AOP 自定義切面驗證

環境準備與資料庫

開發環境

  • Eclipse for Java EE / IntelliJ IDEA
  • JDK 1.7+ (範例用 1.7.0_79)
  • MySQL 5.5.25
  • Navicat (可選,GUI 管理工具)

建立測試資料庫

CREATE DATABASE demo DEFAULT CHARSET utf8; USE demo; CREATE TABLE `user` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `account` VARCHAR(200) NOT NULL, `name` VARCHAR(200) NOT NULL, `address` VARCHAR(1000) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

專案結構與 Jar 依賴

採用傳統 WEB-INF/lib 手動放 Jar 方式 (亦可改用 Maven),核心包包含:

  • Struts 2.3.24 全家桶
  • Spring 4.1.6 (core, context, orm, tx, aop, web, test)
  • Hibernate 4.3.11 (core, ehcache, validator, c3p0)
  • MySQL Connector/J 5.1.35+
  • C3P0 0.9.5+
  • Ehcache 2.10+
  • Gson 2.3+ (JSON)
  • Commons 系列、Log4j、SLF4J、Javassist、Antlr、Dom4j 等傳遞依賴

核心配置檔深度解析

1. web.xml:雙核心啟動器

<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>*.action</url-pattern> </filter-mapping> <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>

關鍵:ContextLoaderListener 啟動 Spring 根容器 (載入 Service/Dao/事務/資料源);StrutsPrepareAndExecuteFilter 啟動 Struts 核心控制器 (載入 Action)。

2. applicationContext.xml:Spring 總配置 (核心大檔)

<beans ...> <!-- 1. 掃描註解 Bean (排除 Controller 留給 Struts) --> <context:component-scan base-package="ssh" /> <!-- 2. C3P0 連線池 --> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/demo"/> <property name="user" value="root"/> <property name="password" value="root"/> <property name="initialPoolSize" value="30"/> <property name="minPoolSize" value="30"/> <property name="maxPoolSize" value="80"/> <property name="acquireIncrement" value="1"/> <property name="maxIdleTime" value="60"/> <property name="acquireRetryAttempts" value="60"/> <property name="acquireRetryDelay" value="1000"/> <property name="breakAfterAcquireFailure" value="false"/> </bean> <!-- 3. SessionFactory (Hibernate + 二級快取) --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.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> <prop key="hibernate.cache.use_second_level_cache">true</prop> <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop> <prop key="hibernate.cache.use_query_cache">true</prop> <prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</prop> </props> </property> <property name="mappingLocations"> <value>classpath:ssh/model/User.hbm.xml</value> </property> </bean> <!-- 4. 事務管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!-- 5. 聲明式事務 (AOP) --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="serviceMethods" expression="execution(* ssh.service..*.*(..))"/> <aop:advisor pointcut-ref="serviceMethods" advice-ref="txAdvice"/> </aop:config> <!-- 6. 自定義 AOP 切面測試 --> <bean id="aopTest" class="ssh.aop.AopTest"/> <bean id="myAop" class="ssh.aop.MyAop"/> <aop:config proxy-target-class="true"> <aop:aspect ref="myAop"> <aop:pointcut id="testMethods" expression="execution(* ssh.aop.AopTest.test*(..))"/> <aop:before pointcut-ref="testMethods" method="before"/> <aop:after pointcut-ref="testMethods" method="after"/> </aop:aspect> </aop:config> </beans>

配置亮點解析

區塊關鍵點
C3P0initialPoolSize=minPoolSize 避免啟動擴容抖動;maxPoolSize 需 < MySQL max_connections;acquireRetryAttempts/Delay 緩衝 DB 重啟窗口
二級快取use_second_level_cache=true + EhCacheRegionFactory + 實體類實作 Serializable + .hbm.xml 配置 <cache usage="read-write"/>
事務傳播REQUIRED 最常用:有事務加入,無則新建;rollback-for="Exception" 確保檢查異常也回滾
AOP 切面proxy-target-class="true" 強制 CGLIB 代理 (不依賴介面);before/after 對應前置/後置通知

3. struts.xml:Action 交給 Spring 管理

<struts> <constant name="struts.objectFactory" value="spring"/> <constant name="struts.devMode" value="false"/> <package name="default" extends="struts-default,json-default"> <global-results> <result type="json"> <param name="root">json</param> </result> </global-results> <action name="addUser" class="userAction" method="addUser"><result>.</result></action> <action name="queryAllUser" class="userAction" method="queryAllUser"><result>.</result></action> </package> </struts>

核心:struts.objectFactory=spring 讓 Struts 從 Spring 容器獲取 Action Bean (id="userAction"),實現 IOC 管理。

4. User.hbm.xml:Hibernate 映射與快取

<hibernate-mapping package="ssh.model"> <class name="User" table="user"> <cache usage="read-write"/> <id name="id" column="id"><generator class="increment"/></id> <property name="account" column="account"/> <property name="name" column="name"/> <property name="address" column="address"/> </class> </hibernate-mapping>

核心代碼實作 (關鍵註解版)

BaseDao:繼承 HibernateDaoSupport

@Repository public class BaseDao extends HibernateDaoSupport { @Resource public void setMySessionFactory(SessionFactory sf) { super.setSessionFactory(sf); } }

UserDao:HibernateTemplate 操作 + 查詢快取控制

@Repository public class UserDao extends BaseDao { public void add(User user) { getHibernateTemplate().save(user); } @SuppressWarnings("unchecked") public List<User> queryAllUser() { HibernateTemplate ht = getHibernateTemplate(); ht.setCacheQueries(true); // 開啟查詢快取 List<User> list = (List<User>) ht.find("from User"); ht.setCacheQueries(false); return list; } }

UserService:@Service + @Resource 注入 Dao

@Service public class UserService { @Resource private UserDao userDao; public void add(User user) { userDao.add(user); } public List<User> queryAllUser() { return userDao.queryAllUser(); } }

UserAction:@Controller + Spring 管理 + JSON 回應

@Controller public class UserAction { @Resource private UserService userService; @Resource private AopTest aopTest; // 驗證自定義 AOP public void addUser() { /* 參數接收、userService.add、Gson 回應 success/fail */ } public void queryAllUser() { aopTest.test1(); aopTest.test2(); // 觸發自定義切面 /* userService.queryAllUser、Gson 回應 List */ } }

AopTest / MyAop:自定義切面驗證

public class AopTest { public void test1() { System.out.println("AopTest test1 running~"); } public void test2() { System.out.println("AopTest test2 running~"); } } public class MyAop { public void before() { System.out.println("before~"); } public void after() { System.out.println("after~"); } }

六大驗證實測與截圖說明

1. SSH 基礎跑通

瀏覽器訪問 index.jsp,點擊「添加」→ 後台印出 Hibernate SQL insert into user...,列表即時顯示新增資料;點擊「查詢」→ 列表顯示所有用戶。

2. C3P0 連線池驗證

配置 maxPoolSize=10,寫測試程式循環獲取 11 個連線 → 第 11 個阻塞等待。調大至 80 → 正常獲取。生產環境建議:maxPoolSize = (CPU 核心數 × 2) + 有效磁碟數,並監控 show processlist 確認實際佔用。

3. Hibernate 二級快取驗證

首次查詢 → Console 印出 select ... from user (Cache Miss);重新整理頁面再次查詢 → 無 SQL 印出 (Cache Hit),響應時間從 ~50ms 降至 ~5ms。Ehcache 統計 hitCount 遞增。

4. Spring 事務驗證

在 Service 某方法中連續 add(user1); throw new RuntimeException(); add(user2); → 資料庫僅插入 0 筆 (全回滾)。註解 @Transactional 或移除 AOP 配置 → 插入 1 筆 (事務失效)。

5. Spring IOC 管理 Action 驗證

Action 加 @Controller,struts.xml class="userAction" (Bean id)。並發請求 100 次 → 僅構造 1 次 (單例)。若需多例 → Spring 配置 scope="prototype"。注意:Struts 2 預設 Action 多例,交給 Spring 後變單例,需評估執行緒安全 (Action 欄位無狀態則安全)。

6. 自定義 AOP 切面驗證

查詢用戶時呼叫 aopTest.test1()/test2() → Console 輸出:
before~
AopTest test1 running~
after~
before~
AopTest test2 running~
after~
證明前置/後置通知正常織入。


常見坑點總結表

現象根因解決
Too many connectionsC3P0 maxPoolSize > MySQL max_connections調小 maxPoolSize 或調大 MySQL max_connections (my.cnf)
二級快取不生效User 未實作 Serializable / 映射檔缺 <cache>實作 Serializable + hbm.xml 加 <cache usage="read-write"/>
事務不回滾拋出檢查異常 / 未掃描到 tx:advicerollback-for="java.lang.Exception" + 確認 aop:config 掃描路徑
Action 非 Spring 管理struts.objectFactory 未設 springstruts.xml 加 <constant name="struts.objectFactory" value="spring"/>
ClassNotFound: EhCacheRegionFactory缺 hibernate-ehcache jar補齊 hibernate-ehcache 版本與 hibernate-core 一致

總結與遷移建議

本教學完整復現了傳統 SSH 架構的所有核心機制。掌握這些原理後,遷移至 Spring Boot 將輕鬆許多:
① application.yml 取代 xml 配置 ② @Transactional 取代 AOP xml ③ @Entity + JPA/Hibernate 取代 hbm.xml ④ @RestController 取代 Struts Action ⑤ spring-boot-starter-cache + @Cacheable 取代 Ehcache xml。
但無論框架如何演進,「連線池調優、快取策略、事務邊界、AOP 織入、Bean 生命週期」這些核心決策點永遠存在。願本文助你建立穩固的架構直覺。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved