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

Spring + SpringMVC + Hibernate 整合完整教程:從零構建 SSH 框架項目

     編輯:Java 綜合教學

前言:為什麼選擇 SpringMVC?

SpringMVC 作為一款優雅的 Web 框架,與 Struts2 並駕齊驅。雖然 Struts2 出世較早佔據一定優勢,但 SpringMVC 憑藉其註解驅動、靈活的控制器設計以及與 Spring 生態無縫整合的特性,逐漸成為企業級開發的主流選擇。本文將通過一個完整的用戶增刪改查(CRUD)實例,詳細演示 Spring、SpringMVC 與 Hibernate 的整合過程,幫助開發者快速掌握 SSH 框架的核心配置與開發模式。

項目準備與目錄結構

首先創建一個名為 test_ssh 的 Web 項目,確保引入以下核心 JAR 包:

  • Spring 核心包(spring-core, spring-context, spring-web, spring-webmvc, spring-orm, spring-tx, spring-jdbc)
  • Hibernate 核心包(hibernate-core, hibernate-entitymanager)
  • 數據庫驅動(mysql-connector-java)
  • 連接池(commons-dbcp, commons-pool)
  • JSON 處理(jackson-core, jackson-databind)
  • 其他:servlet-api, jsp-api, jstl, aopalliance, cglib 等

項目採用標準 Maven 目錄結構,配置文件統一放置在 src/main/resources/config/spring/ 目錄下。

實體類定義:基於註解的映射

創建 User 實體類,使用 JPA 註解進行 ORM 映射,採用 UUID 作為主鍵生成策略:

package com.tgb.entity;

import javax.persistence.*;
import org.hibernate.annotations.GenericGenerator;

@Entity
@Table(name = "T_USER")
public class User {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    @Column(length = 32)
    private String id;

    @Column(length = 32)
    private String userName;

    @Column(length = 32)
    private String age;

    // Getter/Setter 方法省略...
}

關鍵點解析:

  • @Entity:標識該類為持久化實體
  • @Table:指定對應的數據庫表名
  • @Id + @GeneratedValue:主鍵生成策略,此處使用 Hibernate 的 UUID 生成器
  • @Column:定義列屬性,如長度、是否為空等

核心配置文件詳解

1. Spring 通用配置 (spring-common.xml)

負責數據源、SessionFactory、事務管理器等核心基礎設施的配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="https://www.springframework.org/schema/context"
       xsi:schemaLocation="https://www.springframework.org/schema/beans 
       https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 數據源配置:使用 Spring 內置 DriverManagerDataSource -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost/test_ssh"/>
        <property name="username" value="root"/>
        <property name="password" value="1"/>
    </bean>

    <!-- SessionFactory 配置:整合 Hibernate 4 -->
    <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.hbm2ddl.auto">update</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>
        <property name="annotatedClasses">
            <list><value>com.tgb.entity.User</value></list>
        </property>
    </bean>

    <!-- 事務管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- 事務代理模板:定義事務傳播屬性 -->
    <bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
        <property name="transactionManager" ref="transactionManager"/>
        <property name="transactionAttributes">
            <props>
                <prop key="add*">PROPAGATION_REQUIRED,-Exception</prop>
                <prop key="modify*">PROPAGATION_REQUIRED,-myException</prop>
                <prop key="del*">PROPAGATION_REQUIRED</prop>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
</beans>

2. SpringMVC 配置 (spring-mvc.xml)

專注於 Web 層組件掃描、註解驅動、靜態資源映射及視圖解析:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="https://www.springframework.org/schema/context"
       xmlns:mvc="https://www.springframework.org/schema/mvc"
       xsi:schemaLocation="https://www.springframework.org/schema/beans 
       https://www.springframework.org/schema/beans/spring-beans.xsd
       https://www.springframework.org/schema/context 
       https://www.springframework.org/schema/context/spring-context-3.2.xsd
       https://www.springframework.org/schema/mvc 
       https://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">

    <!-- 掃描控制器包 -->
    <context:component-scan base-package="com.tgb"/>

    <!-- 啟用註解驅動 -->
    <mvc:annotation-driven/>

    <!-- 靜態資源訪問配置 -->
    <mvc:resources location="/js/" mapping="/js/**"/>

    <!-- 視圖解析器:JSP 模式 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

3. Web 部署描述符 (web.xml)

配置 Spring 容器啟動、SpringMVC 前端控制器、字符編碼過濾器及 OpenSessionInView 過濾器:

<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee">
    <display-name>ssh_demo</display-name>
    
    <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>

    <!-- 載入所有 Spring 配置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:config/spring/spring-*.xml</param-value>
    </context-param>

    <!-- Spring 容器監聽器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- SpringMVC DispatcherServlet -->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:config/spring/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- 字符編碼過濾器 -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- Hibernate OpenSessionInView 過濾器:解決懶加載問題 -->
    <filter>
        <filter-name>openSession</filter-name>
        <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>openSession</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

視圖層實現:JSP 頁面與前端交互

項目包含以下核心頁面:

  • login.jsp:系統入口頁面
  • index.jsp:用戶管理主界面,使用 JSTL 遍歷用戶列表,集成 jQuery 實現異步刪除
  • addUser.jsp:添加用戶表單頁面
  • editUser.jsp:編輯用戶信息頁面,預填充數據
  • success.jsp / error.jsp:操作結果提示頁面

index.jsp 關鍵代碼片段:

<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<script type="text/javascript" src="../js/jquery-1.7.1.js"></script>
<script>
    function del(id) {
        $.get("/test_ssh/user/delUser?id=" + id, function(data) {
            if ("success" == data.result) {
                alert("刪除成功");
                window.location.reload();
            } else {
                alert("刪除失敗");
            }
        });
    }
</script>

<h6><a href="/test_ssh/user/toAddUser">添加用戶</a></h6>
<table border="1">
    <tr><th>姓名</th><th>年齡</th><th>操作</th></tr>
    <c:if test="${!empty userList}">
        <c:forEach items="${userList}" var="user">
            <tr>
                <td>${user.userName}</td>
                <td>${user.age}</td>
                <td>
                    <a href="/test_ssh/user/getUser?id=${user.id}">編輯</a>
                    <a href="javascript:del('${user.id}')">刪除</a>
                </td>
            </tr>
        </c:forEach>
    </c:if>
</table>

業務邏輯層實現:Controller、Manager、DAO 三層架構

1. 控制層 - UserController

使用 @Controller 和 @RequestMapping 註解定義 REST 風格的 URL 映射:

package com.tgb.web;

@Controller
@RequestMapping("/user")
public class UserController {

    @Resource(name = "userManager")
    private UserManager userManager;

    @RequestMapping("/getAllUser")
    public String getAllUser(HttpServletRequest request) {
        request.setAttribute("userList", userManager.getAllUser());
        return "/index";
    }

    @RequestMapping("/getUser")
    public String getUser(String id, HttpServletRequest request) {
        request.setAttribute("user", userManager.getUser(id));
        return "/editUser";
    }

    @RequestMapping("/toAddUser")
    public String toAddUser() {
        return "/addUser";
    }

    @RequestMapping("/addUser")
    public String addUser(User user, HttpServletRequest request) {
        userManager.addUser(user);
        return "redirect:/user/getAllUser";
    }

    @RequestMapping("/delUser")
    public void delUser(String id, HttpServletResponse response) throws IOException {
        String result = "{\"result\":\"error\"}";
        if (userManager.delUser(id)) {
            result = "{\"result\":\"success\"}";
        }
        response.setContentType("application/json");
        response.getWriter().write(result);
    }

    @RequestMapping("/updateUser")
    public String updateUser(User user, HttpServletRequest request) {
        if (userManager.updateUser(user)) {
            return "redirect:/user/getAllUser";
        }
        return "/error";
    }
}

2. 服務層 - UserManager 接口與實現

定義業務邏輯契約,實現類委託 DAO 層執行具體操作:

// 接口定義
public interface UserManager {
    User getUser(String id);
    List<User> getAllUser();
    void addUser(User user);
    boolean delUser(String id);
    boolean updateUser(User user);
}

// 實現類
public class UserManagerImpl implements UserManager {
    private UserDao userDao;
    
    public void setUserDao(UserDao userDao) { this.userDao = userDao; }
    
    @Override public User getUser(String id) { return userDao.getUser(id); }
    @Override public List<User> getAllUser() { return userDao.getAllUser(); }
    @Override public void addUser(User user) { userDao.addUser(user); }
    @Override public boolean delUser(String id) { return userDao.delUser(id); }
    @Override public boolean updateUser(User user) { return userDao.updateUser(user); }
}

3. 數據訪問層 - UserDao 接口與 Hibernate 實現

使用 Hibernate 的 SessionFactory 進行數據庫操作,採用 HQL 查詢:

// 接口定義
public interface UserDao {
    User getUser(String id);
    List<User> getAllUser();
    void addUser(User user);
    boolean delUser(String id);
    boolean updateUser(User user);
}

// 實現類
public class UserDaoImpl implements UserDao {
    private SessionFactory sessionFactory;
    
    public void setSessionFactory(SessionFactory sessionFactory) { 
        this.sessionFactory = sessionFactory; 
    }
    
    @Override
    public User getUser(String id) {
        String hql = "from User u where u.id=?";
        Query query = sessionFactory.getCurrentSession().createQuery(hql);
        query.setString(0, id);
        return (User) query.uniqueResult();
    }
    
    @Override
    public List<User> getAllUser() {
        return sessionFactory.getCurrentSession().createQuery("from User").list();
    }
    
    @Override
    public void addUser(User user) {
        sessionFactory.getCurrentSession().save(user);
    }
    
    @Override
    public boolean delUser(String id) {
        String hql = "delete User u where u.id = ?";
        Query query = sessionFactory.getCurrentSession().createQuery(hql);
        query.setString(0, id);
        return query.executeUpdate() > 0;
    }
    
    @Override
    public boolean updateUser(User user) {
        String hql = "update User u set u.userName=?, u.age=? where u.id=?";
        Query query = sessionFactory.getCurrentSession().createQuery(hql);
        query.setString(0, user.getUserName());
        query.setString(1, user.getAge());
        query.setString(2, user.getId());
        return query.executeUpdate() > 0;
    }
}

依賴注入配置 (spring-beans.xml)

將各層組件裝配起來,並為 Service 層應用事務代理:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="https://www.springframework.org/schema/beans 
       https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- DAO 層 -->
    <bean id="userDao" class="com.tgb.dao.UserDaoImpl">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- Service 層基礎實現 -->
    <bean id="userManagerBase" class="com.tgb.manager.UserManagerImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

    <!-- 事務代理:為 Service 應用事務屬性 -->
    <bean name="userManager" parent="transactionProxy">
        <property name="target" ref="userManagerBase"/>
    </bean>
</beans>

項目運行與驗證

  1. 確保 MySQL 數據庫已創建 test_ssh 數據庫
  2. 將項目部署至 Tomcat 等 Servlet 容器
  3. 啟動服務器,訪問 https://localhost:8080/test_ssh/
  4. 系統將自動創建表結構(受 hbm2ddl.auto=update 控制)
  5. 通過界面進行用戶的增刪改查操作驗證功能

總結與最佳實踐建議

本示例展示了經典 SSH 框架的完整整合流程。實際項目中建議關注以下優化點:

  • 註解驅動替代 XML:使用 @Repository、@Service、@Transactional 等註解簡化配置
  • 連接池升級:生產環境建議使用 HikariCP 或 Druid 替代 DBCP
  • 異常統一處理:引入 @ControllerAdvice 實現全局異常捕獲
  • 分頁查詢優化:集成 PageHelper 或手寫分頁工具類
  • 緩存策略:引入 Redis/Ehcache 緩存熱點數據

隨著 Spring Boot 的普及,現代開發更傾向於「約定優於配置」的模式,但理解傳統 SSH 整合原理對於排查疑難雜症、閱讀老項目代碼仍具重要價值。

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