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

SSH (Struts2+Spring+Hibernate) 整合入門實戰:從註冊登錄到增刪改查完整案例

     編輯:Java 綜合教學

專案功能概覽

本案例實現會員管理核心業務:註冊、登錄驗證、信息查詢列表、修改、刪除。採用經典三層架構(Action → Service → DAO),Spring 管理所有 Bean 生命週期與依賴注入,Hibernate 4 通過 SessionFactory 進行 ORM 操作,Struts 2 處理 Web 請求分發。

一、Web 層配置:web.xml 核心解析

<web-app version="3.1" xmlns="https://xmlns.jcp.org/xml/ns/javaee">
    <display-name>ssh-demo</display-name>

    <!-- Struts2 核心過濾器 -->
    <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>

    <!-- Spring 根容器啟動監聽器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

關鍵點:ContextLoaderListener 啟動根容器加載 applicationContext.xml;Struts2 過濾器攔截所有請求,配合 struts.objectFactory=spring 將 Action 實例化交給 Spring。

二、持久層:實體類與 Hibernate 映射

Member.java (POJO)

package com.entity;
public class Member {
    private Long id;
    private String name, password, address, email;
    private Integer level;
    // 構造器、getter/setter 省略
}

Member.hbm.xml

<hibernate-mapping>
    <class name="com.entity.Member" table="MEMBER">
        <id name="id" type="long">
            <column name="ID"/>
            <generator class="identity"/> <!-- 自增主鍵 -->
        </id>
        <property name="name" column="NAME"/>
        <property name="password" column="PASSWORD"/>
        <property name="address" column="ADDRESS"/>
        <property name="email" column="EMAIL"/>
        <property name="level" column="LEVEL" type="int"/>
    </class>
</hibernate-mapping>

三、DAO 層:接口與實現

MemberDAO.java

public interface MemberDAO {
    void add(Member m); void update(Member m); void delete(Long id);
    Member findByName(String name, String pwd);
    Member findById(Long id);
    List<Member> findAll();
}

MemberDAOImpl.java (構造器注入 SessionFactory)

@Repository
public class MemberDAOImpl implements MemberDAO {
    private final SessionFactory sessionFactory;

    @Autowired
    public MemberDAOImpl(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; }

    private Session currentSession() { return sessionFactory.openSession(); }

    @Override public void add(Member m) {
        Session s = currentSession(); Transaction tx = s.beginTransaction();
        try { s.save(m); tx.commit(); } catch (Exception e) { tx.rollback(); throw e; } finally { s.close(); }
    }
    // update、delete、findById、findAll 同理,均使用 HQL 參數綁定防注入
    @Override public Member findByName(String name, String pwd) {
        Session s = currentSession(); Transaction tx = s.beginTransaction();
        try {
            String hql = "FROM Member m WHERE m.name=:n AND m.password=:p";
            Member m = (Member) s.createQuery(hql)
                .setParameter("n", name).setParameter("p", pwd).uniqueResult();
            tx.commit(); return m;
        } finally { s.close(); }
    }
}

四、Service 層:事務邊界與業務邏輯

MemberService.java

public interface MemberService {
    void add(Member m); void update(Member m); void delete(Long id);
    Member findByName(String name, String pwd);
    Member findById(Long id); List<Member> findAll();
}

MemberServiceImpl.java (Setter 注入 DAO)

@Service
public class MemberServiceImpl implements MemberService {
    private MemberDAO memberDao;

    @Autowired public void setMemberDao(MemberDAO memberDao) { this.memberDao = memberDao; }

    @Override @Transactional // 建議在 Service 層聲明式事務
    public void add(Member m) { if (memberDao.findById(m.getId()) == null) memberDao.add(m); }
    // update、delete 同理先判斷存在性
    @Override public Member findByName(String name, String pwd) { return memberDao.findByName(name, pwd); }
    // 其他委託方法省略
}

五、Action 層:Struts2 處理請求

所有 Action 繼承 ActionSupport,屬性驅動接收表單數據,Setter 注入 Service。

關鍵 Action 示例

  • MemberRegisterAction:execute() 調用 memberService.add(member),成功重定向到 memberQuery。
  • MemberLoginAction:驗證用戶名密碼,成功返回 SUCCESS 跳轉 welcome.jsp,失敗返回 ERROR 回 register.jsp。
  • MemberQueryAction:查詢所有會員放入 request 屬性 memberList,轉發 displayAll.jsp。
  • MemberUpdateAction:雙方法設計——showMember() 根據 ID 查詢回顯 update.jsp;execute() 執行更新後重定向列表。
  • MemberDeleteAction:接收 id 參數刪除後重定向列表。

六、Struts2 配置:struts.xml

<struts>
    <constant name="struts.devMode" value="true"/>
    <constant name="struts.objectFactory" value="spring"/> <!-- 關鍵:Action 由 Spring 管理 -->

    <package name="default" namespace="/" extends="struts-default">
        <action name="memberRegister" class="memberRegisterAction">
            <result name="success" type="redirectAction">memberQuery</result>
        </action>
        <action name="memberLogin" class="memberLoginAction">
            <result name="success">/welcome.jsp</result>
            <result name="error">/register.jsp</result>
        </action>
        <action name="memberQuery" class="memberQueryAction">
            <result name="success">/displayAll.jsp</result>
        </action>
        <action name="memberDelete" class="memberDeleteAction">
            <result name="success" type="redirectAction">memberQuery</result>
        </action>
        <action name="memberShow" class="memberUpdateAction" method="showMember">
            <result name="success">/update.jsp</result>
        </action>
        <action name="memberUpdate" class="memberUpdateAction">
            <result name="success" type="redirectAction">memberQuery</result>
        </action>
    </package>
</struts>

七、Spring 核心配置:applicationContext.xml

<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:context="https://www.springframework.org/schema/context"
       xsi:schemaLocation=".../spring-beans-4.3.xsd .../spring-context-4.3.xsd">

    <!-- C3P0 數據源 -->
    <bean id="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/zzh?useUnicode=true&amp;characterEncoding=UTF-8"/>
        <property name="user" value="root"/> <property name="password" value="root"/>
        <property name="maxPoolSize" value="40"/> <property name="minPoolSize" value="1"/>
    </bean>

    <!-- Hibernate 4 SessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mappingResources">
            <list><value>com/entity/Member.hbm.xml</value></list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
            </props>
        </property>
    </bean>

    <!-- Bean 定義與依賴注入 -->
    <bean id="memberDao" class="com.dao.MemberDAOImpl">
        <constructor-arg ref="sessionFactory"/>
    </bean>
    <bean id="memberService" class="com.service.MemberServiceImpl">
        <property name="memberDao" ref="memberDao"/>
    </bean>
    <bean id="memberRegisterAction" class="com.action.MemberRegisterAction">
        <property name="memberService" ref="memberService"/>
    </bean>
    <!-- 其他 Action Bean 省略,均注入 memberService -->
</beans>

八、視圖層:JSP 頁面片段

register.jsp (Struts2 標籤庫)

<s:form action="memberRegister" method="post">
    <s:textfield name="member.name" label="會員姓名" required="true"/>
    <s:password name="member.password" label="會員口令"/>
    <s:textfield name="member.address" label="會員地址"/>
    <s:textfield name="member.email" label="會員郵箱"/>
    <s:textfield name="member.level" label="會員級別"/>
    <s:submit value="提交"/>
</s:form>

displayAll.jsp (迭代顯示與操作鏈接)

<table border="1">
    <tr><th>ID</th><th>姓名</th><th>密碼</th><th>地址</th><th>郵箱</th><th>級別</th><th>操作</th></tr>
    <s:iterator value="#request.memberList" var="mb">
        <tr>
            <td><s:property value="#mb.id"/></td>
            <td><s:property value="#mb.name"/></td>
            <td><s:property value="#mb.password"/></td>
            <td><s:property value="#mb.address"/></td>
            <td><s:property value="#mb.email"/></td>
            <td><s:property value="#mb.level"/></td>
            <td>
                <a href="<s:url action="memberDelete"><s:param name="id" value="#mb.id"/></s:url>">刪除</a>
                <a href="<s:url action="memberShow"><s:param name="id" value="#mb.id"/></s:url>">修改</a>
            </td>
        </tr>
    </s:iterator>
</table>

九、運行驗證與常見問題

  1. 啟動 Tomcat,訪問 register.jsp 註冊會員。
  2. 查看 displayAll.jsp 列表,測試修改、刪除鏈接。
  3. 登錄頁測試正確/錯誤憑證跳轉。
  4. 報錯排查:若 NoClassDefFoundError 檢查 C3P0/Hibernate JAR;若事務不生效確認 @Transactional 与 tx:annotation-driven;若 Action 注入為空確認 struts.objectFactory=spring 及 Bean ID 一致。

總結

本案例展示了 SSH 整合的標準姿勢:Spring 管理全局 Bean 與事務、Hibernate 負責 ORM、Struts2 處理 Web 流控。關鍵在於 applicationContext.xml 中 sessionFactory 注入 DAO、Service 注入 DAO、Action 注入 Service 的依賴鏈,以及 struts.xml 中 class 屬性引用 Spring Bean ID 實現 Action 托管。掌握此模板,可快速構建傳統 Java Web 專案骨架。

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