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

MyBatis 3.3 + Struts 2.3.24 + MySQL 5.1 整合開發環境搭建完整教學(含二級快取驗證)

     編輯:Java 相關知識

前言:經典 SSH 輕量級替代方案

雖然 Spring Boot 早已成為主流,但理解「Struts 2 + MyBatis」這類非 Spring 管理的整合架構,有助於掌握 MVC 分層、連線池、快取、事務控制等核心概念。本文將從零搭建一個可運行的 Web 專案,涵蓋 Jar 依賴、web.xml/struts.xml/mybatis-config.xml/mapper 配置、DAO/Service/Action 分層實作、前端 AJAX 互動,並實測 MyBatis 二級快取(Ehcache)效果。


專案結構與核心依賴

目錄結構

src/ ├─ ms/ │ ├─ action/ │ ├─ dao/ │ │ └─ base/ │ ├─ model/ │ └─ service/ WebContent/ ├─ WEB-INF/ │ ├─ lib/           ← 所有 Jar 放這裡 │ ├─ web.xml │ ├─ struts.xml │ ├─ mybatis-config.xml │ └─ ms/model/userMapper.xml ├─ js/jquery-1.11.1.min.js └─ index.jsp

核心 Jar 清單 (放入 WEB-INF/lib)

  • Struts 2.3.24 核心包 (struts2-core, xwork-core, ognl, freemarker 等)
  • MyBatis 3.3 (mybatis-3.3.0.jar, mybatis-ehcache)
  • MySQL Connector/J 5.1.22
  • Gson 2.1 (JSON 轉換)
  • Ehcache 核心包 (ehcache-core, slf4j-api)
  • Commons 系列 (commons-logging, commons-io, commons-lang)
  • Log4j (log4j-1.2.17.jar)

配置檔詳細解析

1. web.xml:Struts 2 核心過濾器

<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>

關鍵點:StrutsPrepareAndExecuteFilter 會攔截所有 *.action 請求,內部邏輯:
① 排除模式匹配 → ② 尋找 ActionMapping → ③ 執行 Action → ④ 結果處理。

2. struts.xml:動作映射與 JSON 結果

<struts> <constant name="struts.devMode" value="false"/> <package name="default" extends="struts-default,json-default"> <global-results> <result type="json"> <param name="root">json</param> <param name="contentType">text/html</param> </result> </global-results> <action name="addUser" class="ms.action.UserAction" method="addUser"> <result>.</result> </action> <action name="queryAllUser" class="ms.action.UserAction" method="queryAllUser"> <result>.</result> </action> </package> </struts>

重點:繼承 json-default 才能使用 type="json" 結果類型;root 參數指定要序列化的屬性名(Action 中需有 getJson() 或同名屬性)。

3. mybatis-config.xml:資料源、連線池、二級快取

<configuration> <settings> <setting name="cacheEnabled" value="true"/> </settings> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/demo"/> <property name="username" value="root"/> <property name="password" value="admin"/> <property name="poolMaximumActiveConnections" value="10"/> <property name="poolPingEnabled" value="true"/> <property name="poolPingQuery" value="select 1"/> </dataSource> </environment> </environments> <mappers> <mapper resource="ms/model/userMapper.xml"/> </mappers> </configuration>

連線池關鍵參數:POOLED 類型使用 MyBatis 內建池,poolMaximumActiveConnections 限制最大活躍連線,poolPingQuery 定期檢測連線存活。

4. userMapper.xml:SQL 映射與 Ehcache 二級快取

<mapper namespace="UserMapper"> <cache type="org.mybatis.caches.ehcache.LoggingEhcache"> <property name="timeToIdleSeconds" value="3600"/> <property name="timeToLiveSeconds" value="3600"/> <property name="maxEntriesLocalHeap" value="1000"/> <property name="maxEntriesLocalDisk" value="10000000"/> <property name="memoryStoreEvictionPolicy" value="LRU"/> </cache> <insert id="saveUser" parameterType="ms.model.User"> insert into USER(account, name, address) values (#{account}, #{name}, #{address}) </insert> <select id="queryAllUser" resultType="ms.model.User"> select u.id, u.account, u.name, u.address from USER u </select> </mapper>

注意:實體類 User 必須實作 Serializable,否則 Ehcache 序列化失敗。


核心 Java 程式碼實作

1. MySessionFactory:SqlSessionFactory 單例

public class MySessionFactory { private static SqlSessionFactory factory; private MySessionFactory() {} public static synchronized SqlSessionFactory getSqlSessionFactory() { if (factory == null) { try { factory = new SqlSessionFactoryBuilder() .build(Resources.getResourceAsReader("mybatis-config.xml")); } catch (IOException e) { throw new RuntimeException(e); } } return factory; } }

2. UserDao:手動事務控制

public class UserDao { public void add(User user) { SqlSession session = MySessionFactory.getSqlSessionFactory().openSession(); try { session.insert("UserMapper.saveUser", user); session.commit(); } catch (Exception e) { session.rollback(); throw e; } finally { session.close(); } } public List<User> queryAllUser() { SqlSession session = MySessionFactory.getSqlSessionFactory().openSession(); try { // 開啟查詢快取 session.getConfiguration().setCacheEnabled(true); List<User> list = session.selectList("UserMapper.queryAllUser"); session.commit(); return list; } finally { session.close(); } } }

3. UserAction:JSON 回應處理

public class UserAction { private UserService userService = new UserService(); public void addUser() { PrintWriter out = null; try { HttpServletRequest req = ServletActionContext.getRequest(); HttpServletResponse resp = ServletActionContext.getResponse(); resp.setContentType("text/html;charset=UTF-8"); User user = new User(); user.setAccount(req.getParameter("account")); user.setName(req.getParameter("name")); user.setAddress(req.getParameter("address")); userService.add(user); out = resp.getWriter(); out.write(new Gson().toJson("success")); } catch (Exception e) { e.printStackTrace(); if (out != null) out.write(new Gson().toJson("fail")); } finally { if (out != null) { out.flush(); out.close(); } } } public void queryAllUser() { PrintWriter out = null; try { HttpServletResponse resp = ServletActionContext.getResponse(); resp.setContentType("text/html;charset=UTF-8"); List<User> list = userService.queryAllUser(); out = resp.getWriter(); out.write(new Gson().toJson(list)); } catch (Exception e) { e.printStackTrace(); if (out != null) out.write(new Gson().toJson("fail")); } finally { if (out != null) { out.flush(); out.close(); } } } }

前端頁面:jQuery AJAX 互動

<script src="js/jquery-1.11.1.min.js"></script> <script> $(function() { // 載入用戶列表 $.post('queryAllUser.action', function(data) { $.each(data, function(i, user) { $('#userList').append("<li>id=" + user.id + ", " + user.account + "</li>"); }); }, 'json'); // 新增用戶 $('#addUser').click(function() { $.post('addUser.action', { account: $('#account').val(), name: $('#name').val(), address: $('#address').val() }, function(data) { if (data === 'success') { $('#userList').append("<li>" + $('#account').val() + "</li>"); alert('新增成功'); } }, 'json'); }); }); </script>

二級快取實測驗證

  1. 啟動專案,打開瀏覽器開發者工具 Network 頁籤。
  2. 首次點擊「查詢」→ Console 輸出 SQL:select u.id, u.account... from USER u(快取未命中,查資料庫)。
  3. 重新整理頁面或再次查詢 → Console 無 SQL 輸出,資料直接從 Ehcache 返回(快取命中)。
  4. Ehcache 日誌會記錄 Cache Hit / Cache Miss。

✅ 驗證成功標準

  • 第二次查詢不打印 SQL
  • 響應時間明顯縮短
  • Ehcache 統計顯示 hitCount 遞增

常見坑點與解決方案

問題原因解決
快取不生效User 未實作 Serializable實作 java.io.Serializable
快取不生效mybatis-config.xml 未開啟 cacheEnabled設定 <setting name="cacheEnabled" value="true"/>
快取不生效mapper 未配置 <cache>在 userMapper.xml 加入 Ehcache 配置
連線池耗盡poolMaximumActiveConnections 過小依併發量調大,並確保 finally 關閉 session
中文亂碼資料庫/連線/頁面編碼不一致統一 UTF-8,URL 加 useUnicode=true&characterEncoding=UTF-8

總結

本教學完整呈現了「Struts 2 + MyBatis」無 Spring 整合的全棧實作,從環境搭建、配置解析、分層代碼到快取驗證。掌握此架構有助於理解:
① MVC 職責分離 ② MyBatis 靈活 SQL 映射 ③ 連線池資源管理 ④ 二級快取透明加速 ⑤ 手動事務邊界控制。
若專案規模增長,建議遷移至 Spring Boot + MyBatis-Plus,享受自動配置、聲明式事務、分頁插件等現代化紅利。

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