Java Web 應用程式的構建的多種選擇

來源:互聯網
上載者:User

Apache Geronimo 小組已經成功實現了新的 Java Platform, Enterprise Edition (Java EE) 5.0 規範。Java EE 5 擁有許多值得關注的特性,其中之一就是新的 Java Standard Tag Library (JSTL) 1.2 規範。JSTL 1.2 的關鍵是統一運算式語言,它允許我們在 JavaServer Faces (JSF) 中結合使用 JSTL 的最佳特性。本期的叛逆者將介紹 JSTL 1.2 的重要性,探究 Java Web 技術的曆史以及 Geronimo 小組如何利用 GlassFish JSTL 1.2 實現將 JSTL 12 支援添加到 Geronimo 中。

Java Web 技術的演化

Web 技術一直都是 Enterprise Java 語言的一部分。它們從 servlet 開始,並在此基礎上發展演化。

Servlets

Servlets 最初的目的是用於響應 HTTP 要求。通常,編寫 servlet 是一件相當麻煩的事情。請看清單 1。

清單 1. 產生 HTML 的 Servlet

                     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {          ServletOutputStream out = response.getOutputStream();          out.println("<!DOCTYPE html PUBLIC /"-//W3C//DTD XHTML 1.0 Transitional//EN/" /"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd/">");          out.println("<html xmlns=/"http://www.w3.org/1999/xhtml/">");          out.println("<head>");          out.println("<meta http-equiv=/"Content-Type/" content=/"text/html; charset=ISO-8859-1/" />");          out.println("<title>All Users</title>");          out.println("</head>");          out.println("<body>");          out.println("     <table>");          out.println("          <tr>");          out.println("               <td>UserID</td>");          out.println("               <td>UserName</td>");          out.println("               <td>Name</td>");          out.println("          </tr>");          UserDao dao = new UserDao();          List users = dao.getAllUsers();          for (int i=0;i<users.size();i++){               User user = (User) users.get(i);               out.println("          <tr>");               out.println("               <td>"+user.getId()+"</td>");               out.println("               <td>"+user.getUserName()+"</td>");               out.println("               <td>"+user.getFirstName()+' '+user.getLastName()+"</td>");               out.println("          </tr>");          }          out.println("     </table>");          out.println("</body>");          out.println("</html>");     }

Servlets 涉及到大量嵌入到 Java 代碼中的 HTML(例如)。與開發 servlets 相比,對它們進行維護是更困難的事情。假設您希望修改清單 1 中的代碼,使表具有一個邊界。要實現這一目的,您需要修改 Java 代碼並重新編譯 servlet。所幸的是,servlets 很快就通過 JavaServer Pages (JSP) 技術得到了擴充。

JavaServer Pages

JSP 技術增強了 Java servlets。JSP 組件對 servlets 提供了許多改進,其中包括允許混合原生標記和 Java 代碼。清單 2 顯示了與 清單 1 相同的作為 JSP 組件的 servlet。

清單 2. JSP 1.0 版本

                <?xml version="1.0" encoding="ISO-8859-1" ?><%@ page language="java" contentType="text/html; charset=ISO-8859-1"    pageEncoding="ISO-8859-1"%><%@ page import="org.developerworks.*" %><%@ page import="java.util.List" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /><title>All Users</title></head><body>     <table>          <tr>               <td>UserID</td>               <td>UserName</td>               <td>Name</td>          </tr>          <%               UserDao dao = new UserDao();               List users = dao.getAllUsers();               for (int i=0;i<users.size();i++){                    User user = (User) users.get(i);          %>          <tr>               <td><%= user.getId() %></td>               <td><%= user.getUserName() %></td>               <td><%= user.getFirstName() %> <%= user.getLastName()                  %></td>          </tr>          <%               }          %>          </c:forEach>     </table></body></html>

顯然,清單 2 中的代碼在 servlet 的基礎上得到了重大的改進。JSP 組件仍然要編譯為 servlet,不過這需要通過 servlet 容器來完成(或者可以作為構建的一部分來完成)。因此,JSP 組件可以提供與 servlet 相同的效能。PHP 文法類似於 Active Server Page (ASP) 和 PHP 頁面,但是編譯為 servlet 使 JSP 組件相比其他技術擁有了顯著的效能優勢。



回頁首

JSP Model 2

清單 2 中的代碼仍然存在著一些不可忽視的問題。它在其中使用了一段 scriptlet,即一小段 Java 代碼。無論是站在設計還是實際的角度,使用 scriptlet 都會帶來一些問題。JSP 組件可以隨意將商務邏輯(檢索使用者列表)與表示混合在一起。經過發展演化,JSP Model 2 架構解決了這個問題,使 servlet 可以與 JSP 組件結合在一起使用。請看清單 3。

清單 3. Model 2 樣式的 servlet

                    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        UserDao dao = new UserDao();        List users = dao.getAllUsers();        request.setAttribute("users", users);        request.getRequestDispatcher("/user.jsp").forward(request, response);    }

servlet 可以首先處理請求和執行商務邏輯。然後可以將結果儲存在 HttpServletRequest 對象中,並將其轉寄給 JSP 組件。這使得 JSP 組件得以簡化,如清單 4 所示。

清單 4. Model 2 樣式的 JSP 組件

                <?xml version="1.0" encoding="ISO-8859-1" ?><%@ page language="java" contentType="text/html; charset=ISO-8859-1"    pageEncoding="ISO-8859-1"%><%@ page import="org.developerworks.*" %><%@ page import="java.util.List" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /><title>All Users</title></head><body>    <table>        <tr>            <td>UserID</td>            <td>UserName</td>            <td>Name</td>        </tr>        <%            List users = (List) request.getAttribute("users");            for (int i=0;i<users.size();i++){                User user = (User) users.get(i);        %>        <tr>            <td><%= user.getId() %></td>            <td><%= user.getUserName() %></td>            <td><%= user.getFirstName() %> <%= user.getLastName()    %></td>        </tr>        <%            }        %>        </c:forEach>    </table></body></html>

這解決了一些架構方面的問題。但是,仍然存在著一個實際問題。Java 代碼與 HTML 的混合提高了 JSP 組件的門檻,不具備 HTML 知識的 Java 開發人員和不懂 Java 語言的 Web 設計人員在使用 JSP 組件時都會遇到困難。

JavaServer Pages Standard Tag Library (JSTL)

清除 JSP 組件中的 Java scriptlet 成為了 JSP 技術的一個目標。這一探索的最終結果便是 JSTL。JSTL 引入了 HTML 樣式的標記,用於訪問 Java 對象和執行 Java 語言中的眾多構建任務,比如說迭代集合、條件邏輯和格式化文本。JSTL 允許 JSP 組件進一步發展深化,如清單 5 如示。

清單 5. 含有 JSTL 的 JSP

                <?xml version="1.0" encoding="ISO-8859-1" ?><%@ page language="java" contentType="text/html; charset=ISO-8859-1"    pageEncoding="ISO-8859-1"%><%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /><title>All Users</title></head><body>     <table>          <tr>               <td>UserID</td>               <td>UserName</td>               <td>Name</td>          </tr>          <c:forEach items="${users}" var="user">          <tr>               <td><c:out value="${user.id}"/></td>               <td><c:out value="${user.userName}"/></td>               <td><c:out value="${user.firstName}"/> <c:out value="${user.lastName}"/></td>          </tr>          </c:forEach>     </table></body></html>

<c:forEach> 標記允許對使用者列表進行迭代。<c:out> 標記允許對 Java 對象及其資料輸出進行訪問。

標記中所使用的各種運算式,如 ${users}${user.id},都是通過 JSTL Expression Language (EL) 解釋。比如說,EL 解釋字串 ${users} 並在可訪問的各個對象(如 pageContextrequestsessionservlet(應用程式)上下文)中尋找 users 屬性。經過進一步發展,JSP 組件允許從 JSTL 標記外部存取 EL。這使 JSP 組件的代碼再次改頭換面,如清單 6 所示。

清單 6. 在 JSP 中使用 JSTL 和 EL

                <?xml version="1.0" encoding="ISO-8859-1" ?><%@ page language="java" contentType="text/html; charset=ISO-8859-1"    pageEncoding="ISO-8859-1"%><%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /><title>All Users</title></head><body>     <table>          <tr>               <td>UserID</td>               <td>UserName</td>               <td>Name</td>          </tr>          <c:forEach items="${users}" var="user">          <tr>               <td>${user.id}</td>               <td>${user.userName}</td>               <td>${user.firstName} ${user.lastName}</td>          </tr>          </c:forEach>     </table></body></html>

這是一種更新式的 JSTL,並且 EL 首次出現在了 JSP 2.0 規範中。通過 Model 2 構架(通常由各種 使用者介面架構實現,比如 Apache Struts 等等),結合 JSTL 和 EL 能夠在不使用 Java 的情況下構建 JSP 組件。這允許非 Java 程式員操作 JSP 組件,並且讓 Java 開發人員能夠專註於實現他們應用程式的商務邏輯。

JavaServer Faces 技術

但是,JSP 技術並不是惟一一項構成 Enterprise Java 架構的 Web 技術。JSP 2.0 規範登場之後,JSF 技術也緊隨其後。JSF 旨在成為一個組件架構。Web 頁面上的各種對象都視為具有生命週期的組件,並與 Java 對象綁定在一起。因此,在本文的 JSP 樣本中,我們可以使用 JSF 直接將 Java 對象綁定到視圖組件。產生的 JSP 組件如清單 7 所示。

清單 7. 在 JSP 中使用 JSF

                <?xml version="1.0" encoding="ISO-8859-1" ?><%@ page language="java" contentType="text/html; charset=ISO-8859-1"    pageEncoding="ISO-8859-1"%><%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %><%@ taglib uri="http:.//java.sun.com/jsf/core" prefix="f" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /><title>All Users</title></head><body>     <f:view>          <h:dataTable id="users" value="#{UserBean.users}" var="user">               <h:column>              <f:facet name="header">UserID</f:facet>               <h:outputText value="#{user.id}"/>            </h:column>            <h:column>              <f:facet name="header">UserName</f:facet>               <h:outputText value="#{user.userName}"/>            </h:column>            <h:column>              <f:facet name="header">Name</f:facet>               <h:outputText value="#{user.firstName}"/> <h:outputText value="#{user.lastName}"/>            </h:column>          </h:dataTable>                </f:view></body></html>

注意我們是如何將 dataTable 綁定到 Java 對象的。然後,我們只需定義表的列,組件自己知道迭代表的行。我們假定使用該資料建立了一個託管的後台 bean (backing bean)(UserBean)。 dataTable 組件將為我們建立 HTML,因此無需為表指定任何 HTML。這是 JSF 的優勢之一。



回頁首

JSF 和 JSP 1.2

JSF 一直都在使用 JSP 技術。但是,當引入 JSF 時,JSP 1.2 是 JSP 技術使用最為廣泛的一個版本。因此 JSF 基於 JSP 1.2,這樣 JSF 便不支援 JSTL 和 EL。您可能已經注意到了 <h:dataTable><h:outputText> 的值屬性。它們看上去類似於 JSTL 所使用的 EL。但是,在 JSF 1.0 中,它們只是表面相同。JSF 擁有自己的 EL,其工作原理與 JSTL 中引入的 EL 極為相似,並且隨後成為 JSP 技術的一部分。但是,JSF EL 與 JSTL EL 並不相容 — 直到現在。

統一運算式語言

Java EE 5 的關鍵點之一就是統一運算式語言。這樣,JSTL 和 JSF 所使用的 EL 便合為一體。現在已經可以將 JSTL 和 JSF 混合在一起了,如清單 8 所示。

清單 8. JSF 和 JSTL 混合

                     <f:view>          <c:forEach items="${UserBean.groups}" var="group">               ${group.groupName}               <h:dataTable id="#{group.groupId}" value="#{group.users}"    var="user">                  <h:column>                   <f:facet name="header">UserID</f:facet>                    ${user.id}                 </h:column>                 <h:column>                   <f:facet name="header">UserName</f:facet>                    ${user.userName}                 </h:column>                 <h:column>                   <f:facet name="header">Name</f:facet>                    ${user.firstName} ${user.lastName}"                 </h:column>               </h:dataTable>                     </c:forEach>     </f:view>

清單 8 中的樣本示範了如何使用 JSTL 迭代多個組。然後,我們為各個組都建立了一個顯示表,用於列出組中的使用者。注意如何使用不同的 EL 分別為 JSTL 標記(<c:forEach>)和 JSF 組件(<h:dataTable>)引用資料,並作為直接在 JSP 組件中使用的 EL 運算式。通過混合 JSTL 和 JSF EL,我們獲得了雙劍合壁的效果。

EL 作為 Java EE 5 的一部分

Java EE 5 對 EL 還做出了一個主要修改。JSTL 實現並不要求成為 J2EE 1.4 規範的一部分。Web 應用程式開發人員可以在應用程式中選擇使用哪個 JSTL 實現。當然,他們也可以選擇只在應用程式中使用 JSF 實現。

Java EE 5 規範要求使用 JSTL 實現。Web 應用程式開發人員 再也不用為應用程式中的實現操心了。相反,他們可以毫不猶豫地選擇使用 JSTL。他們還可以利用 JSF 的強大功能。統一運算式語言也成為了 Java EE 5 規範的一部分。



回頁首

Geronimo 和 GlassFish JSTL

上一節介紹了這樣一個事實:在過去,Web 應用程式開發人員可以選擇是否包括 JSTL 技術。如果選擇是,那麼需要在應用程式中選擇要使用的 JSTL 實現。可用的 JSTL 實現多種多樣,不一而足。

如今,在 Java EE 5 中,JSTL 實現附帶在應用伺服器中。因此,Java EE 5 規範的任何實現都必須包括 JSTL 實現。當 Apache Geronimo 開發人員開始操作 Java EE 5 實現時 —Geronimo 2.0— 他們需要包括一個 JSTL 實現。

但是,他們不能隨意選取一個已有的實現。統一運算式語言是 JSTL 實現的一個重要要求。許多 JSTL 實現在設計時都不能與 JSF 一同運行。所幸的是,Geronimo 小組並沒有自己實現 JSTL 和統一運算式語言。他們可以利用 Sun 公司的 GlassFish。

您對 GlassFish 可能還比較陌生,它是 Sun 公司 Java EE 5 規範的參考實現。它是開源的應用程式,並且同時通過了 Sun 的 Common Development and Distribution License (CDDL) 和 GNU General Public License (GPL) 許可。Sun 一直都提供了一個 JSF 參考實現,因此他們很快便提供了一個含有統一運算式語言的 JSTL 參考實現。GlassFish 的開源性質使 Geronimo 小組能夠利用這一成果並在 Geronimo 2.0 中包含 GlassFish JSTL 實現。這個裡程碑式的發行版為:Geronimo 2.0-M1。

許可考慮

由於 GlassFish 同時通過了 CDDL 和 GPL 許可,因此可以將其包含在 Geronimo 中。但是,它的許可沒有像其餘 Geronimo 的 Apache 樣式的許可那樣,而是對 Geronimo 小組附加了一些限制。

基本上,Geronimo 包括 GlassFish JSTL,但是並沒有包括其原始碼。此外,Geronimo 小組無法修改其原始碼,但是他們顯然可以對 GlassFish JSTL 做貢獻並使用 Geronimo 打包出一個新的程式。

Geronimo 的一個非凡之處就是,您可以修改其代碼並將自己定製的 Geronimo 版本發布出去。但是,JSTL 實現顯然是一個例外。它的原始碼並沒有包含在 Geronimo 中,並且其許可為發布自訂版本的 Geronimo 施加了一些限制。比如說,如果您修改了 GlassFish 的原始碼,那麼其修改只在相同的 GlassFish 許可下才可以使用。



回頁首

結束語

隨著 Java 技術中各種 Web 技術的發展和演化,開發人員從中收穫了巨大的利益。統一運算式語言是 Web 技術的最新發展,它允許開發人員混合 JSTL 和 JSF 技術,並且允諾開發人員將繼續從中受益。如今,統一運算式語言是 Java EE 5 規範的一個重要部分,這使其也成為了 Geronimo 的一個重要部分。Geronimo 不僅實現了其規範,而且還使用了該規範的參考實現,再一次為開發人員提供了便利。使用 GlassFish JSTL 和 Geronimo 2.0,開發人員在構建 Java Web 應用程式時將擁有更多的選擇。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.