程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 利用Stripes、Apache Derby和Eclipse進行無配置的J2EE開發(二)

利用Stripes、Apache Derby和Eclipse進行無配置的J2EE開發(二)

編輯:關於JAVA

Stripes 注釋和單元測試

發現 Stripes 注釋的套件,並在您的應用程序上構造單元測試。

Stripes 注釋

Stripes 帶有以下注釋:

分派注釋:

@UrlBinding:該注釋允許 ActionBean 類生成定制 UrlBinding URL 路徑。在帶注釋 的 UrlBinding 路徑被請求時,會調用 ActionBean 類。

@HandlesEvent:該綁定允許通過指定的名稱調用 actionBean() 方法。默認情況下, Stripes 試圖將事件名解析成 actionBean() 方法中的方法名,除非它找到該注釋。

@DefaultHandler:該注釋允許在到 ActionBean 的請求中未提供事件名時執行一個方 法。默認情況下,如果只有一個處理程序方法存在於 ActionBean 中,那麼該名稱自然就 成為默認的名稱。

@SessionScope:使用該注釋,您可以在初始化時將 ActionBean 放置在用戶會話中, 從此之後在會話的生命期重用它。

@Wizard:該注釋允許 ActionBean 被看作向導表單的一部分(一個邏輯表單分成多個 物理頁面)。向導接收特殊的狀態管理和驗證處理。

驗證注釋:

@DontValidate:該注釋允許 ActionBean 事件跳過驗證。

@Validate:利用該注釋,可以在 ActionBean 中為單個字段配置定制的驗證規則。 Validate 注釋允許特殊的參數定義驗證業務規則。可以利用預配置的驗證器,利用一個 表達式或組合(例如 @Validate(required="true",minlength="1", maxlength="200")) 創建定制驗證器。

@ValidateNestedProperties:該注釋允許為對象驗證使用嵌套的 validate() 方法。

@ValidationMethod:利用該注釋,您可以在任何事件處理程序被調用之前執行一個特 殊的驗證方法。

其他注釋:

@Before

@After

@SpringBean

@Test

利用 TestNG 進行單元測試

TestNG 沒有以任何方式與 Stripes 耦合在一起。但是它在利用 JDK 1.5 注釋方面共 享一個公共的結合點,並且與其他測試框架相比,它需要更少的配置和維護。TestNG 是 選擇用於 Stripes 開發的單元測試套件。下面是一些要點:

您只需要一個 XML 配置文件,其中包含關於測試套件運行元數據的信息。

一個測試套件可以包含多個測試,而一個測試又包含多個類。

您可以運行測試組,以及將這些測試組合到更大的組中,以便為何時測試哪些組提供 靈活性。

您可以通過一個似於 Ant 任務的腳本啟動測試套件運行。

利用一個開放的應用程序接口 (API),TestNG 通過控制台、HTML 和定制選項提供報 告。

如果需要的話,插件和 JUnit 報告是可用的。

開發 Glossary 1.0 Web 應用程序

本節指導您開發 Glossary 1.0 Web 應用程序。

Glossary 1.0 應用程序設計

Glossary 1.0 Web 應用程序包括以下三層:

持久層或模型(Model)

表示層 (UI) 或視圖(View)

業務邏輯層或控制器(Controller)

圖 17 展示了該設計。

圖 17. Glossary 1.0 應用程序設計

默認情況下,應用程序流依次執行以下任務:

應用程序根 index.jsp 初始化一個對 ActionBean /glossary/action/Glossary.action 的調用。

ActionBean 沒有特定的事件調用,就會調用默認的處理程序。

默認的處理程序對數據訪問層對象進行一次調用,並請求術語表(glossary)中的所 有術語。

術語被發送回 ActionBean,ActionBean 然後把術語轉發給用戶。

使用 FowardResolution() 方法,/glossary/index.jsp 文件是默認處理程序請求的 頁面。

用戶現在看到了 /glossary/index.jsp 頁面上的術語列表。

從這裡,用戶可以添加、編輯或刪除術語。

創建 Java 類

Glossary 1.0 應用程序允許用戶管理術語列表和定義。用戶可以執行以下操作:

查看所有術語。

添加新術語。

編輯現有術語。

刪除術語。

下面三個 Java 類使得這些操作成為可能:

glossary.Term.java(如 清單 3 所示)

glossary.action.GlossaryActionBean.java(如 清單 4 所示)

glossary.dao.MyGlossaryTerm.java(如 清單 5 所示)

下面幾節給出了 Glossary 1.0 應用程序的完整 Java 源代碼清單以及詳細的描述。

Glossary.Term.java

Term 類是一個 Java 對象,表示 Glossary 1.0 應用程序中的一個術語。Term 類實 現 Comparable 元素,它的自然種類已設置在 term 字段中。Term 類包括三個字段:

id:一個惟一的標識符

term:術語標題

definition:術語定義

應用程序創建新的 Term 類對象,用戶可以對這些對象執行不同的操作。這裡沒有什 麼特殊的事情,Term 類只是一個普通舊式 Java 對象 (POJO),如 清單 3 所示。

清單 3. Glossary.Term.java

<![CDATA[
package glossary;

import java.util.List;

/**
  * Represents a term in the glossary database.
  *
  * @author BJ Allmon
  */

public class Term implements Comparable {

  private Integer id;

  private String term;

  private String definition;

  private List<Term> glossary;

  public Integer getId() {
   return id;
  }

  public void setId(Integer id) {
   this.id = id;
  }

  public String getTerm() {
   return term;
  }

  public void setTerm(String term) {
   this.term = term;
  }

  public String getDefinition() {
   return definition;
  }

  public void setDefinition(String definition) {
   this.definition = definition;
  }

  public List getGlossary() {
   return glossary;
  }

  public void setGlossary(List<Term> glossary) {
   this.glossary = glossary;
  }

  public int compareTo(Object o) {
   Term that = (Term) o;
    return this.term.compareTo(that.term);
  }
}
]]>

Glossary.action.GlossaryActionBean.java

GlossaryActionBean 類是一個 Stripes ActionBean。為了成為一個有效的 Stripes ActionBean,GlossaryActionBean 實現了 net.sourceforge.stripes.action.ActionBean。Stripe 的 ActionBean 類可以為術語列 表之類的元素或者其他資源包含 getter 和 setter。

List results 獲得和設置術語列表。

String resultSize 獲得術語表數據庫中術語的個數。

Term term 獲得和設置 Term 對象。

通過使用 Stripes ActionBeanContext,這些資源可以容易地被設置在請求或會話上 ,以備視圖頁面使用。

Stripes 在運行時自動發現 ActionBean 類的所有實現。Stripes 收集器使用 NameBasedActionResolver 類來創建默認的 URL 綁定。Stripes 也為創建定制配置提供 一個框架。默認的操作解析器通過以下方法生成 URL 綁定,即拆開包名稱,從名稱的末 尾刪除 action 和 bean,用斜槓取代句點,並附加後綴 .action(默認的後綴)。例如 :

之前: /glossary/action/GlossaryActionBean

之後: /glossary/action/Glossary.action

當一個表單被提交後,Stripes 就會利用請求 URL 和 ActionBean 上的 UrlBinding 注釋來計算出正確的 ActionBean,用於管理請求。然後 Stripes 利用諸如 @DefaultHandler 或 @HandlesEvent("myEvent") 之類的注釋,來確定在 ActionBean 上 調用一次哪個事件。如果沒有事件傳遞給 ActionBean 進行處理,則會調用 @DefaultHandler() 方法,如 清單 4 所示。

清單 4. @DefaultHandler() 方法被調用

<![CDATA[
@UrlBinding("/glossary/action")
public class GlossaryActionBean implements ActionBean {
...
]]>

子類化 ActionBeanContext

Stripes 文檔建議子類化 ActionBeanContext,以便為應用程序提供上下文狀態的方 面(facade)。

ActionBean 類必須提供一個 ActionBeanContext。ActionBeanContext 提供對 Servlet API 的訪問,並且包含關於當前請求的信息。具有對 Servlet API 的訪問使得 您可以調用諸如 getRequest() 和 setRequest(HttpServletRequest request) 之類的方 法,如 清單 5 所示。

清單 5. Servlet API 允許您調用方法

<![CDATA[
public ActionBeanContext getContext() {
  return context;
}

public void setContext(ActionBeanContext actionBeanContext) {
  this.context = actionBeanContext;
}
]]>

事件映射到處理程序方法。Stripes 首先確定 ActionBean,然後確定處理程序。可以 將 HTML 標記(比如 <image> 和 <button>)的名稱屬性與事件處理程序相 關聯。在 GlossaryActionBean 中,save() 方法類似於 清單 6。

清單 6. GlossaryActionBean 中的 save() 方法

<![CDATA[
@HandlesEvent("save") public Resolution save() {
  ...
  return new RedirectResolution ("/glossary/action/Glossary.action").flash(this);
}
]]>

當您編輯一個術語表術語時,單擊 Save 按鈕提交表單和調用 save() 方法。該按鈕 類似於:

<![CDATA[<stripes:submit name="save" class="btn" value="Save" />]]>

注意 Save 按鈕的 name 值與 GossaryActionBean 類中的 <![CDATA [@HandlesEvent("save")]]> 注釋相關。

Stripes 為處理服務器端轉發或客戶端重定向分別提供了 ForwardResolution 和 RedirectResolution 類。ForwardResolution 類允許只轉發到相同 Web 應用程序中的另 一個路徑。可以用以下三種方式之一構造 ForwardResolution 類:

<![CDATA[ForwardResolution(Class<? extends ActionBean> beanType)]]> 提供一個 ActionBean 來轉發到所需的 URL。

<![CDATA[ForwardResolution(Class<? extends ActionBean> beanType, String event)]]> 提供一個 ActionBean 來轉發到所需的 URL 並調用一個事件。

<![CDATA[ForwardResolution(String path)]]> 提供一個簡單的 URL 路徑用 於轉發到。

RedirectResolution 可以在 Web 上下文之中或者之外進行轉發,您可以用以下四種 方式之一構造它:

<![CDATA[RedirectResolution(Class<? extends ActionBean> beanType)]]> 提供一個 ActionBean 來轉發到所需的 URL。

<![CDATA[RedirectResolution(Class<? extends ActionBean> beanType, String event)]]> 提供一個 ActionBean 來轉發到所需的 URL 並調用一個事件。

<![CDATA[RedirectResolution(String url)]]> 提供一個簡單的 URL 路徑用 於轉發到。

<![CDATA[RedirectResolution(String url, boolean prependContext)]]> 提 供一個簡單的 URL 路徑用於轉發到。它也提供一個 Boolean 值來指定上下文是否應該被 添加到請求。如果是對外部 URL 進行調用的話,該值應該設置為 false。

清單 7 展示了 glossary.action.GlossaryActionBean.java。

清單 7. Glossary.action.GlossaryActionBean.java

<![CDATA[
package glossary.action;

import glossary.Term;
import glossary.dao.MyGlossaryTerm;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.HandlesEvent;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

//http://localhost:8080/article/glossary/action/Glossary.action
@UrlBinding("/glossary/action")
public class GlossaryActionBean implements ActionBean {
   private static final Log log = LogFactory.getLog (GlossaryActionBean.class);

   private List results = new ArrayList();

   private Term term;

   private MyGlossaryTerm gmt;

   private ActionBeanContext context;

   public ActionBeanContext getContext() {
     return context;
   }

   public void setContext(ActionBeanContext actionBeanContext) {
     this.context = actionBeanContext;
   }

   @DefaultHandler
   public Resolution load() {
     log.info("loading");
     results.clear();
     results = MyGlossaryTerm.getInstance().findAllWords();
     //resultSize = getResultSize();
     // just here for debugging purposes
     if (results == null) {
       results = new ArrayList();
       results.add("ERROR LOADING GLOSSARY.");
     }

     return new ForwardResolution("/glossary/index.jsp");
   }

   @HandlesEvent("editForm")
   public Resolution editForm() {

     setTerm(gmt.getSingleTerm(this.term.getId()));

     return new RedirectResolution("/glossary/termEdit.jsp").flash (this);
   }

   @HandlesEvent("save")
   public Resolution save() {

     Term updatedTerm = new Term();

     updatedTerm.setId(this.term.getId());
     updatedTerm.setDefinition(this.term.getDefinition());

     gmt.updateTerm(updatedTerm);

     return new RedirectResolution ("/glossary/action/Glossary.action")
       .flash(this);
   }

   @HandlesEvent("delete")
   public Resolution delete() {

     gmt.deleteTerm(this.term.getId());

     return new RedirectResolution ("/glossary/action/Glossary.action")
       .flash(this);
   }

   @HandlesEvent("addForm")
   public Resolution addForm() {
     return new RedirectResolution("/glossary/termAdd.jsp").flash (this);
   }

   @HandlesEvent("add")
   public Resolution add() {

     Term newTerm = new Term();

     newTerm.setTerm(this.term.getTerm());
     newTerm.setDefinition(this.term.getDefinition());

     gmt.addTerm(newTerm);

     return new RedirectResolution ("/glossary/action/Glossary.action")
       .flash(this);
   }

   public List getResults() {
     return results;
   }

   public void setResults(List results) {
     this.results = results;
   }

   public String getResultSize() {

     String resultSize = "";
     resultSize = gmt.resultSetSize();
     return resultSize;
   }

   public Term getTerm() {
     return term;
   }

   public void setTerm(Term term) {
     this.term = term;
   }
}
  ]]>

Glossary.dao.MyGlossaryTerm.java

數據訪問

在輕量級容器(比如 Spring)中存儲數據訪問連接屬性是一個好的實踐。

glossary.dao.MyGlossaryTerm.java 類(如 清單 8 所示)是一個數據訪問類,其中 包含對數據庫的 JDBC 調用。它也包含所有的方法,以在數據庫上執行 CRUD 操作。 MyGlossaryTerm 類包含以下方法:

getConnection() 方法使用 URL org.apache.derby.jdbc.ClientDriver。數據庫 URL 幾乎就是嵌入式版本,只是數據庫名稱之前的服務器名稱和端口號不同。數據庫 URL 是 jdbc:derby://localhost:1527/glossary。

resultSetSize() 方法針對術語表數據庫中術語的當前總數返回一個字符串。我創建 該方法首先是因為我想要從簡單開始。我使用該方法來在視圖頁面標題欄顯示一個記錄計 數,形式為 There are x entries,其中 x 是記錄數。

getSingleTerm(int id) 方法通過使用提供的術語 ID 從術語表返回一個術語。 ActionBean editForm() 方法使用該 ID 來檢索適當的術語進行編輯。

findAllWords() 方法從術語表返回術語列表。Stripes 的默認處理程序 @DefaultHandler 使用該方法來用術語列表設置請求。

updateTerm(Term term) 方法返回 void。該方法在提供的術語上執行 SQL UPDATE 操 作,並由 ActionBean save 處理程序調用。

deleteTerm(int id) 方法返回 void。該方法針對提供的術語 ID 執行 SQL DELETE 操作,並由 ActionBean delete 處理程序調用。

addTerm(Term term) 方法返回 void。該方法針對提供的術語數據執行 SQL INSERT 操作,並由 ActionBean add 處理程序調用。

清單 8. Glossary.dao.MyGlossaryTerm.java

<![CDATA[
package glossary.dao;

import glossary.Term;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
  * @author BJ Allmon
  */

public class MyGlossaryTerm {

   private static final Log log = LogFactory.getLog (MyGlossaryTerm.class);

   private static final String driver =  "org.apache.derby.jdbc.ClientDriver";

   private static final String database =  "jdbc:derby://localhost:1527/glossary;";

   private static MyGlossaryTerm instance;

   public static MyGlossaryTerm getInstance() {
     if (instance == null) {
       instance = new MyGlossaryTerm();
     }

     return instance;
   }

   private Connection getConnection() {
     Connection connection = null;
     try {
       Class.forName(driver).newInstance();

       Properties props = new Properties();
       props.put("user", "sa");
       props.put("password", "sa");

       connection = DriverManager.getConnection(database,  props);
     } catch (Exception ex) {
       log.error("Error connecting to database: " + database,  ex);
       throw new RuntimeException("Database " + database
         + " is not available.", ex);
     }

     return connection;
   }

   public String resultSetSize() {
     String resultSize = "";

     Connection conn = getConnection();
     Statement s = null;
     ResultSet rs = null;
     try {
       conn = getConnection();
       s = conn.createStatement();
       rs = s
       .executeQuery("SELECT COUNT(TERM_ID) AS TOTAL FROM  APP.GLOSSARY");

       while (rs.next()) {
         resultSize = rs.getString("TOTAL");
       }
     } catch (Exception ex) {
       log.error("Really bad database error.", ex);
     } finally {
       try {
         rs.close();
         s.close();
         conn.commit();
         conn.close();
       } catch (SQLException e) {
         log.error("More really bad database errors.", e);
       }
     }
     return resultSize;
   }

   public Term getSingleTerm(int id) {
     Term term = new Term();

     Connection conn = getConnection();
     Statement s = null;
     ResultSet rs = null;

     try {
       conn = getConnection();
       s = conn.createStatement();
       rs = s.executeQuery("SELECT * FROM APP.GLOSSARY WHERE  TERM_ID = "
         + id);

       while (rs.next()) {
         term.setId(rs.getInt("TERM_ID"));
         term.setTerm(rs.getString("TERM"));
         term.setDefinition(rs.getString("DEFINITION"));
       }
     } catch (Exception ex) {
       log.error("Really bad database error.", ex);
     } finally {
       try {
         rs.close();
         s.close();
         conn.commit();
         conn.close();
       } catch (SQLException e) {
         log.error("More really bad database errors.", e);
       }
     }
     return term;
   }

   public List findAllWords() {
     List glossaryList = new ArrayList();

     Connection conn = getConnection();
     Statement s = null;
     ResultSet rs = null;
     try {
       conn = getConnection();
       s = conn.createStatement();
       rs = s.executeQuery("SELECT * FROM APP.GLOSSARY ORDER BY  TERM");

       log.debug("Results of select * from app.glossary  query:");
       while (rs.next()) {

         log.debug(" " + rs.getString("TERM_ID") + " "
           + rs.getString("TERM") + " "
             + rs.getString("DEFINITION"));
         Term term = new Term();
         term.setTerm(rs.getString("TERM"));
         term.setDefinition(rs.getString("DEFINITION"));
         term.setId(rs.getInt("TERM_ID"));
         glossaryList.add(term);
       }
     } catch (Exception ex) {
       log.error("Really bad database error.", ex);
     } finally {
       try {
         rs.close();
         s.close();
         conn.commit();
         conn.close();
       } catch (SQLException e) {
         log.error("More really bad database errors.", e);
       }
     }
     return glossaryList;
   }

   public void updateTerm(Term term) {
     Term updatedTerm = new Term();
     updatedTerm = term;
     int termId = updatedTerm.getId();
     String definition = updatedTerm.getDefinition();

     Connection conn = getConnection();
     Statement s = null;

     try {
       conn = getConnection();
       s = conn.createStatement();
       s.executeUpdate("UPDATE APP.GLOSSARY SET DEFINITION =  '"
         + definition + "' WHERE TERM_ID = " + termId);
     } catch (Exception ex) {
       log.error("Really bad database error.", ex);
     } finally {
       try {
         s.close();
         conn.commit();
         conn.close();
       } catch (SQLException e) {
         log.error("More really bad database errors.", e);
       }
     }
   }

   public void deleteTerm(int id) {

     Connection conn = getConnection();
     Statement s = null;

     try {
       conn = getConnection();
       s = conn.createStatement();
       s.executeUpdate("DELETE FROM APP.GLOSSARY WHERE TERM_ID =  " + id);
     } catch (Exception ex) {
       log.error("Really bad database error.", ex);
     } finally {
       try {
         s.close();
         conn.commit();
         conn.close();
       } catch (SQLException e) {
         log.error("More really bad database errors.", e);
       }
     }
   }

   public void addTerm(Term term) {
     Term newTerm = new Term();
     newTerm = term;

     String definition = newTerm.getDefinition().trim();
     String title = newTerm.getTerm().trim();

     Connection conn = getConnection();
     Statement s = null;

     try {
       conn = getConnection();
       s = conn.createStatement();
       s.executeUpdate("INSERT INTO APP.GLOSSARY VALUES  (DEFAULT,'"
         + title + "','" + definition + "')");
     } catch (Exception ex) {
       log.error("Really bad database error.", ex);
     } finally {
       try {
         s.close();
         conn.commit();
         conn.close();
       } catch (SQLException e) {
         log.error("More really bad database errors.", e);
       }
     }
   }
}
  ]]>

創建 Web UI

Glossary 1.0 應用程序中使用了四個 .jsp 文件,即 index.jsp、/glossary/index.jsp、/glossary/termAdd.jsp 和 /glossary/termEdit.jsp。

Index.jsp

Index.jsp 是 Web 應用程序根索引頁面。該文件簡單地捕捉初始的請求並將其轉發給 Glossary ActionBean。如果沒有事件被傳遞給 ActionBean,注釋 @DefaultHandler 將 執行默認的行為,如 清單 9 所示。這裡重要的是調用了一個到 /glossary/action/Glossary.action 的轉發,這會初始化對 Stripes ActionBean 的調 用。圖 18 展示了 Glossary 1.0 索引頁面。

圖 18. Glossary 1.0 索引頁面

清單 9. Index.jsp

<![CDATA[
<%@ page language="java" contentType="text/html; charset=ISO-8859- 1"
   pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01  Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859- 1">
<title>Glossary 1.0 - Loading...</title>
</head>
<body>
   <jsp:forward page="/glossary/action/Glossary.action" />
</body>
</html>
]]>

/glossary/index.jsp

/glossary/index.jsp(或 /glossary/action/Glossary.action)文件(如 清單 10 所示)是應用程序入口點。第一個需要注意的事情是包含 Stripes 標記庫。在該頁面上 只使用了很少的 Stripes 標記:

<![CDATA[<stripes:form/>]]>:該 Stripes HTML <form> 標記 允許 Stripe <input> 標記(如 <![CDATA[<stripes:text/>]]>)重 新填充它們的值。在開發期間,我注意到 <form> 標記為所有包含表單的頁面的頁 面名稱動態包含一個隱藏的 form 字段。這個隱藏的字段通過在出現驗證邏輯錯誤時轉發 回相同頁面而幫助驗證。

<![CDATA[<stripes:link/>]]>:這是 Stripes 應用程序中用於鏈接到 頁面和 ActionBean 事件的 Stripes HTML <link> 標記。使用 Stripes <link> 標記,您可以指定一個 ActionBean 類作為 URL,還可以指定 ActionBean 事件。可以將 Add、edit 和 Delete 鏈接與 GlossaryActionBean 類中的方法相關聯。 事件屬性映射到 ActionBean handler() 方法。

<![CDATA[<stripes:link-param/>]]>:您使用該標記來傳遞請求參數( 比如術語 ID)給 ActionBean。

清單 10. /glossary/index.jsp

<![CDATA[
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<%@ page contentType="text/html;charset=UTF-8" language="java"% >

<%@ taglib prefix="stripes"
  uri="http://stripes.sourceforge.net/stripes.tld"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"% >

<html>
<head>
<link rel="stylesheet" type="text/css"
   href="${pageContext.request.contextPath}/style/glossary.css" />
<script  src="${pageContext.request.contextPath}/scripts/glossary.js"></script> ;
<title>Glossary 1.0</title>
</head>
<body>
<div class="contentBorder">
  <a href="${pageContext.request.contextPath}">
   <img border="0"  src="${pageContext.request.contextPath}/images/glossary.gif"
     class="logo" />
  </a>

<div class="contentBody">

<div class="title">
   There are <c:out value="${actionBean.resultSize}" />  entries
</div>
<stripes:form action="/glossary/action/Glossary.action">
  <table cellpadding="0" cellspacing="0" border="0" width="100%"  class="dataTbl">
   <tr>
   <th>Word</th>
    <th>Definition</th>
    <th>
     <stripes:link href="/glossary/action/Glossary.action"  event="addForm">
      Add
     </stripes:link>
    </th>
   </tr>
   <tr>
    <td colspan="2"></td>
   </tr>
   <c:forEach items="${actionBean.results}" var="row">
   <tr>
    <td style="padding-right:4px;"><c:out  value="${row.term}" /></td>
    <td><c:out value="${row.definition}" /></td>
    <td style="padding-left:4px;" nowrap>
     <stripes:link href="/glossary/action/Glossary.action"  event="editForm">
      Edit
      <stripes:link-param name="termId" value="${row.id}" />
     </stripes:link>|
     <stripes:link href="/glossary/action/Glossary.action"  event="delete">
       Delete
       <stripes:link-param name="termId" value="${row.id}" />
     </stripes:link>
    </td>
   </tr>
   </c:forEach>
  </table>
</stripes:form> <br />
<br />
</div>
<div class="footer">
<hr style="height: 1px;" />
Glossary 1.0 is brought to you by <a target="_blank"
   href="http://ibm.com/developerworks">IBM  DeveloperWorks</a></div>
</div>
</body>
</html>
]]>

/glossary/termAdd.jsp

/glossary/termAdd.jsp 文件(如 清單 11 所示)包含一個表單,該表單調用適當的 ActionBean 處理程序,以向數據庫添加新的術語。該表單非常基本。還沒有介紹過的用 於該任務的標記有:

<![CDATA[<stripes:text/>]]>:這是 Stripes HTML 輸入文本框。

<![CDATA[<stripes:textarea/>]]>:這是 Stripes HTML 輸入文本區域 。

<![CDATA[<stripes:submit/>]]>:這是 Stripes 表單 Submit 按鈕。 同樣,使用按鈕的名稱來調用 ActionBean 中的事件。在本例中,事件是 add。

清單 11. /glossary/termAdd.jsp

<![CDATA[
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<%@ page contentType="text/html;charset=UTF-8" language="java"% >

<%@ taglib prefix="stripes"
   uri="http://stripes.sourceforge.net/stripes.tld"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"% >

<html>
<head>
<link rel="stylesheet" type="text/css"
   href="${pageContext.request.contextPath}/style/glossary.css" />
<script  src="${pageContext.request.contextPath}/scripts/glossary.js"></script> ;
<title>Glossary 1.0</title>
</head>
<body>
<div class="contentBorder">
   <a href="${pageContext.request.contextPath}">
     <img border="0"  src="${pageContext.request.contextPath}/images/glossary.gif"
     class="logo" />
   </a>
   <stripes:form action="/glossary/action/Glossary.action"  method="POST">
   <div class="contentBody">

   <div class="title">New Term</div>
   <br />
   <br />
   <b>Term: </b><br />
   <stripes:text name="term" maxlength="80" /><br />
   <b>Definition: </b><br />
   <stripes:textarea name="definition" rows="10"  cols="75"></stripes:textarea>
   <stripes:submit name="add" class="btn"  value="Add" /></div>
</stripes:form>
<div class="footer">
<hr style="height: 1px;" />
Glossary 1.0 is brought to you by <a target="_blank"
   href="http://ibm.com/developerworks">IBM  DeveloperWorks</a></div>
</div>
</body>
</html>
]]>

圖 19 展示了 Glossary 1.0 Add Term 表單。

圖 19. Glossary 1.0 Add Term 表單

/glossary/termEdit.jsp

/glossary/termEdit.jsp 文件(如 清單 12 所示)與 termAdd.jsp 幾乎相同,只有 兩點除外。首先,預填充的表單值利用 JSTL。其次,Submit 按鈕名觸發 save 而不是 add 事件處理程序。

清單 12. /glossary/termEdit.jsp

<![CDATA[
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<%@ page contentType="text/html;charset=UTF-8" language="java"% >

<%@ taglib prefix="stripes"
   uri="http://stripes.sourceforge.net/stripes.tld"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"% >

<html>
<head>
<link rel="stylesheet" type="text/css"
   href="${pageContext.request.contextPath}/style/glossary.css" />
<script  src="${pageContext.request.contextPath}/scripts/glossary.js"></script> ;
<title>Glossary 1.0</title>
</head>
<body>
<div class="contentBorder">
<a href="${pageContext.request.contextPath}">
   <img border="0"  src="${pageContext.request.contextPath}/images/glossary.gif"
     class="logo" />
</a>
<c:if test='${actionBean.term.term == null}'>
   <jsp:forward page="/glossary/action/Glossary.action" />
</c:if>

<stripes:form action="/glossary/action/Glossary.action"  method="POST">
   <stripes:hidden name="termId" value="${actionBean.term.id}" />
   <div class="contentBody">

     <div class="title">Term:
     <span id="term"><c:out  value="${actionBean.term.term}" /></span></div>
     <br />
     <br />
     <b>Definition: </b><br />
     <stripes:textarea name="definition" rows="10" cols="75"
       value="${actionBean.term.definition}" />
       <stripes:submit name="save" class="btn" value="Save" />
   </div>
</stripes:form>
<div class="footer">
<hr style="height: 1px;" />
Glossary 1.0 is brought to you by <a target="_blank"
   href="http://ibm.com/developerworks">IBM  DeveloperWorks</a></div>
</div>
</body>
</html>
]]>

圖 20 展示了 Glossary 1.0 Edit Term 表單。

圖 20. Glossary 1.0 Edit Term 表單

其他應用程序資源

其他本教程中沒有介紹的資源包括在應用程序下載文件中。諸如 Cascading Style Sheets (CSS)、JavaScript 代碼和圖像之類的資源對於應用程序的整體觀感很重要。但 是,它們不是這裡討論的焦點。

結束語

由於 Java 5 中重要的新特性,且需要不太突出的(less-obtrusive)Web 框架, Stripes 保證會被很多人接受作為一種穩定的 Web 框架。類似地,Apache Derby 是一個 需要了解的偉大數據庫,對於如此小的內存占用來說具有大量重要的特性。Eclipse 只是 變得越來越好。

在本教程中,您發現了設置和開始開發重要的應用程序特性是多麼簡單,而不需要將 很多的時間花在配置上。Eclipse 與 Tomcat 的集成允許從動態 Web 項目直接部署。您 看到了整個教程中演示了其他 Eclipse 特性,包括 Database Explorer。通過將 Derby 添加到工具包中,您將能夠持久存儲和管理數據,根本就不需要什麼配置。

文章來源:

http://www.ibm.com/developerworks/cn/edu/os-dw-os-ad-configureless.html

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved