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

Eclipse WTP 整合 Struts 2 與 Hibernate 3 實戰:從 Servlet/JSP 到 MVC 與 ORM 完整遷移

     編輯:Java 相關知識

專案背景

基於 Eclipse WTP、Tomcat 5、MySQL 4 建立的 DBTest Web 應用存在兩大問題:

  1. Servlet 硬編碼 JSP 頁面名稱。
  2. SQL 硬編碼於 Command 類別中。

引入 **Struts** 解決導航耦合,**Hibernate** 解決持久層耦合。

技術棧版本

  • J2SE 5.0、Eclipse 3.1、WTP 1.0
  • Tomcat 5.0、MySQL 4.0.25、MySQL Connector/J 3.1
  • Struts 1.1、Hibernate 3.x

領域模型

Customer (id, firstName, lastName, address) 1 —< * Order (id, custId, datePlaced, amount)

對應資料表 CUSTOMERS、ORDERS。

一、整合 Struts

1. 加入依賴 JAR (WEB-INF/lib)

struts.jar, commons-lang.jar, commons-collections.jar, commons-beanutils.jar,
commons-validator.jar, commons-logging.jar, commons-digester.jar, commons-fileupload.jar

2. 加入 TLD 標籤庫 (WEB-INF)

struts-config.xml, struts-bean.tld, struts-html.tld, struts-logic.tld,
struts-nested.tld, struts-template.tld, struts-tiles.tld

3. 設定 web.xml 啟用 ActionServlet

<servlet>
  <servlet-name>action</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
  <init-param>
    <param-name>config</param-name>
    <param-value>/WEB-INF/struts-config.xml</param-value>
  </init-param>
  <init-param><param-name>debug</param-name><param-value>2</param-value></init-param>
  <init-param><param-name>detail</param-name><param-value>2</param-value></init-param>
  <init-param><param-name>validate</param-name><param-value>true</param-value></init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>action</servlet-name>
  <url-pattern>*.do</url-pattern>
</servlet-mapping>

4. 抽象 Action 基類隔離錯誤處理

public abstract class AbstractAction extends Action {
    public ActionForward execute(ActionMapping m, ActionForm f,
            HttpServletRequest req, HttpServletResponse res) throws Exception {
        ActionErrors errors = new ActionErrors();
        ActionForward forward = new ActionForward();
        try {
            forward = performAction(m, f, req, res);
        } catch (Exception e) {
            errors.add("name", new ActionError("id"));
        }
        if (!errors.isEmpty()) {
            saveErrors(req, errors);
            return mapping.findForward("failure");
        }
        return forward != null ? forward : mapping.findForward("success");
    }
    protected abstract ActionForward performAction(ActionMapping m, ActionForm f,
            HttpServletRequest req, HttpServletResponse res) throws Exception;
}

5. 具體 Action 實作 (以 CreateCustomer 為例)

public class CreateCustomerAction extends AbstractAction {
    protected ActionForward performAction(ActionMapping m, ActionForm f,
            HttpServletRequest req, HttpServletResponse res) {
        String first = req.getParameter("first_name");
        String last = req.getParameter("last_name");
        String addr = req.getParameter("address");
        int id = Math.abs((int) System.currentTimeMillis());

        Customer c = new Customer();
        c.setId(id); c.setFirstName(first); c.setLastName(last); c.setAddress(addr);

        DatabaseCommand cmd = new CreateCustomer(c);
        CommandExecutor.getInstance().executeDatabaseCommand(cmd);

        return mapping.findForward("customer_created");
    }
}

6. struts-config.xml 動作映射

<action path="/CreateCustomer" type="actions.CreateCustomerAction">
  <forward name="customer_created" path="/customer_created.jsp"/>
  <forward name="failure" path="/failure.jsp"/>
</action>

JSP 名稱不再硬編碼於 Java 程式碼,改由設定檔解析。

二、整合 Hibernate

1. 加入 JAR (WEB-INF/lib)

hibernate3.jar, dom4j.jar

2. hibernate.cfg.xml (放在 Java Source 根目錄,部署至 WEB-INF/classes)

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
  "-//Hibernate/Hibernate Configuration DTD//EN"
  "https://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.connection.datasource">java:comp/env/jdbc/TestDB</property>
    <property name="show_sql">true</property>
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <mapping resource="hibernate.mapping.xml"/>
  </session-factory>
</hibernate-configuration>

3. hibernate.mapping.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD//EN"
  "https://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="domain.Customer" table="CUSTOMER" lazy="false">
    <id name="id" column="ID"/>
    <property name="firstName" column="FIRST_NAME"/>
    <property name="lastName" column="LAST_NAME"/>
    <property name="address" column="ADDRESS"/>
  </class>
  <class name="domain.Order" table="ORDERS" lazy="false">
    <id name="id" column="ID"/>
    <property name="custId" column="CUST_ID"/>
    <property name="datePlaced" column="DATE_PLACED"/>
    <property name="orderAmount" column="AMOUNT"/>
  </class>
</hibernate-mapping>

lazy="false" 避免 Session 關閉後存取延遲屬性拋出異常(本範例資料量小、無後續操作)。

4. CommandExecutor 改用 Hibernate Session

private SessionFactory sessionFactory = null;

public SessionFactory getSessionFactory() {
    if (sessionFactory == null) {
        sessionFactory = new Configuration().configure().buildSessionFactory();
    }
    return sessionFactory;
}

public Object executeHibernateCommand(DatabaseCommand cmd) throws Exception {
    Session session = null;
    try {
        session = getSessionFactory().openSession();
        return cmd.executeHibernateOperation(session);
    } catch (SQLException e) { throw e; }
    finally {
        if (session != null) { session.flush(); session.close(); }
    }
}

5. DatabaseCommand 介面新增方法

public Object executeHibernateOperation(Session session) throws SQLException;

6. 四個 Command 類別實作 executeHibernateOperation

// CreateCustomer
public Object executeHibernateOperation(Session session) {
    session.save(cust); session.flush(); return 1;
}

// CreateOrder (類似)

// ListCustomers
public Object executeHibernateOperation(Session session) {
    Query q = session.createQuery("from Customer");
    Iterator it = q.iterate();
    List list = new ArrayList();
    while (it.hasNext()) list.add(it.next());
    return list;
}

// ListCustomerOrders
public Object executeHibernateOperation(Session session) {
    Query q = session.createQuery("from Order where custId = '" + this.cust_id + "'");
    Iterator it = q.iterate();
    List list = new ArrayList();
    while (it.hasNext()) list.add(it.next());
    return list;
}

HQL 查詢物件而非資料表,無硬編碼 SQL、欄位名,切換資料庫只需改 dialect 與 datasource。

7. 更新 Struts Action 呼叫 executeHibernateCommand

將 CommandExecutor.getInstance().executeDatabaseCommand(cmd) 改為 executeHibernateCommand(cmd)。

三、部署與驗證

  1. Eclipse WTP:File → Export → WAR file 產出 DBTestStruts.war。
  2. Tomcat Manager 部署 WAR。
  3. 瀏覽器驗證各功能:建立客戶、下單、查詢訂單、列出客戶。

結語

Struts 分離 Model/View/Controller,Hibernate 消除硬編碼 SQL 與 JDBC 樣板碼,兩者結合大幅提升專案可維護性、程式碼重用性與可讀性。

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