用response.sendRedirect()方法能夠將頁面重定向至其它頁面,重定向後在瀏覽器地址欄上會出現重定向頁面的URL。
【例4-7】頁面重定向
繼續使用例4-6中的login.jsp,用戶在輸入用戶名和密碼後將數據提交至checklogin.jsp頁面,checklogin.jsp檢查密碼是否等於「000000」,若是等於則顯示用戶登陸成功,不然跳轉至前面示例的dispatcherDemo.jsp頁面。
checklogin.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>responseDemo</title>
</head>
<body bgcolor="#ffffff">
<h1>
用戶登陸信息
</h1>
<%
String name=request.getParameter("name");
String password=request.getParameter("password");
if (password.equalsIgnoreCase("000000")){
%>
用戶登陸成功
<%}else{
response.sendRedirect("dispatcherDemo.jsp");
}
%>
</body>
</html>
首先運行login.jsp,如圖-11所示。

圖4-11 login.jsp運行顯示結果
輸入用戶名「orion」、密碼「000000」和驗證碼「2071」點擊「登陸」按鈕提交至checklogin.jsp頁面運行結果如圖4-12所示。

圖4-12 checklogin.jsp運行顯示結果
若是輸入密碼不等於「000000」時,checklogin.jsp將執行以下語句:
response.sendRedirect("dispatcherDemo.jsp");
顯示結果如圖4-13所示。
用response.sendRedirect()方法能夠將頁面重定向至其它頁面,重定向後在瀏覽器地址欄上會出現重定向頁面的URL。
【例4-7】頁面重定向
繼續使用例4-6中的login.jsp,用戶在輸入用戶名和密碼後將數據提交至checklogin.jsp頁面,checklogin.jsp檢查密碼是否等於「000000」,若是等於則顯示用戶登陸成功,不然跳轉至前面示例的dispatcherDemo.jsp頁面。
checklogin.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>responseDemo</title>
</head>
<body bgcolor="#ffffff">
<h1>
用戶登陸信息
</h1>
<%
String name=request.getParameter("name");
String password=request.getParameter("password");
if (password.equalsIgnoreCase("000000")){
%>
用戶登陸成功
<%}else{
response.sendRedirect("dispatcherDemo.jsp");
}
%>
</body>
</html>
首先運行login.jsp,如圖-11所示。

圖4-11 login.jsp運行顯示結果
輸入用戶名「orion」、密碼「000000」和驗證碼「2071」點擊「登陸」按鈕提交至checklogin.jsp頁面運行結果如圖4-12所示。

圖4-12 checklogin.jsp運行顯示結果
若是輸入密碼不等於「000000」時,checklogin.jsp將執行以下語句:
response.sendRedirect("dispatcherDemo.jsp");
顯示結果如圖4-13所示。

圖4-13 dispatcherDemo.jsp運行顯示結果
從運行結果來看IE的地址欄發生了改變已經徹底指向了
http://localhost:8080/implict_object/dispatcherDemo.jsp
說明是從客戶端從新發送了一次請求到服務器,因此dispatcherDemo.jsp沒法從request對象中再次取得用戶名參數。
【思考1】思考RequestDispatcher.forward()和response.sendRedirect()二者有什麼區別?編寫程序時使用哪一個更好?
版權方受權希賽網發佈,侵權必究
第 4 章:隱含對象解析做者:鄧子云,赫斌等 來源:希賽網 2014年03月03日
response對象:設置響應標頭
經過response.setHeader()方法能夠設置HTTP響應的頭信息參數使客戶端能自動產生相應的動做。
【例4-8】限時自動重定向
接下來將實現一個JSP中實如今某頁面停留若干秒後,自動重定向到另外一頁面的功能。實際上HTML的使用中也有相似的功能:
<meta http-equiv="refresh" content="300; url=target.jsp">
它的含義是:在5分鐘以後,正在瀏覽的頁面將會自動變爲target.html。代碼中的300爲刷新的延遲時間,以秒爲單位。targer.jsp爲你想轉向的目標頁,若爲本頁則爲自動刷新本頁。能夠經過setHeader來實現某頁面停留若干秒後,自動重定向到另外一頁面,關鍵代碼以下:
String content=stayTime+";URL="+URL;
response.setHeader("REFRESH",content);
refreshDemo.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>refreshDemo</title>
</head>
<body bgcolor="#ffffff">
<h1>
自動刷新示例
</h1>
<%
System.out.println(new java.util.Date()+ "刷新一次了");
String content=5+";URL=refreshDemo.jsp";
response.setHeader("REFRESH",content);
%>
</body>
</html>
refreshDemo.jsp設置的是每隔5秒刷新一次,運行結果顯示如圖4-14所示。

圖4-14 refreshDemo.jsp運行顯示結果

圖4-15 運行refreshDemo.jsp時Tomcat的控制檯輸出
版權方受權希賽網發佈,侵權必究
第 4 章:隱含對象解析做者:鄧子云,赫斌等 來源:希賽網 2014年03月03日
out對象
out對象能把結果輸出到網頁上。一般咱們最常使用out.println(String name)和out.print(String name),它們二者最大的差異在於println()在輸出的數據後面會自動加上換行的符號;而println()不會在數據後自動換行。但這種區別對於HTML網頁輸出在IE瀏覽中顯示沒有任何差異的,若是用記事本查看HTML源碼時能夠看到是有差異的。
out對象除了這兩種最常使用方法以外,它還有一些方法,這些方法主要是用來控制管理輸出的緩衝區(buffer)和輸出流(output stream)。
int getBufferSize():取得目前緩衝區的大小(KB)。
int getRemaining():取得目前使用後還剩下的緩衝區大小(KB)。
void clearBuffer():清除輸出緩衝區的內容。
void close():關閉輸出流,清除全部的內容。
【例4-9】使用out對象
outDemo.jsp
<%@ page contentType="text/html; charset=GBK"%>
<html>
<head>
<title>outDemo.jsp</title>
</head>
<body>
<h2>JSP out對象示例</h2>
<%
out.println("歡迎來到 JSP: 隱含對象<br>");
out.print("歡迎來到 JSP: 隱含對象<br>");
int BufferSize=out.getBufferSize();
int Availabel=out.getRemaining();
int Used=BufferSize-Availabel;
%>
緩衝區大小:<%= BufferSize%><br>
能夠使用大小:<%= Availabel%><br>
被使用了:<%=Used %><br>
</body>
</html>
outDemo.jsp運行顯示結果如圖4-16所示。

圖4-16 outDemo.jsp運行顯示結果
版權方受權希賽網發佈,侵權必究
第 4 章:隱含對象解析做者:鄧子云,赫斌等 來源:希賽網 2014年03月03日
與Context有關的隱含對象
本節中將要介紹session、application、pageContext這三個對象。session對象提供一些機制,讓服務器能個別辨認用戶。當程序在執行時,application對象能提供服務端(Server-Side)的Context,說明哪些資源是可利用的,哪些信息是可獲取的。pageContext對象提供存取全部在此網頁中能夠被利用的隱含對象,而且能夠管理它們的屬性。
版權方受權希賽網發佈,侵權必究
第 4 章:隱含對象解析做者:鄧子云,赫斌等 來源:希賽網 2014年03月03日
session對象
session對象表示用戶的會話情況,用此項機制能夠輕易識別每個用戶,能保存和跟蹤用戶與服務器之間的會話狀態。例如,購物車最常使用session的概念,當用戶把商品放入購物車時,它再去添加另外的商品到購物車時,原先選購的商品仍然在購物車內,並且用戶不用反覆去作身份驗證。但若是用戶關閉Web瀏覽器,則會斷開與服務器的會話。
session對象存儲有關用戶會話的全部信息。session對象用於在程序的網頁之間跳轉時,存儲有關會話的信息,如圖4-17所示。

圖4-17 會話跟蹤原理圖
session對象經常使用的方法以下。
void setAttribute(String name,Object value):以名稱/值的方式,將一個對象的值存放到session中。
void getAttribute(String name):根據名稱去獲取session中存放對象的值。
【例4-10】校驗驗證碼
接下來演示如何從session對象中得驗證碼,並比較用戶輸入的驗證碼是否與session對象中保存的驗證碼相等。一塊兒來修改例4-7中的checklogin.jsp文件代碼。
checklogin.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>responseDemo</title>
</head>
<body bgcolor="#ffffff">
<h1>
用戶登陸信息
</h1>
<%
String name=request.getParameter("name");
String password=request.getParameter("password");
if (password.equalsIgnoreCase("000000")){
//從Session中取得驗證碼的值
String verifycode=(String)session.getAttribute("verifycode");
//從客戶端取用戶提交過來驗證碼
String verifycode1=request.getParameter("verifycode");
if (verifycode.equalsIgnoreCase(verifycode1)){
%>
用戶登陸成功,客戶端輸入驗證碼爲:<%= verifycode1%>
<%}
}else{
response.sendRedirect("dispatcherDemo.jsp");
}
%>
</body>
</html>
接下來看看來效果。login.jsp的運行效果如圖4-18所示。

圖4-18 login.jsp運行顯示結果
輸入用戶爲「orion」,密碼爲「000000」和驗證碼爲「4762」點擊「登陸」按鈕後運行結果如圖所示。

圖4-19 從會話中取得驗證碼的顯示
版權方受權希賽網發佈,侵權必究
第 4 章:隱含對象解析做者:鄧子云,赫斌等 來源:希賽網 2014年03月03日
application對象
application對象的做用範圍比session更大,不只僅是在同一個瀏覽器窗口中,而是做用於整個應用程序,全部客戶端瀏覽器窗口均可以共享對象,它從服務器啓動開始就在,直到服務器關閉爲止。application對象經常使用的方法以下。
String getServerInfo():取得容器的名稱和版本。
void setAttribute(String name,Object value):以名稱/值的方式,將一個對象的值存放到application中。
void getAttribute(String name):根據名稱去獲取application中存放對象的值。
版權方受權希賽網發佈,侵權必究
第 4 章:隱含對象解析做者:鄧子云,赫斌等 來源:希賽網 2014年03月03日
pageContext對象
pageContext對象使用戶能夠訪問頁面做用域中定義的全部隱含對象。pageContext對象提供方法以訪問隱含對象在頁面上定義的全部屬性,它的做用範圍僅僅在頁面內。
pageContext對象最經常使用的方法以下。
void setAttribute(String name,Object value):以名稱/值的方式,將一個對象的值存放到pageContext中。
void getAttribute(String name):根據名稱去獲取pageContext中存放對象的值。
這兩個方法的使用與session,application相似,下面舉一個例子來區別pageContext、session、application這3個對象做用範圍的區別。
【例4-11】計數器
下面將分別使用session、application和pageContext對象顯示會話計數、應用程序計數和頁面計數。
Count.java
package implictobject;
public class Count {
//定義計數器
private int count;
//返回計數器的當前值
public int getCount(){
return ++count;
}
}
countDemo.jsp
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="implictobject.*" %>
<html>
<head>
<title>countDemo</title>
</head>
<body bgcolor="#ffffff">
<h1>
多種計數器示例
</h1>
<%
//判斷是否存在計數器對象,不存在則新建
if(pageContext.getAttribute("count")==null)
pageContext.setAttribute("count",new Count());
if(session.getAttribute("count")==null)
session.setAttribute("count",new Count());
if(application.getAttribute("count")==null)
application.setAttribute("count",new Count());
%>
<h2>
頁面計數器:
<%=((Count)pageContext.getAttribute("count")).getCount() %>
</h2>
<h2>
會話計數器:
<%=((Count)session.getAttribute("count")).getCount() %>
</h2>
<h2>
應用計數器:
<%=((Count)application.getAttribute("count")).getCount() %>
</h2>
</body>
</html>
countDemo.jsp運行結果如圖4-20所示。

圖4-20 countDemo.jsp運行結果
多刷新幾回頁面能夠發現頁面計數器始終爲1,會話計數器和應用計數器實現告終果累加。按如圖所示的操做新建一個瀏覽器窗口看看countDemo.jsp輸出的結果是否有變化。
看看新建瀏覽器窗口的輸出,以下圖所示。

圖4-21 新建瀏覽器窗口後countDemo.jsp運行結果
能夠看出application(應用計數器)徹底是依賴服務器存在的,session(會話計數器)依賴窗口會話,pageContext(頁面計數器)只依賴頁面自己。
版權方受權希賽網發佈,侵權必究
第 4 章:隱含對象解析做者:鄧子云,赫斌等 來源:希賽網 2014年03月03日
與Servlet有關的隱含對象
在JSP頁面的執行過程當中,每一個JSP頁面都會生成一個Servlet。Servlet對象提供方法和變量以訪問爲JSP頁面建立的Servlet的全部信息。Page和config就是這樣的Servlet對象。
版權方受權希賽網發佈,侵權必究
第 4 章:隱含對象解析做者:鄧子云,赫斌等 來源:希賽網 2014年03月03日
page對象
page對象提供對網頁上定義的全部對象的訪問。page對象表示頁面自己,它是java.lang.Object類的一個實例。爲JSP頁面建立的Servlet類定義變量和方法,這些變量和方法包含頁面的信息。使用page對象能夠訪問全部這些變量和方法。page對象的用法以下。
<%@page info="個人信息" contentType="text/html;charset=GBK" %>
<html>
<body>
<%=((javax.servlet.jsp.HttpJspPage)page).getServletInfo()%>
</body>
</html>
不過,page對象較少在JSP開發中使用,通常使用前面學過的page指令便可。
版權方受權希賽網發佈,侵權必究
第 4 章:隱含對象解析做者:鄧子云,赫斌等 來源:希賽網 2014年03月03日
config對象
config對象存儲Servlet的一些初始信息,與page對象同樣都會不多用到。config對象是javax.servlet.ServletConfig接口的一個實例,ServletConfig接口提供方法以檢索Servlet初始化參數。config對象表示編譯JSP頁面的Servlet初始化數據的配置。
String propertyFile=(String)config.getInitParameter("propertyFile");
版權方受權希賽網發佈,侵權必究
第 4 章:隱含對象解析做者:鄧子云,赫斌等 來源:希賽網 2014年03月03日
與Error有關的隱含對象
最後一類的隱含對象只有一個成員:exception對象。當JSP網頁有錯誤時會產生異常,而exception對象就來針對這個異常作處理。exception對象並非在每個JSP網頁中都可以使用。若要使用exception對象時,必須在page指令中設定。<%@page isErrorPage="true"%>才能使用,否則在編譯時會產生錯誤。
【例4-12】使用exception對象
MakerError.jsp
<%@ page contentType="text/html; charset=GBK" %>
<%@ page errorPage="ErrorPage.jsp" %>
<html>
<head>
<title>產生錯誤頁面</title>
</head>
<body bgcolor="#ffffff">
<h1>
產生被零整除錯誤的頁面,若是沒有發生跳轉說明頁面正確運行
</h1>
<%
int i=8,j=0;
out.print("i/j的正確結果:");
out.print(i/j);
%>
</body>
</html>
ErrorPage.jsp
<%@ page contentType="text/html; charset=GBK" %>
<%@page isErrorPage="true" %>
<%@page import="java.io.PrintWriter"%>
<html>
<head>
<title>錯誤處理頁面</title>
</head>
<body bgcolor="#ffffff">
<h1>
程序運行發生了以下錯誤:
</h1>
<font color="red">
錯誤緣由是:<%=exception.getMessage()%>
</font>
<br>
<font color="red">
錯誤跟蹤:<%exception.printStackTrace(new PrintWriter(out));%>
</font>
</body>
</html>
MakerError.jsp會產生一個除零異常將被自動轉給ErrorPage.jsp處理,由於<%@page isErrorPage="true" %>因此能讀取exception對象中的錯誤信息。運行結果如圖4-22所示。

圖4-22 錯誤處理頁面運行結果
【專家提示】程序代碼中打印異常追蹤信息使用了printStackTrace(new java.io.PrintWriter(out)),其中 printStackTrace()的參數要爲PrintWriter而不是JspWriter。
版權方受權希賽網發佈,侵權必究
第 4 章:隱含對象解析做者:鄧子云,赫斌等 來源:希賽網 2014年03月03日
小結
JSP隱含對象分爲I/O有關對象、Context有關對象、Servlet有關對象、Error有關對象4類。
I/O有關對象包括request、response和out;Context有關對象包括session、application和pageContext;Servlet對象包括config和page;Error有關對象包括exception。
request對象經過getParameter()和getParameterValues()方法去獲取表單請求數據;response對象經過sendRedirect()方法去實現重定向;out方法經過print()方法去實現頁面輸出。
session、application和pageContext對象經過setAttribute()和getAttribute()方法去設置和獲取屬性值。
版權方受權希賽網發佈,侵權必究
第 4 章:隱含對象解析做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
思考解答
【思考1】思考requestDispatcher.forward()和response.sendRedirect()二者的區別,以及平時在程序開發中如何使用它們?
答:requestDispatcher.forward()是容器中控制權的轉向,在客戶端瀏覽器地址欄中不會顯示出轉向後的地址;而response.sendRedirect()則是徹底的跳轉,瀏覽器將會獲得跳轉的地址,並從新發送請求連接。這樣,從瀏覽器的地址欄中能夠看到跳轉後的連接地址。前者更加高效,在前者能夠知足須要時,儘可能使用requestDispatcher.forward()方法。
第5章 Servlet開發
【本章專家知識導學】
衆所周知JSP頁面最終在服務端是被編譯成Servlet的形式運行的,要對JSP有深刻的瞭解,Servlet是最基本的內容,只要可以把Servlet學好,就更可以理解JSP技術底層運做的方式。
本章旨在引導讀者學習什麼是Servlet以及客戶端和服務器之間的數據傳輸是如何發生的。經過學習讀者還可以掌握HttpServlet類的方法,用於開發Servlet的Servlet生命週期、基本接口、類和方法的概念。讀者將可以較全面地使用Servlet API進行開發。
5.1 什麼是Servlet
服務器是一臺設備,它爲網絡上的不一樣設備(客戶端)的請求提供信息。例如,文件服務器提供有關文件的共享信息。最初,經過編寫CGI(Common Gateway Interface,通用網關接口)程序來實現數據在Web上的傳輸,這類程序是使用如Perl這樣的語言編寫的。可是,對於客戶端做出的每一個請求,必須建立CGI程序的一個新的實例,這將佔用大量內存致使系統運行效率不高。所以爲了解決這個問題,1997年3月 Sun Microsystems公司所組成的JavaSoft部門推出了Servlet技術替代當時的CGI之類的產品。Java Servlet是一個專門用於編寫網絡服務器應用程序的Java組件。全部基於Java的服務器端編程都是構建在Servlet之上的。Servlet具備以下優勢:
可移植性
因爲Servlet是用Java編寫的,因此它與生俱來就有跨平臺的特性,所以Servlet程序的設計徹底和平臺是無關的,一樣的Servlet徹底能夠在Apache,IIS等不一樣Web服務器上執行,無論底層的操做系統是Windows,Solaris,Mac,Linux仍是其餘的能支持Java的操做系統。
高效率
Servlet是跟普通的Java程序同樣,是被編譯成字節碼後由JVM執行的。相比傳統的CGI,儘管CGI是用本地代碼直接執行的,可是因爲每次客戶端發出請求,服務器必須啓動一個新的程序來處理請求,這就把高負載強加給了服務器資源,尤爲若是CGI使用腳本語言編寫時,如perl語言,服務器還必須啓動語言解釋程序,程序越多,佔用的內存就越多,消耗CPU資源也越多,嚴重影響系統性能。
Servlet運行於Servlet引擎管理的Java虛擬機中,被來自客戶機的請求所喚醒,與CGI不一樣的是,在虛擬機中只要裝載一個Servlet就可以處理新的請求,每一個新請求使用內存中那個Servlet的相同副本,因此效率比CGI要高。其它採用服務器端的腳本,如ASP,PHP,語言解釋程序是內置程序,所以能夠加快服務器的運行,可是效率仍是比不上準編譯的Servlet。實際的使用也已經證實,Servlet是效率很高的服務器端程序,很適合用來開發Web服務器應用程序。
【專家提示】使用過CGI的讀者必定知道CGI程序的做用,Servlet要實現的功能和CGI是同樣的,只是實現的時候更爲方便,效率更高。若是讀者對以上概念不是很清楚,也沒必要着急,經過學習下面的內容,有了感性的認識,再回來看看,必定會有更大的收穫。
擴展性
Java Servlet有着十分普遍的應用。不只能簡單的處理客戶端的請求,藉助Java的強大的功能,使用Servlet還能夠實現大量的服務器端的管理維護功能,以及各類特殊的任務,好比,併發處理多個請求,轉送請求,代理服務等。
版權方受權希賽網發佈,侵權必究
第 5 章:Servlet開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
Servlet的工做原理
Servlet容器將Servlet動態地加載到服務器上。以HTTP Servlet爲例,HTTP Servlet使用HTTP請求和HTTP響應標題與客戶端進交互。所以,Servlet容器支持請求和響應所用的HTTP協議。Servlet應用程序的工做原理如圖 5-1所示。

圖5-1 Servlet工做原理
客戶端對Servlet的請求首先會被Web服務器接收,Web服務器將客戶的HTTP請求提交給Servlet容器,Servlet容器調用相應的Servlet,Servlet做出的響應傳遞到Servlet容器,並進而由WEB服務器將響應傳輸給客戶端。WEB服務器提供靜態內容並將全部客戶端對Servlet做出的請求傳遞到Servlet容器。
Servlet是實現javax.servlet.Servlet接口的對象。大多數Servlet經過從GenericServlet或HttpServlet類進行擴展來實現。Servlet API包含於兩個包中,即javax.servlet和javax.servlet.http。
(1)javax.servlet包

圖5-2 javax.Servlet包
ServletInputStream類:用於從客戶端讀取二進制數據。
ServletOutputStream類:向客戶端發送二進制數據。
GenericServlet類:抽象類,定義一個通用的,獨立於底層協議的Servlet。
ServletRequest接口:定義一個對象封裝客戶向Servlet發關的請求信息。
ServletResponse接口:定義一個對象輔助Servlet將請求的響應信息發送給客戶端。
ServletContext接口:定義Servlet使用方法以獲取其容器的信息。
ServletConfig接口:定義了在Servlet初始化的過程當中由Servlet容器傳遞給Servlet的配置信息對象。
Servlet接口:定義全部Servlet必須實現的方法。
(2)javax.servlet.http包

圖5-3 javax.servlet.http
HttpServletRequest接口:擴展ServletRequest接口,爲HTTP Servlet提供HTTP請求信息。
HttpServletResponse接口:擴展ServletResponse接口,提供HTTP特定的發送響應的功能。
HttpSession接口:用於標識客戶端並存儲有送客戶端的信息。
HttpSessionAttributeListener接口:實現這個偵聽接口用於獲取會話屬性列表改變的通知。
HttpServlet類:擴展GenericServlet的抽象類。用於擴展建立Http Servlet。
Cookie類:建立一個Cookie,用於存儲Servlet發送給客戶端的消息。
版權方受權希賽網發佈,侵權必究
第 5 章:Servlet開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
如何開發Servlet
讀者瞭解Servlet的一些基礎知識後,接下來我將開發一個簡單的Servlet。開發Servlet步驟通常分爲:
安裝Servlet運行環境。
編寫Servlet接口的實現程序。
編譯並部署編寫好的Servlet程序。
運行Servlet查看結果。
版權方受權希賽網發佈,侵權必究
第 5 章:Servlet開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
安裝Servlet運行環境
爲了運行Servlet,首先固然須要一個JVM來提供對Java的基本支持,通常須要安裝JRE(Java Runtime Environment)或JDK(Java Develop Kit,JRE是其一個子集)。其次咱們須要Servlet API的支持,通常的Servlet引擎都自帶Servlet API,只要咱們安裝Servlet引擎,或直接支持Servlet的Web服務器以後便會自動安裝上Servlet相關的程序包。本章使用本書第二章「開發環境的安裝與配置」中所講述的Tomcat服務器爲Servlet運行環境。
【專家提示】典型的Servlet運行環境有JSWDK,Tomcat,Resin等,這幾個都是免費的軟件,適合用來學習Servlet和JSP。它們都自帶一個簡單的HTTP Server,只需簡單配置便可投入使用,也能夠把它們綁定到經常使用的Web服務器上,如Apache,IIS等,提供小規模的Web服務。還有一些商業的大中型的支持Servlet和JSP的Web服務器,如JRun,Web Sphere,Web Logic等等,配置比較複雜,並不適合初學者,可是功能較爲強大,有條件的讀者能夠一試。
版權方受權希賽網發佈,侵權必究
第 5 章:Servlet開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
編寫Servlet接口的實現程序
程序必須導入(import)javax.servlet.*、javaxservlet.http.*兩個包。
全部Servlet都必須實現javax.servlet.Servlet接口(Interface),可是一般咱們都會從javax.servlet.GenericServlet或javax.servlet.http.HttpServlet擇一繼承來實現。若寫的Servlet程序和HTTP協議無關,那必須繼承GenericServlet抽象類;如有關,就必須繼承HttpServlet抽象類。目前咱們絕大多數應用都是與HTTP協議有關,因此本書示例的Servlet繼承HttpServlet抽象類。
【例5-1】一個簡單的Servlet
firstServlet.java
package ch05;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class FirstServlet extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=GBK";
//初始化
public void init() throws ServletException {
}
//處理HTTP請求
protected void service(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>FirstServlet</title></head>");
out.println("<body bgcolor=\"#ffffff\">");
out.println("<H1>這是個人第一個Servlet</H1>");
out.println("</body>");
out.println("</html>");
out.close();
}
//清除資源
public void destroy() {
}
}
Servlet能夠利用HttpServletResponse接口的setContentType()方法來設定內容類型,咱們要顯示爲HTML網頁類型,所以,內容類型設爲「text/html」,這是HTML網頁的標準MIME類型值。以後,Servlet用getWrite()方法取得PrintWriter類型的out對象,它與PrintSteam相似,可是它能對Java的Unicode字符進行編碼轉換。最後,再利用out對象把字符串顯示在網頁上。
接下來看如何編譯、部署Servlet程序。將servlet-api.jar(能夠在{Tomcat_Install}\common\lib目錄下找到)加入至CLASSPATH之中,使用您的IDE工具或直接使用javac來編譯firstServlet.java。編譯好firstServlet.java以後將其生成的class文件放置到相應的Web應用目錄,如圖 5-4所示。

圖5-4 部署Servlet應用
接下再設定web.xml,以下:
<servlet>
<servlet-name>firstservlet</servlet-name>
<servlet-class>ch05.FirstServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>firstservlet</servlet-name>
<url-pattern>/firstservlet</url-pattern>
</servlet-mapping>
這樣當客戶端產生/firstservlet請求的時候,Tomcat就能把這個請求定向到ch05.firstServlet上,該Servlet就能正常運行了。
firstServlet.java的執行結果如圖5-5所示。

圖5-5 firstServlet.java的執行結果
版權方受權希賽網發佈,侵權必究
第 5 章:Servlet開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
Servlet的生命週期
跟客戶端的Applet類似,Servlet也遵循嚴格的生命週期。Servlet的生命週期由Servlet容器控制,容器建立Servlet的實例。Servlet生命週期就是指Servlet實例在建立以後響應客戶請求直至銷燬的全過程。Servlet實例的建立取決於Servlet的首次調用。Servlet接口定義了Servlet生命週期的3個方法,分別說明以下。
init()。當Servlet第一次被裝載時,Servlet引擎調用這個Servlet的init()方法,只調用一次。若是某個Sevlet須要特殊的初始化須要。那麼Servlet編寫人員能夠重寫該方法來執行初始化任務。這是一個可選的方法。若是某個Servlet不須要初始化,那麼默認狀況下將調用它父類的init()方法。系統保證,在init方法成功完成之前,是不會調用Servlet去處理任何請求的。
service()。這是Servlet最重要的方法,是真正處理請求的地方。對於每一個請求,Servlet引擎將調用Servlet的service()方法,並把Servlet請求對象和Servlet響應對象最爲參數傳遞給它。
destroy()。這是相對於init的可選方法,當Servlet即將被卸載時由Servlet引擎來調用,這個方法用來清除並釋放在init()方法中所分配的資源。
Servlet的生命週期能夠被概括爲如下幾步:
(1) 裝載Servlet,這一項操做通常是動態執行的。然而,Servlet一般會提供一個管理的選項,用於在Servlet啓動時強制裝載和初始化特定的Servlet。
(2) 服務器建立一個Servlet實例。
(3) 服務器調用Servlet的init()方法。
(4) 一個客戶端請求到達Server。
(5) 服務器建立一個請求對象。
(6) 服務器建立一個響應對象。
(7) 服務器激活Servlet的servic()e方法,傳遞請求和響應對象做爲參數。
(8) service()方法得到關於請求對象的信息,處理請求,訪問其餘資源,得到須要的信息。
(9) service()方法使用響應對象的方法。將響應傳回Server,最終到達客戶端。Service()方法可能激活其餘方法以處理請求。如doGet(),doPost()或其餘程序員本身開發的方法。
(10) 對於更多的客戶端請求,Server建立新的請求和響應對象,仍然激活此servlet的service()方法,將這兩個對象做爲參數傳遞給它,如此重複以上的循環,但無需再次調用init方法,Servlet通常只初始化一次。
(11) 當Server再也不須要Servlet時,好比當Server要關閉時,Server調用Servlet的destroy()方法。
Servlet生命週期的各個階段如圖5-6所示。

圖5-6 Servlet生命週期
【例5-2】Servlet的生命週期
接下來將firstServlet.java示例代碼修改演示Servlet生命週期的各類方法的調用。
firstServlet2.java
package ch05;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
//Servlet生命週期演示
public class FirstServlet2 extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=GBK";
private String user;
//讀取初始化參數
public void init() throws ServletException {
super.init();
user=this.getServletConfig().getInitParameter("user");
System.out.println("Servlet已經成功初始化");
}
//處理HTTP請求
protected void service(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>FirstServlet</title></head>");
out.println("<body bgcolor=\"#ffffff\">");
out.println("<H1>加載後初始化參數user="+user+"</H1>");
out.println("</body>");
out.println("</html>");
out.close();
System.out.println("Servlet的service方法被執行了一次");
}
//清除資源
public void destroy() {
System.out.println("Servlet實例已經被釋放");
}
}
firstServlet2加載並實例化後init()方法讀取web.xml中初始化參數並在系統控制檯輸出「Servlet已經成功初始化」的信息;service()方法接受客戶端的請求在響應中輸出init()方法中讀取的初始化參數值隨後在系統控制檯輸出「Servlet的service()方法被執行了一次」;容器在銷燬Servlet實例以前會調用destroy()方法,destroy()方法給了Servlet機會,來清除所持有的資源(好比內存,文件處理和線程),本例僅僅是在系統控制檯輸出「Servlet實例已經被釋放」。
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee_
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
<display-name>ch05</display-name>
<servlet>
<servlet-name>firstservlet</servlet-name>
<servlet-class>ch05.FirstServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>firstservlet</servlet-name>
<url-pattern>/firstservlet</url-pattern>
</servlet-mapping>
<!--Servlet生命週期示例-->
<servlet>
<servlet-name>firstservlet2</servlet-name>
<servlet-class>ch05.FirstServlet2</servlet-class>
<!--定義初始化參數-->
<init-param>
<param-name>user</param-name>
<param-value>jspdev</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>firstservlet2</servlet-name>
<url-pattern>/firstservlet2</url-pattern>
</servlet-mapping>
</web-app>
firstServlet2的執行結果如圖 5-7所示。

圖5-7 firstServlet2的執行結果
多點擊幾回「刷新」或按「F5」鍵並中止應用服務器,系統控制檯顯示結果如圖 5-8所示。

圖5-8 FirstServlet2運行時在系統控制檯輸出
能夠看到建立Servlet實例並初始化(init()方法)只在第一次調用Servlet時執行,之後反覆調用僅僅只執行service()方法。中止應用服務器(Tomcat)則調用了destroy()方法。
【專家提示】Servlet生命週期徹底由Servlet容器掌握,當Servlet容器沒有限定一個加載的Servlet能保存多長時間,所以,一個Servlet實例可能只在Servlet容器中存活幾毫秒,或是其餘更長的任意時間。所以示例中咱們採用了中止Tomcat應用服務器的方式來測試destroy()方法。
版權方受權希賽網發佈,侵權必究
第 5 章:Servlet開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
Servlet與表單交互
表單是HTML中使用最普遍的傳遞信息的手段。能使用Servlet與表單的交互,就在客戶端與服務器之間架起了一座橋樑。Servlet使用HttpServlet類中的方法與表單進行交互。在HttpServlet類中有幾個未徹底實現的方法,讀者能夠本身定義方法的內容,可是必須正確使用方法名稱以使HTTP Server把客戶請求正確的映射到相應的函數上。
版權方受權希賽網發佈,侵權必究
第 5 章:Servlet開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
HTTP Servlet
HttpServlet做爲一個抽象類用來建立用戶本身的 HTTP Servlet。HttpServlet類擴展了GenericServlet類。HttpServlet類的子類必須至少重寫如下方法中一個:
doGet():由服務器調用來處理客戶端發出的GET請求。經過GenericServlet類的service()方法來調用此方法。重寫GET方法還支持HTTP HEAD請求,該請求返回沒有主體只標題字段的響應。提交響應以前,Servlet容器要編寫標題,這是由於在HTTP中必須在發送響應主體以前發送標題。GET方法必須是安全的,若是客戶端請求更改存儲的數據,則必須使用其餘的HTTP方法。若是請求的格式不正確,則doGet()方法返回HTTP「請求錯誤」消息。doGet()方法的語法爲:
public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException
其中,request是存儲客戶端請求的HttpServletRequest對象;response是包含服務器對客戶端做出響應的HttpServletResponse對象。
doPost():服務器調用以容許Servlet處理客戶端發出的POST請求。經過GenericServlet類的service()方法來調用此方法。HTTP POST方法用於經過Internet發送大量數據。提交響應以前,Servlet容器要編寫標題,這是由於在HTTP中必須在發送響應主體以前發送標題。若是HTTP POST請求格式不正確,則doPost()方法會返回HTTP「請求錯誤」消息。doPost()方法的語法爲:
public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException
其中,request是存儲客戶端請求的HttpServletRequest對象;response是包含服務器對客戶端做出響應的HttpServletResponse對象。
doHeader()用於處理HEADER請求。
doPut()用於處理PUT請求。
doDelete()用於處理DELETE請求。
版權方受權希賽網發佈,侵權必究
第 5 章:Servlet開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
HttpServletRequest和HttpServletResponse
HttpServletRequest接口
HttpServletRequest接口擴展ServletRequest接口並向HTTP Servlet提供信息。Servlet容器建立HttpServletRequest實現對象,並將其做爲參數傳遞給Servlet的service()方法(service()方法再傳遞給doGet(),doPost()等)。
HttpServletRequest接口的經常使用方法以下。
getInputStream():返回客戶端請求中的二進制數據,並將其存儲在ServletInputStream對象中。
getParameter(String name):用於獲取隨請求信息一塊兒發送的請求參數。
getContentLength():返回客戶端發送的請求的實際長度,若是長度未知,則返回-1。
getMethod():返回用做出請求的HTTP方法的名稱,如GET和POST。
HttpServletResponse接口
HttpServletResponse接口擴展ServletResponse接口,用於幫助向客戶端發送響應。HttpServletResponse實現對象在建立後會做爲參數傳遞至service()方法。
HttpServletResponse接口的經常使用方法以下。
getOutputStream():返回一個ServletOutputStream對象,它被用來向客戶端發送二進制數據響應。
getWriter():返回將字符文本發送到客戶端的PrintWriter類的對象。
setContentLength(int len):容許設置將做爲響應發送的數據的長度。
【例5-3】Servlet與表單交互數據
接下來將在一個Servlet中演示對GET請求和POST請求的不一樣處理。
formServlet.java
package ch05;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class FormServlet extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=GBK";
//初始化
public void init() throws ServletException {
}
//處理HTTP的GET請求
public void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>FormServlet</title></head>");
out.println("<body bgcolor=\"#ffffff\">");
out.println("<h3>GET請求被處理</h3>");
out.println("<form method='post' action=''>");
out.println("姓名:<input name='name' type='text'/><br>");
out.println("年齡:<input name='age' type='text'/><br>");
out.println("<input type='submit' value='提交'/><br>");
out.println("</form>");
out.println("</body>");
out.println("</html>");
out.close();
}
//處理HTTP的POST請求
public void doPost(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
request.setCharacterEncoding("GBK");
String name=request.getParameter("name");
String age=request.getParameter("age");
out.println("<html>");
out.println("<head><title>FormServlet</title></head>");
out.println("<body bgcolor=\"#ffffff\">");
out.println("<h3>POST請求被處理</h3>");
out.println("姓名:"+name+"<br>");
out.println("年齡:"+age+"<br>");
out.println("</body>");
out.println("</html>");
out.close();
}
//Clean up resources
public void destroy() {
}
}
formServlet對GET請求的處理時,生成一個HTML表單網頁並指定的提交請求數據方式是POST方式,並再次向formServlet提交請求。對POST請求的處理時,接收請求參數顯示HTML網頁。

圖5-9 FormServlet對GET請求的處理

圖5-10 FormServlet對POST請求的處理
經過示例咱們能夠看到對於同一個Servlet對GET和POST請求的不一樣的處理方式。
【思考1】爲何程序中覆蓋doGet()和doPost()等方法而不覆蓋service()方法?
版權方受權希賽網發佈,侵權必究
第 5 章:Servlet開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
小結
Servlet是容許運行在服務器上的Java代碼,能響應用戶的請求生成動態的內容;運行Servlet必須提供一個Servlet容器;Servlet API主要包含在兩個包中,分別爲javax.servlet和javax.servlet.http;經過繼承GenericServlet抽象類或HttpServlet抽象類,能夠編寫Servlet。
Servlet的生命週期由Servlet容器徹底掌控,Servlet接口定義了Servlet生命週期的3個方法,分別爲init()、service()和destroy()。
繼承HttpServlet抽象類的Servlet必須覆蓋以下至少一個方法:doGet()、doPost()、doPut()、doDelete()、destroy()和getServletInfo()。
版權方受權希賽網發佈,侵權必究
第 5 章:Servlet開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
思考解答
【思考1】爲何程序中覆蓋doGet()和doPost()等方法而不覆蓋service()方法?
答:當服務器接收到對 servlet 的請求時,服務器會產生一個新的線程調用 service()方法。Service()方法檢查HTTP請求類型(GET、POST、PUT、DELETE 等)而後相應的調用doGet()、doPost()、doPut()、doDelete()等方法。若是servlet處理POST請求和GET請求方式相同,也能夠嘗試覆蓋service()方法。但這樣作並不理想,更好的作法在 doPost()方法中調用doGet()(或者反過來)。這種方法代碼稍多了一些,但相比直接覆蓋 service()方法它有幾個優勢:
1.這樣作確保您之後能夠在子類中添加對其餘請求服務的支持,如doPut()、doTrace() 等。若是您直接覆蓋了service()方法則就沒有了這種可能性。
2.您能夠經過實現getLastModified()方法來增長對修改日期的支持。若是您調用了 doGet()方法,標準service()方法會用getLastModified()方法設置header的最後修改日期而後對GET請求做出迴應(包括以修改過的 header,If-Modified-Since header)。
版權方受權希賽網發佈,侵權必究
第 6 章:JavaBean開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
什麼是JavaBean
第6章 JavaBean開發
【本章專家知識導學】
JavaBean是JSP開發中一種重要的組件開發技術,JSP程序員須要學會用JavaBean來封裝各類程序中的處理邏輯,以提升程序的可複用程度和可讀性,並學會在JSP頁面中使用JavaBean組件。
本章從JavaBean的基本概念講起,詳細講解了如何開發JavaBean,包括如何編寫、編譯、部署和使用JavaBean。
6.1 什麼是JavaBean
能夠把JavaBean簡單地理解爲一個Java類,這個類中封裝了一段能夠重複使用的Java代碼。Sun公司把JavaBean定義爲一個可重複使用的軟件組件。爲了方便使用,JavaBean每每被設計成是具備特定功能的,如生成一個數據庫鏈接的JavaBean類、表明網上商場購物車的JavaBean類、計算某些複雜數字運算公式的類等。
JavaBean有兩種,一種是帶有可視化界面的JavBean,如表明窗口界面中的按鈕的類、代碼窗口界面中的下拉框的類等;另外一種中沒有可視代界面的JavaBean,在Web開發者常使用後者,由於Web系統的界面經過HTML、CSS等技術結合已能完成,集成顯示在瀏覽器,配合以JavaScript語言還能夠實現許多的特效,這比窗口界面的可視化應用程序界面具備更加豐富的表現力。
在Web開發中,使用JavaBean能夠把各類程序邏輯功能與頁面分離開來,以在Web頁面中儘可能少地出現Java代碼,而大量的Java代碼封裝於JavaBean中,這樣程序的可讀性更強,可維護性也會更好一些,大多數狀況下,修改代碼只需修改JavaBean代碼,而沒必要在冗長的Web頁面中去尋找Java代碼。
版權方受權希賽網發佈,侵權必究
第 6 章:JavaBean開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
如何開發JavaBean
本節中學習開發JavaBean時所必須掌握的幾個關鍵步驟時要用到的方法與技術:如何編寫JavaBean,如何編譯JavaBean,如何打包和解包jar文件,如何部署JavaBean類和jar文件,以及如何在JSP頁面中使用JavaBean。
版權方受權希賽網發佈,侵權必究
第 6 章:JavaBean開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
編寫JavaBean
編寫JavaBean,其實質上就是寫一個Java類的源代碼,所以能夠使用許多的編輯工做來編寫,最簡單的就是使用記事本了。爲了方便編寫、調試、編譯程序,筆者推薦使用Java IDE開發工具,如Eclipse、Jbuilder。在Eclipse中編寫JavaBean時,編寫了屬性後,能夠用嚮導方面爲JavaBean類的屬性生成getXxxx()和setXxxx()方法的代碼,以下降手工書寫代碼出錯的可能性;保存了JavaBean類後,Eclipse能爲程序員自動編譯類(固然這須要在Eclipse環境中做出設置),生成.class字節碼文件,這樣,程序員就沒必要再書寫複雜的javac編譯指令了。
JavaBean既然是一個類,那麼它固然也就可以有屬性和方法,編寫JavaBean所要作的工做就是書寫屬性和方法的源代碼。書寫時程序員須要遵循以下的規則:
(1)屬性的get()與set()方法
屬性名爲xxxx,則相應的獲得屬性值和設置屬性值的方法爲getXxxx()和setXxxx(),方法名中屬性名的第一個字母爲大寫,具體形式以下:
public 屬性數據類型 getXxxx()
public void setXxxx(屬性數據類型 data)
參數data是設置賦與屬性的值。
若是屬性數據類型爲布爾型,則形式以下:
public boolean isXxxx()
public boolean getXxxx()
public void setXxxx(boolean data)
isXxxx()方法和getXxxx()方法用於獲得屬性的值,setXxxx()方法用設置屬性的值。
(2)訪問屬性的方法都設爲public,即公有方法;若是有構造函數,則方法也爲public型。
然而,以上2個規則並非嚴格的,好比設置成員屬性的值也並不必定要使用setXxxx()方法,讀者也能夠自行編寫方法,在調用JavaBean注意使用就好了。所以,程序員也能夠依本身的喜愛來編寫程序,不過遵循這2個規則將給其它程序帶來一些方便。好比在使用<jsp:setProperty>指令來設置JavaBean的屬性值,默認狀況下就是調用的setXxxx()方法,使用<jsp:setProperty>指令來獲得JavaBean的屬性值時,默認狀況下就是調用的getXxxx()方法。
版權方受權希賽網發佈,侵權必究
第 6 章:JavaBean開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
編譯JavaBean
編譯JavaBean的方法和編譯一個Java類的方法相同,使用javac命令。若是使用Eclipse這樣的Java IDE開發工具,Eclipse還能爲程序員自動編譯JavaBean,其實Eclipse也是使用的javac命令來完成編譯工做的。
打開「命令與提示符工具」(在Windows 9x/2000/XP中是在【開始】→【程序】→【附件】選項中),再切換到保存JavaBean類源文件(擴展名爲.java)的目錄下,輸入以下命令:
javac 源文件名.java
若是編譯經過就會在和JavaBean類源文件同一目錄下生成同名的.class文件。
javac是一個編譯工具,在JDK安裝目錄的bin子目錄下有javac.exe文件,它是這個編譯器的執行文件,也能夠帶一些參數來使用,形式以下:
javac [編譯時的選項] 源文件名.java
「[]」中的內容表示可選項,也就是說編譯時的選項無關緊要。經常使用的編譯時的選項有以下一些:
(1)-classpath path。設定編譯時須要用到的Java類文件的路徑,若是在系統變量CLASSPATH中已有則沒必要給出,參數path是類文件的路徑。
(2)-d directory。設定編譯生成的.class文件輸入到哪個目錄。一般狀況下,javac把生成的 .class文件放在 .java文件所在的目錄中;若是使用-d參數,則能夠指定javac將生成的 .class文件在其餘目錄中;參數directory是要放入的目錄。
(3)-g。此選項在代碼產生器中打開調試表,之後可憑此調試產生的字節代碼。
(4)-nowarn。此選項禁止編譯器產生警告。
(5)-o。告訴javac優化由內聯的static、final以及privite成員函數所產生的代碼。
(6)-verbose。告知Java顯示出有關被編譯的源文件和任何被調用類庫的信息。
最爲經常使用的是第1項和第2項,設定要用到的類和class文件輸出的路徑。
【例6-1】編譯一個簡單的JavaBean
編寫一個JavaBean類,源代碼以下:
book.java
package bean;
/**
* @author dengziyun
*/
public class book {
public long bookId;//書籍ID號
public String bookName;//書名
public String bookAbstract;//書的內容簡介
public String bookAuthor;//書的做者
public String bookPublisher;//書的出版社
public float bookPrice;//書的價格
/**
* @return Returns the bookAuthor.
*/
public String getBookAuthor() {
return bookAuthor;
}
/**
* @param bookAuthor The bookAuthor to set.
*/
public void setBookAuthor(String bookAuthor) {
this.bookAuthor = new String(bookAuthor);
}
/**
* @return Returns the bookId.
*/
public long getBookId() {
return bookId;
}
/**
* @param bookId The bookId to set.
*/
public void setBookId(long bookId) {
this.bookId = bookId;
}
/**
* @return Returns the bookName.
*/
public String getBookName() {
return bookName;
}
/**
* @param bookName The bookName to set.
*/
public void setBookName(String bookName) {
this.bookName = new String(bookName);
}
/**
* @return Returns the bookPublisher.
*/
public String getBookPublisher() {
return bookPublisher;
}
/**
* @param bookPublisher The bookPublisher to set.
*/
public void setBookPublisher(String bookPublisher) {
this.bookPublisher = new String(bookPublisher);
}
/**
* @return Returns the bookAbstract.
*/
public String getBookAbstract() {
return bookAbstract;
}
/**
* @param bookAbstract The bookAbstract to set.
*/
public void setBookAbstract(String bookAbstract) {
this.bookAbstract = new String(bookAbstract);
}
/**
* @return Returns the bookPrice.
*/
public float getBookPrice() {
return bookPrice;
}
/**
* @param bookPrice The bookPrice to set.
*/
public void setBookPrice(float bookPrice) {
this.bookPrice = bookPrice;
}
}
這個類爲書籍類,他的一個對象表明一本書。book類有6個屬性,bookId爲書籍的ID號,bookName爲書名,bookAbstract爲書的內容簡介,bookAuthor爲做者名稱,bookPublisher爲出版社名稱,bookPrice爲書的價格。這個類比較常見的用處就是在在線書店系統中,用來表明書籍,封裝數據庫中的書籍表的記錄。
針對書籍類的每個屬性都有相應的getXxxx()方法和setXxxx()方法,以便於JSP頁面在使用JavaBean時,能夠直接設置JavaBean的屬性。
進入命令窗口,將當前目錄切換到Java源文件所在的目錄,本處爲「D:\eclipse\workspace\javabean\src\bean」。若是系統變量PATH中沒有設置JDK的bin目錄,請加入。本例中設置JDK的bin目錄到PATH變量中的命令爲:
set path=%path%;d:\jdk5\bin
使用「%path%;」的目的是爲了避免影響PATH變量中原有的設置;本處由於JDK1.5安裝在「d:\jdk5」目錄中,故設置的路徑爲「d:\jdk5\bin」,讀者須要根據本身機器上的安裝狀況改變這個設置。
【專家提示】在命令窗口中設置變量PATH的值,並不會影響到系統變量的值,而只是對當前窗口中的對話在效,一旦窗口關閉即會失效,所以建議讀者把JDK的bin目錄設置到系統變量PATH中。設置系統變量能夠經過「個人電腦」「屬性」對話框中的「系統變量」選項卡來設置。
再用以下的命令編譯book.java:
javac book.java
【專家提示】book.java屬於bean包,在Java中包對應着操做系統的一個目錄,編譯時,須要把當前目錄切換到book.java所在的目錄,即Java源文件所在最底層的包的目錄。
編譯的狀況如圖6-1所示。

圖6-1 編譯book.java
從圖6-1也能夠看出,在book.java源文件的同一目錄下生成了編譯後的字節碼文件book.class。
版權方受權希賽網發佈,侵權必究
第 6 章:JavaBean開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
打包和解包jar文件
當編寫的類較多時,程序員經常會把類按功能類型,或按類與類之間的緊密程度,把屬於同一功能模塊或互相之間調用關係比較緊密的類放在同一個包中,若是類的體系比較龐大,還會將包再分紅若干個層次,造成一個樹形的架構,這就象操做系統文件夾的結構,事實上類的源代碼和編譯後的字節碼文件最終的表現形式也就是操做系統的文件夾結構,按包的層次進行組織。
若是在一個Web系統中須要引用許多個類,若是要將這些類一一配置到系統變量CLASSPATH中,要麼是CLASSPATH變量的配置參數值會至關冗長,且程序員要做的工做量也比較大,稍一不慎還會出錯。爲此,能夠考慮將全部要用到的類打成一個jar文件(或稱爲jar包),再在CLASSPATH中引用這個jar文件,就能夠使用這個jar文件中的全部類了。
那麼jar文件究竟是什麼呢?一個jar文件是一個壓縮包,能夠包含一組類及其相關的資源,甚至是聲音和圖像文件,把這些文件組成統一的一個文件——jar文件。有了jar文件,其中包含的類就沒必要一個一個地部署,能夠做爲一個jar文件一次部署,也能夠在網上方便下載,由於下載一個文件比下載多個文件方便得多。
將資源打包成jar文件的jar工具使用語法以下:
jar 打包時的選項 [打包後的jar文件名稱.jar] 要打包的文件
打包時的選項比較經常使用的有:
c——建立一個新的存檔文件。
f——文件列表中第一個文件的名稱爲要建立的或要訪問的包文件的名稱。
m——文件列表中的第一個文件是外部清單文件名。
t——jar文件的內容應制成表格。
u——更新已存在的jar文件。
v——當jar工具執行時顯示詳細信息。
X——從jar文件中展開文件。
這些選項能夠組合使用,如cvf。
「要打包的文件」參數中能夠使用通配符,若是是全部文件用「*」,若是是以JPEG爲擴展的則用*.JPEG。若是要將當前目錄下的全部.class文件打包成class.jar,可以使用以下的命令:
jar cf class.jar *.class
jar工具也能夠用於將jar文件解包。列出class.jar包中的文件命令以下:
jar tf class.jar
展開class.jar文件,並釋放在當前目錄下:
jar xf class.jar
除了jar工具之外,還有一種簡便的方法能夠將資源打包成jar文件,以及將jar文件解包,那就是使用WinRar或WinZip這樣的解壓縮工具。
將資源打包成jar文件的方法是:用WinRar或WinZip將資源打包成.zip壓縮文件,或將.zip文件的擴展名改成.jar。
將jar文件解包的方法是:將jar文件的擴展名改成.zip,再用WinRar或WinZip解壓縮。
版權方受權希賽網發佈,侵權必究
第 6 章:JavaBean開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
部署JavaBean類
部署JavaBean編譯後的.class文件,須要先考慮這個JavaBean是要讓Web站點中的全部Web應用都可以使用,仍是讓Web站點中的某一個Web應用可以使用,二者的部署方法不一樣。
若是要讓Web站點中的全部Web應用都可以使用,應當把類文件拷貝到Tomcat5安裝目錄的「common/classes」目錄中,若是類屬於某個包則應當把整個包都拷貝過去。
若是僅僅是想讓Web站點中的某一個Web應用可以使用,則應當把類文件拷貝到這個Web應用的「WEB-INF/classes」(注意區分大小寫)目錄中,「WEB-INF」是每一個Web應用都必需要有的子目錄。若是類屬於某個包則應當把整個包都拷貝過去。
版權方受權希賽網發佈,侵權必究
第 6 章:JavaBean開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
部署jar文件
與部署JavaBean相似,部署jar文件一樣有兩種狀況,一種是對Web服務器中的JSP頁面都有效;另外一種僅對當前應用有效。
若是要讓Web服務器中全部的JSP頁面均可以使用要部署的jar文件,則能夠把打包後的jar文件拷貝到Tomcat 5安裝目錄的「common/lib」或「lib」子目錄下,但須要重啓Tomcat服務器。這樣無需做出配置,JSP頁面便可使用這個jar文件了。
若是隻對當前的應用有效,則須在當前應用的WEB-INF子目錄中創建一個新的子目錄lib,並把jar文件拷貝過來。
【專家提示】其實,並沒必要把jar文件拷貝到這些指定的目錄中,也能夠是放在Web服務器中的任意以外,但必須在CLASSPATH系統變量中引用。
版權方受權希賽網發佈,侵權必究
第 6 章:JavaBean開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
在JSP中使用JavaBean
部署好JavaBean後就能夠JSP中使用了。要在JSP頁面中使用JavaBean,首先要用<%@page%>指令引入要使用到的類。如,要使用本章前文中編譯後的book類,可以使用以下的<%@page%>指令:
<%@page import="bean.book"%>
其中,book是要導入的類名,若是還有包,可在類名前加包名,形如「包名.類名」。
導入後便可以JSP頁面中的Java代碼中使用這個JavaBean類了。
JSP提供了指令標籤useBean簡單而又方便地使用JavaBean。這個指令標籤的語法以下:
<jsp:useBean id="給JavaBean實例取的名稱" class="Bean類名"
scope="JavaBean實例的有效範圍"></jsp:useBean>
或
<jsp:useBean id="給JavaBean實例取的名稱" class="JavaBean類名"
scope=" JavaBean實例的有效範圍"/>
其中,id的設置可由用戶任意給定;class爲JavaBean類名,若是類之上還有包,則此參數用形如「包名.類名」的形式;scope有四種不一樣的取值範圍,分別解說以下:
scope設爲page,表示分配給每一個客戶的JavaBean不一樣,有效範圍僅對當前的JSP頁面有效,若是關閉此JSP頁面,相應的分配給此客戶的JavaBean將被取消。
scope設爲session表示分配給每一個客戶的JavaBean不一樣,但在同一個客戶打開的多個JSP頁面,即一次會話其間,是同一個JavaBean。若是在同一客戶的不一樣JSP頁面中聲明瞭相同id的JavaBean,且範圍仍爲scope,若更改此JavaBean的成員變量值,其餘頁面中此id的Bean的成員變量值也會被改變。當客戶打開服務器上的全部網頁都被關閉時,對應客戶的這一次會話中的JavaBean也被取消。
scope設爲request表示分配給每一個客戶的JavaBean不一樣,且有效範圍在request期間,即在請求與被請求頁面之間共享JavaBean。當對請求做出響應後,JavaBean就會被取消。
scope設爲application表示在服務器的全部客戶之間共享JavaBean。當一個客戶改變了成員變量的值時,另外一個客戶的此JavaBean的同一個成員變量值也會被改變。當服務器關閉時JavaBean纔會被取消。
【例6-2】使用JavaBean
假設前面編寫的類book位於包javabean下,經編譯經過後已按本節中部署class文件或部署jar文件的方法部署好,再來看在JSP頁面中如何使用它。
useBeanBook.jsp
<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="bean.book"%>
<html>
<head>
<title>第一個JSP頁面</title>
</head>
<body>
<%//------用jsp:useBean指令使用JavaBean------
out.println("用jsp:userBean指令使用JavaBean<hr>");
%>
<jsp:useBean id="csaiBookZYS" class="bean.book" scope="page">
<jsp:setProperty name="csaiBookZYS" property="bookId" value="2"/>
<jsp:setProperty name="csaiBookZYS"
property="bookName" value="系統分析師技術指南"/>
<jsp:setProperty name="csaiBookZYS"
property="bookAuthor" value="張友生"/>
<jsp:setProperty name="csaiBookZYS"
property="bookPublisher" value="清華大學出版社"/>
<jsp:setProperty name="csaiBookZYS"
property="bookPrice" value="45"/>
</jsp:useBean>
<%
out.println("書籍ID號:"+csaiBookZYS.bookId+"<br>");
out.println("書名:"+csaiBookZYS.bookName+"<br>");
out.println("做者:"+csaiBookZYS.bookAuthor+"<br>");
out.println("出版社:"+csaiBookZYS.bookPublisher+"<br>");
out.println("訂價:"+csaiBookZYS.bookPrice);
%>
<jsp:getProperty name="csaiBookZYS" property="bookPrice"/>
<%//------在Java程序片中使用JavaBean------
book csaiBookDZY=new book();
csaiBookDZY.bookId=1;
csaiBookDZY.bookName="精通J2EE網絡編程";
csaiBookDZY.bookAuthor="鄧子云";
csaiBookDZY.bookPublisher="清華大學出版社";
csaiBookDZY.bookPrice=49;
out.println("<br>在Java程序片中使用JavaBean");
out.println("<hr>書籍ID號:"+csaiBookDZY.bookId+"<br>");
out.println("書名:"+csaiBookDZY.bookName+"<br>");
out.println("做者:"+csaiBookDZY.bookAuthor+"<br>");
out.println("出版社:"+csaiBookDZY.bookPublisher+"<br>");
out.println("訂價:"+csaiBookDZY.bookPrice+"<br>");
%>
</body>
</html>
程序的運行效果如圖6-2所示。

圖6-2 使用JavaBean
程序中經過兩種方法來使用JavaBean,一種是經過<jsp:useBean>指令來使用;另外一種是直接在Java程序片中使用。爲了減小Java代碼量,建議程序員儘可能使用JSP指令,以加強JSP頁面中代碼的可讀性。
版權方受權希賽網發佈,侵權必究
第 6 章:JavaBean開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
設置與獲得JavaBean的屬性
從例6-2能夠看出,使用setXxxx()方法和getXxxx()方法能設置和獲得JavaBean的屬性值,也能夠用動做標籤setProperty與getProperty來修改與獲取JavaBean的屬性值。
getProperty標籤得到JavaBean的屬性值,並將這個屬性值以字符串的形式顯示出來。getProperty的使用語法格式以下:
<jsp:getProperty name="JavaBean的名稱" property="JavaBean屬性的名稱"/>
或
<jsp:getProperty name="JavaBean的名稱" property="JavaBean屬性的名稱">
<jsp:getProperty>
setProperty標籤設置JavaBean的屬性值用於設置JavaBean的屬性值。setProperty標籤的使用語法有以下4種:
<jsp:setProperty name="bean的名稱" property="*"/>
<jsp:setProperty name="bean的名稱" property="屬性名稱"/>
<jsp:setProperty name="bean的名稱" property="屬性名稱" param="參數名稱"/>
<jsp:setProperty name="bean的名稱" property="屬性名稱" value="屬性值"/>
在第一種語法格式中,property="*",應用這種格式要求bean屬性的名稱與類型要和request對象中參數名稱與類型一致,以此用bean中的屬性來接收客戶輸入的數據,系統會根據名稱來自動匹配。若是類型不一致,會根據bean中的類型進行轉換。第二種語法格式則只設置其中匹配的一個bean的屬性。第三種語法格式根據指定的reaquest對象中的參數與屬性匹配。第四種語法格式用來給bean的屬性賦值,屬性值的數據類型要與屬性的數據類型一致,不然程序會出錯,所以要進行數據類型的轉換。
setProperty動做指令能夠在useBean動做指令中使用,也可在聲明瞭useBean後使用,但不能在聲明以前使用。與userBean動做指令結合使用的語法格式以下:
<jsp:useBean id="bean的名稱" scope="有效範圍" class="包名.類名">
<jsp:setProperty name="bean的名稱" property="屬性名稱" value="屬性值"/>
… …
<jsp:setProperty name="bean的名稱" property="屬性名稱" value="屬性值"/>
</jsp:useBean>
【專家提示】因爲用戶輸入的數據每每不規範,數據類型的轉換可能會出錯,所以在程序中要及時捕獲並報告錯誤,以加強程序的健壯性。
【專家提示】在同一個setProperty動做指令中不能同時存在param和value參數。
還一種方法,能夠經過表單來設置JavaBean的屬性值,但這種方法要求HTML表單輸入項的名字要與JavaBean屬性的名字相同,這樣服務器引擎會自動進行匹配把字符串轉換爲相應JavaBean屬性的數據類型數據。使用以下的語法格式:
<jsp:getProperty name="JavaBean的名稱" property="*"/>
【例6-3】用HTML表單設置JavaBean的屬性值
htmlJavaBean.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%!
public String codeToString(String str){//處理中文字符串的函數
String s=str;
try{
byte tempB[]=s.getBytes("ISO-8859-1");
s=new String(tempB);
return s;
}catch(Exception e){
return s;
}
}
%>
<jsp:useBean id="csaiBookZYS" class="bean.book" scope="page">
</jsp:useBean>
<jsp:setProperty name="csaiBookZYS" property="*"/>
<html>
<head>
<title>用HTML表單設置JavaBean的屬性</title>
</head>
<body>
<div align="center">
<center>
<%
out.println("書籍ID號:"+csaiBookZYS.bookId+"<br>");
out.println("書名:"+codeToString(csaiBookZYS.bookName)+"<br>");
out.println("做者:"+codeToString(csaiBookZYS.bookAuthor)+"<br>");
out.println("出版社:"+codeToString(csaiBookZYS.bookPublisher)+"<br>");
out.println("訂價:"+csaiBookZYS.bookPrice);
%>
<table border="1" width="46%">
<form name="form1" action="" method="post">
<tr>
<td width="44%">請輸入書籍ID號:</td>
<td width="56%"> <input type="text" name="bookId" size="20"></td>
</tr>
<tr>
<td width="44%">請輸入書名:</td>
<td width="56%"> <input type="text" name="bookName" size="20"></td>
</tr>
<tr>
<td width="44%">請輸入做者名字:</td>
<td width="56%"> <input type="text" name="bookAuthor" size="20"></td>
</tr>
<tr>
<td width="44%">請輸入出版社名稱:</td>
<td width="56%"> <input type="text" name="bookPublisher" size="20"></td>
</tr>
<tr>
<td width="44%">請輸入此書的訂價:</td>
<td width="56%"> <input type="text" name="bookPrice" size="20"></td>
</tr>
<tr>
<td width="100%" colspan="2">
<p align="center"><input type="submit" name="T1" size="20" value="提交">
<input type="reset" name="T1" size="20" value="重置"> </td>
</tr>
</form>
</table>
</center>
</div>
</body>
</html>
程序中,表單的action屬性值爲空,表示數據提交到本頁面。表單中的輸入框的名稱與JavaBean屬性的名稱一一對應起來了,所以能夠只用以下的一句語句便可將提交過來的數據設置爲JavaBean的屬性值:
<jsp:setProperty name="csaiBookZYS" property="*"/>
程序的運行結果如圖6-3所示。

圖6-3 用HTML表單設置JavaBean的屬性值
<jsp:setProperty name="csaiBookZYS" property="*"/>語句也能夠改成以下的5句,效果相同:
<jsp:setProperty name="csaiBookZYS" property="bookId" param="bookId"/>
<jsp:setProperty name="csaiBookZYS" property="bookName" param="bookName"/>
<jsp:setProperty name="csaiBookZYS" property="bookAuthor" param="bookAuthor"/>
<jsp:setProperty name="csaiBookZYS"
property="bookPublisher" param="bookPublisher"/>
<jsp:setProperty name="csaiBookZYS" property="bookPrice" param="bookPrice"/>
版權方受權希賽網發佈,侵權必究
第 6 章:JavaBean開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
小結
JavaBean是一個可重複使用的軟件組件,能夠用來執行復雜的計算任務,或負責與數據庫的交互以及數據提取等。Java中有兩種JavaBean,便可視化和非可視化JavaBean,在JSP中通常使用後者。
編寫JavaBean其實質上就是編寫一個Java類,編寫屬性和方法。編譯JavaBean用javac命令。若是類比較多,可分類用包存放,交能夠打包成jar文件,打包和解包jar方便使用jar命令。
使用JavaBean也就是使用一個Java類,能夠用<%@page import%>語句導入這個類後,便可在Java代碼塊中使用,也能用<jsp:useBean>標籤來使用,再經過<jsp:setProperty>標籤和<jsp:getProperty>標籤設置和獲得JavaBean的屬性值。
第7章 Web方式上傳與下載文件
【本章專家知識導學】
Web應用程序常常要進行文件的上傳、下載操做。能夠使用Java I/O流自定義完成文件操做的類,也能夠使用專業的第三方上傳、下載組件。使用Java I/O流自定義完成文件操做的類,程序代碼多,設計複雜;而使用專業的上傳、下載組件,程序代碼短小,編制簡單。經常使用的文件操做組件有jspSmartUpload、FileUpload。
經過本章的學習,要掌握使用jspSmartUpload組件進行文件上傳、下載操做方法和使用FileUpload組件進行文件上傳操做的方法。
7.1 文件操做組件介紹
jspSmartUpload是一款免費、開源的文件上傳下載組件,能夠從以下的網站下載獲得:
http:// www.jspsmart.com
jspSmartUpload適合於在JSP文件中嵌入式實現文件的上傳和下載功能。該組件有如下幾個特色:
1.使用簡單。在JSP文件中僅僅書寫三五行Java代碼就能夠完成文件的上傳或下載,程序員使用方便、快捷。
2.能全程控制上傳。利用jspSmartUpload組件提供的對象及其操做方法,能夠得到所有上傳文件的信息(包括文件名、大小、類型、擴展名、文件數據等),方便存取。
3.能對上傳的文件尺寸大小、類型等方面作出限制,能夠過濾掉不符合要求的文件。
4.下載靈功能活。只須要寫少許的代碼,就能把Web服務器當成是文件服務器來使用,不論文件是在Web應用的目錄下仍是在Web服務器的其它任何目錄下,均可以利用jspSmartUpload進行下載。
FileUpload也是一款免費開源的可實現文件上傳功能的組件,能夠從以下的網站下載獲得:
http://jakarta.apache.org
Commons是Apache開放源代碼組織中的一個Java子項目,該項目主要涉及一些開發中經常使用的模塊,例如文件上傳、命令行處理、數據庫鏈接池、XML配置文件處理等。這些項目集合了來自世界各地軟件工程師的心血,其性能、穩定性等方面都能經實際應用的考驗,有效地利用這些項目將會給開發帶來顯而易見的效果。FileUpload就是其中用來處理HTTP文件上傳的子項目。
版權方受權希賽網發佈,侵權必究
第 7 章:Web方式上傳與下載文件做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
jspSmartUpload組件的安裝與配置
下載獲得jspSmartUpload組件後,壓縮包的名字是jspSmartUpload.zip,將文件名更改成jspSmartUpload.jar(若是下載獲得的是jspSmartUpload.jar則無需更改)。Tomcat對文件名大小寫敏感,它要求Web應用程序相關的jar組件包所在目錄爲「WEB-INF/lib」。
將jspSmartUpload.jar文件拷貝到所須要使用jspSmartUpload組件的Web應用的「WEB-INF/lib」,便可以在這個Web應用的JSP文件中使用jspSmartUpload組件了。
【注意】按上述方法安裝後,只有當前Web應用下的程序能夠使用jspSmartUpload組件,若是想讓Web服務器的全部Web應用程序都能用它,則應當將jspSmartUpload.jar文件拷貝到Tomcat安裝目錄的「shared/lib」目錄下。
版權方受權希賽網發佈,侵權必究
第 7 章:Web方式上傳與下載文件做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
jspSmartUpload組件的主要對象
1.File類
這個類包裝了一個上傳文件的全部信息。經過它,能夠獲得上傳文件的文件名、文件大小、擴展名、文件數據等信息。
File類主要提供如下方法:
(1)saveAs()
方法原型:
public void saveAs(java.lang.String destFilePathName) 或
public void saveAs(java.lang.String destFilePathName, int optionSaveAs)
其中destFilePathName是另存的文件名,optionSaveAs是另存的選項,該選項有三個值,分別是SAVEAS_PHYSICAL,SAVEAS_VIRTUAL,SAVEAS_AUTO。SAVEAS_PHYSICAL代表以操做系統的根目錄爲文件根目錄另存文件,SAVEAS_VIRTUAL代表以Web應用程序的根目錄爲文件根目錄另存文件,SAVEAS_AUTO則表示讓組件決定,當Web應用程序的根目錄存在另存文件的目錄時,它會選擇SAVEAS_VIRTUAL,不然會選擇SAVEAS_PHYSICAL。
例如,saveAs("/upload/sample.zip",SAVEAS_PHYSICAL)執行後若Web服務器安裝在C盤,則另存的文件名實際是c:\upload\sample.zip。saveAs("/upload/sample.zip",_
SAVEAS_VIRTUAL)執行後若Web應用程序的根目錄是「webapps/jspsmartupload」則另存的文件名實際是「webapps/jspsmartupload/upload/sample.zip」。saveAs("/upload/sample.zip",SAVEAS_AUTO)執行時若Web應用程序根目錄下存在upload目錄,則其效果同saveAs("/upload/sample.zip",SAVEAS_VIRTUAL),不然同saveAs("/upload/sample.zip",SAVEAS_PHYSICAL)。
對於Web程序的開發來講,最好使用SAVEAS_VIRTUAL,以便於程序的移植。
(2)isMissing()
isMissing()方法用於判斷用戶是否選擇了文件,也即對應的表單項是否有值。選擇了文件時,它返回false。未選文件時,它返回true。方法原型:
public boolean isMissing()
(3)getFieldName()
getFieldName()方法用於獲取HTML表單中對應於此上傳文件的表單項的名字。 方法原型:
public String getFieldName()
(4)getFileName()
getFileName()方法用於獲取文件名(不含目錄信息)。方法原型:
public String getFileName()
(5)getFilePathName()
getFilePathName()方法用於獲取文件全稱(帶路徑)。方法原型:
public String getFilePathName
(6)getFileExt()
getFileExt()方法用於獲取文件擴展名(後綴)。方法原型:
public String getFileExt()
(7)getSize()
getSize()方法用於獲取文件長度,長度以字節計。方法原型:
public int getSize()
(8)getBinaryData()
getBinaryData()方法用於獲取文件數據中指定位移處的一個字節,用於檢測文件等。方法原型:
public byte getBinaryData(int index)
其中,index表示位移,其值在0到getSize()-1之間。
2. Files類
這個類表示全部上傳文件的集合,經過它能夠獲得上傳文件的數目、大小等信息。主要有如下方法:
(1)getCount()
getCount()方法可用於取得上傳文件的數目。方法原型:
public int getCount()
(2)getFile()
getFile()方法可用於取得指定位移處的文件對象File(這是com.jspsmart.upload.File,不是java.io.File,注意區分)。方法原型:
public File getFile(int index)。
其中index爲指定位移,其值在0到getCount()-1之間。
(3)getSize()
getSize()方法可得到上傳文件的總長度,可用於限制一次性上傳的數據量大小。方法原型:
public long getSize()
(4)getCollection()
getCollection()方法用於將全部上傳文件對象以Collection的形式返回,以便其它應用程序引用,瀏覽上傳文件信息。方法原型:
public Collection getCollection()
(5)getEnumeration()
getEnumeration()方法用於將全部上傳文件對象以Enumeration(枚舉)的形式返回,以便其它應用程序瀏覽上傳文件的信息。方法原型:
public Enumeration getEnumeration()
3. Request類
Request類的功能等同於JSP內置的對象request。只因此提供這個類,是由於對於文件上傳表單,經過request對象沒法得到表單項的值,必須經過jspSmartUpload組件提供的Request對象來獲取。該類提供以下方法:
(1)getParameter()
getParameter()方法用於獲取指定參數之值,若是指定的參數不存在,返回值爲null。 方法原型:
public String getParameter(String name)
其中name爲參數的名字。
(2)getParameterValues()
當一個參數能夠有多個值時,用getParameterValues()方法來取其值,getParameterValues()方法返回的是一個字符串數組若是指定的參數不存在,返回值爲null。 方法原型以下:
public String[] getParameterValues(String name)。其中,name爲參數的名字。
(3)getParameterNames()
getParameterNames()方法用於取得Request對象中全部參數的名字,經過返回的枚舉類型數據能夠遍歷全部參數。方法原型:
public Enumeration getParameterNames()
4.SmartUpload類
SmartUpload類用於完成上傳下載工做,它的主要方法以下。
(1)initialize()
initialize()方法是上傳與下載時共用的方法,用於執行上傳下載的初始化工做,必須第一個被執行。方法原型(有多個,主要使用下面這個):
public final void initialize(javax.servlet.jsp.PageContext pageContext)
其中pageContext爲JSP頁面內置對象(頁面上下文)。
(2)upload()
upload()方法用於上傳文件數據。通常地,上傳操做第一步執行initialize方法,第二步就是執行upload()方法。方法原型:
public void upload()
(2)save()
save()方法用於將所有上傳文件保存到指定目錄下,並返回保存的文件個數。 方法原型:
public int save(String destPathName) 或
public int save(String destPathName,int option)
其中destPathName爲文件保存目錄,option爲保存選項,它有三個值,分別是SAVE_PHYSICAL,SAVE_VIRTUAL和SAVE_AUTO。(同File類的saveAs方法的選項之值相似)SAVE_PHYSICAL指示組件將文件保存到以操做系統根目錄爲文件根目錄的目錄下,SAVE_VIRTUAL指示組件將文件保存到以Web應用程序根目錄爲文件根目錄的目錄下,而SAVE_AUTO則表示由組件自動選擇。
【專家提示】save(destPathName)做用等同於save(destPathName,SAVE_AUTO)。
(3)getSize()
getSize()方法用於獲取上傳文件數據的總長度。方法原型:
public int getSize()
(4)getFiles()
getFiles()方法用於獲取所有上傳文件,以Files對象形式返回,能夠利用Files類的操做方法來得到上傳文件的數目等信息。方法原型:
public Files getFiles()
(5)getRequest()
getRequest()方法用於取得Request對象,以便由此對象得到上傳表單參數之值。 方法原型:
public Request getRequest()
(6)setAllowedFilesList()
setAllowedFilesList()方法用於設定容許上傳帶有指定擴展名的文件,當上傳過程當中有文件名不容許時,組件將拋出異常。方法原型:
public void setAllowedFilesList(String allowedFilesList)
其中allowedFilesList爲容許上傳的文件擴展名列表,各個擴展名之間以逗號分隔。若是想容許上傳那些沒有擴展名的文件,能夠用兩個逗號表示。例如:setAllowedFilesList("doc,txt,,")將容許上傳帶doc和txt擴展名的文件以及沒有擴展名的文件。
(7)setDeniedFilesList()
setDeniedFilesList()方法用於限制上傳那些帶有指定擴展名的文件。如有文件擴展名被限制,則上傳時組件將拋出異常。方法原型:
public void setDeniedFilesList(String deniedFilesList)
其中deniedFilesList爲禁止上傳的文件擴展名列表,各個擴展名之間以逗號分隔。若是想禁止上傳那些沒有擴展名的文件,能夠用兩個逗號來表示。例如:setDeniedFilesList("exe,bat,,")將禁止上傳帶exe和bat擴展名的文件以及沒有擴展名的文件。
(8)setMaxFileSize()
setMaxFileSize()方法用於設定每一個文件容許上傳的最大長度。方法原型:
public void setMaxFileSize(long maxFileSize)
其中maxFileSize爲爲每一個文件容許上傳的最大長度,當文件超出此長度時,將不被上傳。
(9)setTotalMaxFileSize()
setTotalMaxFileSize()方法用於設定容許上傳的文件的總長度,以限制一次性上傳的數據量大小。方法原型:
public void setTotalMaxFileSize(long totalMaxFileSize)
其中totalMaxFileSize爲容許上傳的文件的總長度。
(10)setContentDisposition()
setContentDisposition()方法用於將數據追加到MIME文件頭的CONTENT-DISPOSITION域。jspSmartUpload組件會在返回下載的信息時自動填寫MIME文件頭的CONTENT-DISPOSITION域,若是用戶須要添加額外信息,請用此方法。方法原型:
public void setContentDisposition(String contentDisposition)
其中contentDisposition爲要添加的數據。若是contentDisposition爲null,則組件將自動添加「attachment;」,以代表將下載的文件做爲附件,結果是IE瀏覽器將會提示另存文件,而不是自動打開這個文件(IE瀏覽器通常根據下載的文件擴展名決定執行什麼操做,擴展名爲doc的將用word程序打開,擴展名爲pdf的將用acrobat程序打開,等等)。
(11)downloadFile()
downloadFile()方法用於下載文件,共有如下三個原型可用,第一個最經常使用,後兩個用於特殊狀況下的文件下載(如更改內容類型,更改另存的文件名)。
①public void downloadFile(String sourceFilePathName)
其中sourceFilePathName爲要下載的文件名(帶目錄的文件全名)
②public void downloadFile(String sourceFilePathName,String contentType)
其中sourceFilePathName爲要下載的文件名(帶目錄的文件全名),contentType爲內容類型(MIME格式的文件類型信息,可被瀏覽器識別)。
③public void downloadFile(String sourceFilePathName,String contentType,String destFileName)
其中sourceFilePathName爲要下載的文件名(帶目錄的文件全名),contentType爲內容類型(MIME格式的文件類型信息,可被瀏覽器識別),destFileName爲下載後默認的另存文件名。
版權方受權希賽網發佈,侵權必究
第 7 章:Web方式上傳與下載文件做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
FileUpload組件的安裝與配置
下載獲得FileUpload組件安裝包後,解壓獲得的zip包。將commons-fileupload.jar複製到要使用該組件的Web應用程序的「WEB-INF\lib」目錄下。
【注意】按上述方法安裝後,只有使用該組件的Web應用程序能夠使用FileUpload組件,若是想讓Tomcat服務器的全部Web應用程序都能用它,應當將commons-fileupload.jar拷貝到Tomcat的shared/lib目錄下。
版權方受權希賽網發佈,侵權必究
第 7 章:Web方式上傳與下載文件做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
文件上傳處理
本節中將分別介紹如何利用jspSmartUpload組件和FileUpload組件上傳文件。
版權方受權希賽網發佈,侵權必究
第 7 章:Web方式上傳與下載文件做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
利用jspSmartUpload組件進行文件上傳處理
下面經過三個實例來演示jspSmartUpload組件如何進行文件上傳處理操做。
【例7-1】jspSmartUpload簡單文件上傳
下面的web應用中,將實現一次能夠上傳三個文件到服務器上的功能。在JSP頁面上的表單中放置三個文件上傳域,【瀏覽…】按鈕用來選擇要上傳的文件,當選擇好文件後按【上傳】按鈕,就能夠將文件上傳至服務器upload目錄下。當完成上傳操做之後,服務器提示成功上傳多少個文件。
首先編寫提供文件選擇對話框的HTML頁面7-1.html中的代碼。
7-1.html
<HTML>
<HEAD>
<TITLE>例 7-1 jspSmartUpload 基本文件上傳</TITLE>
</HEAD>
<BODY BGCOLOR="white">
<HR>
<FORM METHOD="POST" ACTION="/jspsmartupload/7-1.jsp" ENCTYPE="multipart/form-data">
<INPUT TYPE="FILE" NAME="FILE1" SIZE="50"><BR>
<INPUT TYPE="FILE" NAME="FILE2" SIZE="50"><BR>
<INPUT TYPE="FILE" NAME="FILE3" SIZE="50"><BR>
<BR>
<INPUT TYPE="SUBMIT" VALUE="上傳">
</FORM>
</BODY>
</HTML>
【專家提示】凡是要上傳文件的表單都必須設置enctype屬性,且屬性值必須是「multipart/form-data」,同時method屬性必須設爲POST。
7-1.html的執行結果如圖7-1所示

圖7-1 7-1.html運行界面
接下來定義7-1.jsp來處理程序,7-1.jsp調用jspSmartUpload組件完成文件的上傳。
7-1.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page language="java" import="com.jspsmart.upload.*"%>
<jsp:useBean id="mySmartUpload" scope="page" class="com.jspsmart.upload.SmartUpload" />
<HTML>
<HEAD>
<TITLE>例 7-1 jspSmartUpload 基本文件上傳</TITLE>
</HEAD>
<BODY BGCOLOR="white">
<HR>
<%
// 聲明變量count,用來存儲上傳文件個數
int count=0;
// 執行初始化操做
mySmartUpload.initialize(pageContext);
//設定上傳文件最大字節數
mySmartUpload.setTotalMaxFileSize(100000);
// 上傳文件到服務器
mySmartUpload.upload();
try {
/*調用SmartUpload方法的save方法保存上傳文件。存儲時以文件原有名稱存儲。
尋找存儲路徑首先看當前web應用程序下是否存在upload目錄,若是有,則直接存儲在該目錄;不然,尋找web服務器所在驅動器物理路徑下是否存在upload目錄,若是有,則存儲,若是沒有,則會拋出異常。*/
count = mySmartUpload.save("/upload");
// 顯示上傳文件數量
out.println(count + "個文件已經上傳.");
} catch (Exception e){
out.println(e.toString());
}
%>
</BODY>
</HTML>
在執行後,選擇文件,單擊【上傳】按鈕,當上傳成功顯示確認頁面,如圖7-2所示。

圖7-2 上傳確認頁面
假設Tomcat5.5安裝在D盤根目錄下,
7-1.html和7-1.jsp都部署在D:\Tomcat5.5\webpass\jspsmartupload下,
jspSmartUpload.jar部署在D:\Tomcat5.5\webpass\jspsmartupload\WEB-INF\lib下。
若是 (如:D:\Tomcat5.5\webpass\jspsmartupload)以及Web服務器所在的物理路徑(如D:\)都不存在upload目錄,則拋出異常,如圖7-3所示。

圖7-3 存儲路徑不存在致使的異常
有時不但要上傳文件,並且還要顯示上傳文件信息。顯示上件文件信息,能夠經過File類的一些方法來得到。例如getFileName( )能夠獲得不帶目錄的文件名,getFilePathName()能夠獲得帶目錄的文件名,getFileExt()能夠獲得文件的擴展名,getsize()能夠獲得文件長度信息。接下來咱們看一個既能上傳文件,又能獲得文件信息的Web程序。
【例7-2】jspSmartUpload上傳文件,並顯示上傳文件信息
首先定義文件選擇頁面7-2.html
7-2 .html
<HTML>
<TITLE>
jspSmartUpload 上傳文件,並顯示上傳文件信息
</TITLE>
<BODY BGCOLOR="white">
<HR>
<FORM METHOD="POST" ACTION="/jspsmartupload/7-2.jsp"
ENCTYPE="multipart/form-data">
<INPUT TYPE="FILE" NAME="FILE1" SIZE="50"><BR>
<INPUT TYPE="FILE" NAME="FILE2" SIZE="50"><BR>
<INPUT TYPE="FILE" NAME="FILE3" SIZE="50"><BR>
<BR>
<INPUT TYPE="SUBMIT" VALUE="上傳">
</FORM>
</BODY>
</HTML>
7-2.html的執行結果如圖7-4所示

圖7-4 7-2.html 的執行結果
接下來定義文件上傳處理程序7-2.jsp。
7-2.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page language="java" import="com.jspsmart.upload.*"%>
<jsp:useBean id="mySmartUpload" scope="page" class="com.jspsmart.upload.SmartUpload" />
<HTML>
<TITLE>
例7-2 jspSmartUpload 上傳文件,並顯示上傳文件信息
</TITLE>
<BODY BGCOLOR="white">
<TABLE BORDER=1 bordercolor="Black">
<TR><TD WIDTH="100">文件名</TD><TD WIDTH="50">擴展名</TD>
<TD WIDTH="100"> 長度</TD> <TD WIDTH="300"> 帶路徑的文件名</TD> </TR>
<%
// 聲明變量count,用來存儲上傳文件個數
int count=0;
// 執行初始化操做
mySmartUpload.initialize(pageContext);
// 上傳文件到服務器
mySmartUpload.upload();
// 對上傳到服務器的文件進行逐個處理
for (int i=0;i<mySmartUpload.getFiles().getCount();i++)
{
// 取出一個文件
com.jspsmart.upload.File myFile = mySmartUpload.getFiles().getFile(i);
// 只有myFile表明的文件存在時才執行存儲操做
if (!myFile.isMissing()) {
// 保存該文件到web應用程序下的upload目錄
myFile.saveAs("/upload/" + myFile.getFileName());
%>
<TR><TD WIDTH="100"><%=myFile.getFileName()%> </TD>
<TD WIDTH="50"><%=myFile.getFileExt()%></TD>
<TD WIDTH="100"><%=myFile.getSize()%> </TD>
<TD WIDTH="300"><%=myFile.getFilePathName()%></TD> </TR>
<%
//成功上傳文件計數
count++;
}
}
%>
</TABLE>
<%
// 顯示能被上傳的文件數目
out.println("<BR>"+mySmartUpload.getFiles().getCount()+"個文件 能被上傳.<BR>");
// 顯示成功上傳的文件數目
out.println(count + " 個文件 已成功上傳.");
%>
</BODY>
</HTML>
獲得的上傳信息如圖7-5所示

圖7-5 上傳文件,並顯示文件信息
在網站中文件上傳已是經常使用的功能了,考慮到網絡的傳輸速度等緣由,多數狀況上傳的文件不該該很大,這就須要對用戶上傳文件的大小和類型進行限制。jspSmartUpload組件SmartUpload類提供了有效的方法來解決這些問題。例如:設置容許上傳文件的大小限制用setMaxFileSize()方法,容許上傳指定的帶有指定擴展名的文件用setAllowedFilesList(String allowedFilesList)方法,不容許上傳帶有擴展名的文件用setDeniedFilesList(String allowedFilesList)方法。接下來看一個利用jspSmartUpload上傳文件,並對上傳文件進行限制的Web程序。
【例7-3】jspSmartUpload上傳文件,並對上傳文件進行限制
7-3.html
<HTML>
<TITLE>
例7-3 jspSmartUpload 上傳文件,並對上傳的文件進行限制
</TITLE>
<BODY BGCOLOR="white">
<HR>
<FORM METHOD="POST" ACTION="/jspsmartupload/7-3.jsp"
ENCTYPE="multipart/form-data">
<INPUT TYPE="FILE" NAME="FILE1" SIZE="50"><BR>
<INPUT TYPE="FILE" NAME="FILE2" SIZE="50"><BR>
<INPUT TYPE="FILE" NAME="FILE3" SIZE="50"><BR>
<BR>
<INPUT TYPE="SUBMIT" VALUE="上傳">
</FORM>
</BODY>
</HTML>
7-3.html執行結果如圖7-6所示

圖7-6 7-3.html執行結果
接下來定義7-3.jsp處理程序
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page language="java" import="com.jspsmart.upload.*"%>
<jsp:useBean id="mySmartUpload"
scope="page" class="com.jspsmart.upload.SmartUpload" />
<HTML>
<TITLE>
例7-3 jspSmartUpload 上傳文件,並對上傳的文件進行限制
</TITLE>
<BODY BGCOLOR="white">
<HR>
<%
int count=0;
mySmartUpload.initialize(pageContext);
// 只容許上傳htm/html/txt/bmp/gif/mp3類型文件
mySmartUpload.setAllowedFilesList("htm,html,txt,bmp,gif,mp3,,");
//設置不容許上傳的文件類型exe/bat/zip
// mySmartUpload.setDeniedFilesList("exe,bat,zip");
//設置容許上傳文件的大小限制
// mySmartUpload.setMaxFileSize(50000);
mySmartUpload.upload();
//在服務器的上傳目錄中使用原始文件名保存文件
try {
count = mySmartUpload.save("/upload", mySmartUpload.SAVE_VIRTUAL);
} catch (Exception e){
out.println("<b>錯誤信息 : </b>" + e.toString());
}
//顯示成功上傳的文件數目
out.println(count + " 個文件 己經成功上傳。");
%>
</BODY>
</HTML>
當按指定類型(htm/html/txt/bmp/gif/mp3類型)上傳文件時,獲得的上傳處理信息,如圖7-7所示。

圖7-7 上傳文件成功信息
當不按指定類型(禁止exe/bat/zip類型)上傳文件時,就會拋出異常信息,如圖7-7所示。

圖7-7 拋出異常信息
版權方受權希賽網發佈,侵權必究
第 7 章:Web方式上傳與下載文件做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
利用FileUpload組件進行文件上傳處理
FileUpload組件將頁面提交的全部元素(普通form表單域,如text和文件域file)都看做同樣的FileItem,這樣上傳頁面提交的request請求也就是一個FileItem的有序組合,FileUpload組件能夠解析該request,並返回一個的FileItem。而對每個FileItem,FileUpload組件能夠判斷出它是普通form表單域仍是文件file域,從而根據不一樣的類型,採起不一樣的操做:若是是普通的表單域,就讀出其值,若是是文件域,就保存文件到服務器硬盤上或者內存中。
本小節將經過兩個實例,演示FileUpload組件的用法。
【例7-4】利用apachefileupload組件進行文件上傳
7-4.html
<HTML>
<TITLE>
例7-4 apachefileupload 上傳文件
</TITLE>
<BODY BGCOLOR="white">
<HR>
<FORM METHOD="POST" ACTION="/apachefileupload/7-4.jsp"
ENCTYPE="multipart/form-data">
<INPUT TYPE="FILE" NAME="FILE1" SIZE="50"><BR>
<INPUT TYPE="FILE" NAME="FILE2" SIZE="50"><BR>
<INPUT TYPE="FILE" NAME="FILE3" SIZE="50"><BR>
<BR>
<INPUT TYPE="SUBMIT" VALUE="上傳">
</FORM>
</BODY>
</HTML>
【注意】必須保證表單的ENCTYPE屬性值爲multipart/form-data,這樣瀏覽器才能正確執行上傳文件的操做。
7-4.html執行結果如圖7-8所示

圖7-8 7-4.html執行結果
接下來編寫7-4.jsp處理程序。首先建立一個DiskFileUpload對象,經過它來解析請求。執行解析後,全部的表單都保存在一個List中。而後經過循環依次得到List裏的FieldItem對象。
7-4.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="org.apache.commons.fileupload.*"%>
<%@ page import="java.util.*"%>
<%@ page import="java.io.*"%>
<HTML>
<TITLE>例7-4 apachefileupload 上傳文件</TITLE>
<BODY BGCOLOR="white">
<%
try {
//建立一個DiskFileUpload對象,經過它來解析請求
DiskFileUpload fu = new DiskFileUpload();
// 獲得全部的文件:
List fileItems = fu.parseRequest(request);
%>
<TABLE BORDER=1 bordercolor="Black">
<TR><TD WIDTH="500">文件名</TD><TD WIDTH="100">文件長度</TD> </TR>
<%
Iterator i = fileItems.iterator();
// 依次處理每個文件:
while(i.hasNext()){
FileItem fi = (FileItem)i.next();
// 得到文件名,這個文件名包括路徑:
String fileName = fi.getName();
if(fileName!=null && fileName.length()!=0) {
File fullFile = new File(fi.getName());
File savedFile =
new File(application.getRealPath("/")+"/uploadfiles",_
fullFile.getName());
fi.write(savedFile);
%>
<TR><TD WIDTH="500"><%=fi.getName()%> </TD>
<TD WIDTH="100"><%=fi.getSize()%></TD> </TR>
<%
}
}
%>
</TABLE>
<%
out.println("己經成功上傳" );
}
catch(Exception e) {
e.printStackTrace();
out.println(e.getMessage());
}
%>
</BODY>
</HTML>
7-4.jsp執行後頁面所如圖7-9所示。

圖7-9 7-4.jsp執行後頁面
【例7-5】利用apachefileupload組件進行文件上傳,並對上傳文件進限制。
7-5.html
<HTML>
<TITLE>
例7-5 apachefileupload 上傳文件,並對上傳文件進行限制
</TITLE>
<BODY BGCOLOR="white">
<HR>
<FORM METHOD="POST" ACTION="/apachefileupload/7-5.jsp"
ENCTYPE="multipart/form-data">
<INPUT TYPE="FILE" NAME="FILE1" SIZE="50"><BR>
<INPUT TYPE="SUBMIT" VALUE="上傳">
</FORM>
</BODY>
</HTML>
7-5.hmtl執行結果如所圖7-10所示

圖7-10 7-5.hmtl執行結果
接下來編寫7-5.jsp處理程序:處理程序首先檢查服務器目錄,是否有upload目錄,如沒有就建立;而後檢查unload目錄是否有tmp目錄,如沒有就建立;接下來就是進行上傳操做。
7-5.jsp
<HTML>
<TITLE>
例7-5 apachefileupload 上傳文件,並對上傳文件進行限制
</TITLE>
</HTML>
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="org.apache.commons.fileupload.*"%>
<%@ page import="java.util.*"%>
<%@ page import="java.io.*"%>
<%
File uploadPath=new File("c:\\upload");//上傳文件目錄
if(!uploadPath.exists()){
uploadPath.mkdirs();
}
String tempPath="c:\\upload\\tmp\\"; // 臨時文件目錄
File tempPathFile=new File("c:\\upload\\tmp");
if(!tempPathFile.exists()){
tempPathFile.mkdirs();
}
try {
DiskFileUpload fu = new DiskFileUpload();
// 設置最大文件尺寸 1MB
fu.setSizeMax(10485760);
// 設置緩衝區大小,這裏是4KB
fu.setSizeThreshold(4096);
// 設置臨時目錄:
fu.setRepositoryPath(tempPath);
// 獲得全部的文件:
List fileItems = fu.parseRequest(request);
Iterator i = fileItems.iterator();
// 依次處理每個文件:
while(i.hasNext()) {
FileItem fi = (FileItem)i.next();
// 得到文件名,這個文件名包括路徑:
String fileName = fi.getName();
if(fileName!=null) {
File fullFile = new File(fi.getName());
File savedFile = new File(uploadPath ,fullFile.getName());
fi.write(savedFile);
}
}
out.println("文件已經成功上傳");
}
catch(Exception e) {
out.println(e.getMessage());
}
%>
7-5.jsp處理程序上傳文件成功提示頁面以下圖7-11所示。

圖7-11 7-5.jsp 文件上傳成功提示頁面
當文件違反限制進行上傳時,處理程序會出現提示頁面如圖7-12所示。

圖7-12 7-5.jsp 文件違反限制上傳時出現的提示頁面
在這個文件中須要注意的是FileUpload對象的一些參數值的意義,以下面代碼所示的三個參數sizeMax、sizeThreshold、repositoryPath:
// 設置容許用戶上傳文件大小,單位:字節
fu.setSizeMax(104857600);
// 設置最多隻容許在內存中存儲的數據,單位:字節
fu.setSizeThreshold(4096);
// 設置一旦文件大小超過getSizeThreshold()的值時數據存放在硬盤的目錄
fu.setRepositoryPath(tempPath);
這3個參數的意義分別爲:
sizeMax:用來設置上傳文件大小的最大值,一旦用戶上傳的文件大小超過該值時將會拋出一個FileUploadException異常,提示文件太大;
sizeThreshold:設置內存中緩衝區的大小,一旦文件的大小超過該值的時候,程序會自動將其它數據存放在repositoryPath指定的目錄下做爲緩衝。合理設置該參數的值能夠保證服務器穩定高效的運行;
repositoryPath:指定緩衝區目錄。
【專家提示】從實際應用的狀況來看要想上傳文件的程序可以穩定高效的工做,其中參數SizeThreshold的值相當重要,設置太大會佔用過多的內存,設置過小會頻繁使用硬盤做爲緩衝以至犧牲性能。所以,設置該值時要根據用戶上傳文件大小分佈狀況來設定。例如大部分文件大小集中在100KB左右,則能夠使用100KB做爲該參數的值,固然了再大就不太合適了。
版權方受權希賽網發佈,侵權必究
第 7 章:Web方式上傳與下載文件做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
文件下載處理
jspSmartUpload組件提供上傳和下載功能,而FileUpload組件只提供上傳功能。下面這個例子演示了利用jspSmartUpload組件進行文件下載操做。
【例7-7】利用 jspSmartUpload下載文件
首先編寫下載頁面7-7.html中的代碼,該文件連接到下載處理程序7-7.jsp。
7-7.html
<HTML>
<TITLE>
例7-7 jspSmartUpload 下載文件
</TITLE>
<BODY BGCOLOR="white">
<HR>
<A HREF="/jspsmartupload/7-7.jsp"> readme.txt 下載</A>
</BODY>
</HTML>
7-7.html執行結果如圖7-13所示

圖7-13 7-7.html執行結果
接下來編寫7-7.jsp處理程序
7-7.jsp
<jsp:useBean id="mySmartUpload"
scope="page" class="com.jspsmart.upload.SmartUpload" /><%
mySmartUpload.initialize(pageContext);
// 設定contentDisposition爲null以禁止瀏覽器自動打開文件,
//保證點擊連接後是下載文件。若不設定,則下載的文件擴展名爲txt時,直接在瀏覽器打開。
//文件類型爲doc時,瀏覽器將自動用word打開它。擴展名爲pdf時瀏覽器將用acrobat打開。
mySmartUpload.setContentDisposition(null);
// 下載文件
mySmartUpload.downloadFile("/upload/readme.txt");%>
版權方受權希賽網發佈,侵權必究
第 7 章:Web方式上傳與下載文件做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
小結
本章主要講解了如何利用jspSmartUpload組件進行文件上傳、下載操做,如何利用FileUpload組件進行上傳操做。調用的jspSmartUpload和FileUpload這兩個組件的訪問頁面表單都必須設置enctype屬性,且屬性值必須是「multipart/form-data」,同時表單的method屬性值必須是POST。jspSmartUpload、 FileUpload組件均可以進行文件上傳和對上傳文件進行各類限制,但FileUpload組件不能進行文件下載操做。
版權方受權希賽網發佈,侵權必究
第 8 章:JSP數據庫開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
JDBC概述
第8章 JSP數據庫開發
【本章專家知識導學】
在應用系統中將數據存入數據庫中最大的好處是能利用開發技術(如:JSP、ASP、PHP和Perl)對數據做出分析,並按照不一樣的需求而呈現出不一樣的內容。例如:許多網站所提供的個性化服務,搜索引擎,在線訂票應用等皆以數據庫做爲後端架構衍生出來的應用。
本章主要探討JDBC的架構與運做方式,讓讀者對JDBC有完整的基礎概念後,可以快速上手JSP與數據庫的運用,並介紹了一些數據庫操做時經常使用的技術,如使用存儲過程、使用事務處理等。
8.1 JDBC概述
JDBC(Java Database Connectivity)是Sun提供的一套數據庫編程標準API接口,由Java語言編寫的類、接口組成,其體系結構如圖8-1所示。

圖8-1 JDBC體系結構圖
用JDBC寫的程序可以自動地將SQL語句傳送給相應的數據庫管理系統。不但如此,使用Java編寫的應用程序能夠在任何支持Java的平臺上運行,沒必要在不一樣的平臺上編寫不一樣的應用。Java和JDBC的結合可讓開發人員在開發數據庫應用程序時真正實現「一次編寫,處處運行!」
鏈接數據庫有四種鏈接方式。第一種就是ODBC(Open Database Connection 開放式數據庫鏈接)橋鏈接:ODBC橋鏈接是經過操做系統裏面的數據源鏈接到各類不一樣的數據庫。絕大多數數據庫都支持操做系統裏面的數據源。也提供了相應的驅動程序。包括:SQL Server 2000,Oracle9i等等。在JAVA剛開始的時候,SUN公司提供了用於ODBC橋鏈接的驅動程序JDBC-ODBC橋驅動程序,它把JDBC的調用轉換爲ODBC操做。這個橋使得全部支持ODBC的DBMS均可以和Java應用程序交互,但僅適用於Windows平臺,適用於JDBC初學者。

圖8-2 JDBC-ODBC體系結構圖
第二種驅動程序也稱爲部分Java驅動程序(native-API partly-Java Driver),由於它們直接將JDBC API翻譯成具體數據庫的API。也就是本地庫Java驅動程序,將JDBC調用轉換爲對數據庫的客戶端API的調用。

圖8-3 JDBC本地驅動體系結構圖
第三種驅動程序是網絡驅動程序(net-protocol all-java driver(JDBC Proxy)),它將JDBC API轉換成獨立於數據庫的協議。JDBC驅動程序並無直接和數據庫進行通信;它和一箇中間件服務器通信,而後這個中間件服務器和數據庫進行通信。這種額外的中間層次提供了靈活性:能夠用相同的代碼訪問不一樣的數據庫,由於中間件服務器隱藏了Java應用程序的細節。

圖8-4 JDBC網絡驅動程序體系結構圖
第四種驅動程序是純Java驅動程序(native-protocal all-Java driver),它直接與數據庫進行通信。不少程序員認爲這是最好的驅動程序,由於它一般提供了最佳的性能,並容許開發者利用特定數據庫的功能。固然,這種緊密偶合會影響靈活性,特別是若是您須要改變應用程序中的底層數據庫時。這種驅動程序一般用於applet和其它高度分佈的應用程序。適用於企業應用,如圖8-5所示。

圖8-5 JDBC純Java驅動程序體系結構圖
版權方受權希賽網發佈,侵權必究
第 8 章:JSP數據庫開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
Java編程語言和JDBC
編寫正確且遵照規範的Java程序,能夠無需從新編譯就在任何啓用Java技術的平臺上運行。Java編程語言完全地進行了規定。根據定義,啓用Java技術的平臺必須支持已知的核心庫。就java.sql包或javax.sql包或者JDBC就是這樣一個庫,它們能夠視爲ODBC的可移植版本,且其自己就是重大的標準。Java編程語言和JDBC一塊兒使用,能夠給編寫數據庫應用程序提供正確的可移植性解決方案。JDBC驅動程序就是JAVA類,它實現JDBC驅動程序接口,並能夠爲特別的數據庫轉換程序(通常是SQL)請求。無疑,驅動程序在這裏起了重要做用。大多數的數據庫供應商如今都提供驅動程序,以實現特定系統的JDBC API,這些驅動程序一般都是免費提供的。JDBC編程的核心包爲java.sql包,其結構如圖8-6所示。

圖8-6 java.sql包結構圖
版權方受權希賽網發佈,侵權必究
第 8 章:JSP數據庫開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月04日
JDBC編程的步驟
第一步:加載驅動程序。
爲了與特定的數據庫相連,JDBC必須加載相應的驅動程序。如:
try {
//加載JDBC-ODBC驅動
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
如下是加載各類不一樣的數據庫驅動程序的方法:
//SQL Server
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
//MySQL
Class.forName("org.gjt.mm.mysql.Driver");
//Oracle
Class.forName("Oracle.jdbc.driver.OracleDriver");
//Informix
Class.forName("com.informix.jdbc.IfxDriver");
//Sybase
Class.forName("com.sybase.jdbc2.jdbc.SybDriver");
//AS400
Class.forName("com.ibm.as400.access.AS400JDBCConnection");
第二步:將「驅動程序」傳遞到DriverManager,而後得到「鏈接」。
DriverManager類的getConnection(String url,String user, String password)方法用於創建與某個數據庫的鏈接。每一個JDBC驅動程序使用一個專門的JDBC URL做爲自我標識的一種方法。
JDBC URL的格式爲:jdbc : <子協議名> : <子名稱>
子協議(sub-protocol)與JDBC驅動程序有關,能夠是odbc,oracle,db2,mysql,microsoft等等,根據實際的JDBC驅動程序廠商而不一樣。子名稱(數據庫定位器)是與驅動程序有關的指示器,用於惟一指定應用程序要和哪一個數據庫進行交互。根據驅動程序的類型,該定位器可能包括主機名,端口和數據庫系統名。如下是鏈接語句示例:
try{
String url="jdbc:odbc:myodbc";
Connection con=DriverManager.getConnection(url);
// 或者
/*Connection con=DriverManager.getConnection(url,user,password);
}catch(SQLException e){
e.printStackTrace();
如下是鏈接各類不一樣的數據庫的URL編寫方法:
//SQL Server
DriverManager.("jdbc:microsoft:sqlserver://主機:端口號; DatabaseName=數據庫名","用戶名","密碼")
//MySQL
DriverManager.getConnection("jdbc:mysql://主機:端口號:數據庫名","用戶名","密碼")
//Oracle
DriverManager.getConnection("jdbc:Orcale:thin:@主機:端口號:數據庫名","用戶名","密碼")
//Informix
DriverManager.getConnection("jdbc:informix-sqli://主機:端口號/數據庫名:
INFORMIXSERVER=informix服務名","用戶名","密碼")
//Sybase
DriverManager.getConnection("jdbc:sybase:Tds:主機:端口號/數據庫名","用戶名","密碼")
//AS400
DriverManager.getConnection("jdbc:as400://主機」,"用戶名","密碼")}
第三步:建立語句,Statement ,PreparedStatement,或CallableStatement,並將它們用於更新數據庫或執行查詢。
Statement 對象用於將SQL語句發送到數據庫中。實際上有三種Statement對象,它們均可以做爲在給定鏈接上執行SQL語句的對象:Statement、PreparedStatement( 繼承Statement )和 CallableStatement(繼承PreparedStatement)。它們都專用於發送特定類型的 SQL 語句:Statement 對象用於執行不帶參數的簡單 SQL語句;PreparedStatement 對象用於執行帶或不帶 IN 參數的預編譯 SQL 語句;CallableStatement對象用於執行對數據庫已存儲過程的調用。
第四步:查詢並返回包含有已請求數據的ResultSet,該ResultSet是按類型檢索的。
ResultSet包含符合SQL語句中條件的全部行,而且它經過一套get方法(這些get方法能夠訪問當前行中的不一樣列)提供了對這些行中數據的訪問。DatabaseMetaData和ResultSetMetaData接口能夠用來提供有關數據庫或ResultSet的信息。
第五步:顯示數據或根據獲得的查詢結果完成業務邏輯處理。
第六步:最後關閉ResultSet(結果集)、Statement(語句對象)、Conection(數據庫鏈接)。
【例8-1】經過ODBC創建與數據庫的鏈接
配置Windows下ODBC詳細步驟以下(以配置鏈接SQL Server 2000的pubs數據庫爲例):
(1)啓動SQL Server 2000數據庫。
從控制面板裏面找到數據源,如圖8-7所示。

圖8-7 準備建立ODBC數據源
打開數據源,創建鏈接SQLServer的數據源,建立界面如圖8-8所示。

圖8-8 建立ODBC數據源
選擇系統DSN,點擊 按鈕。出現圖8-9的界面,選擇「SQL Server」點擊完成,出現圖8-10的界面。

圖8-9 建立ODBC數據源

圖8-10 建立ODBC數據源
輸入數據源的名字,如:myodbc。在服務器裏面加個點,表示用本地機器上的SQL Server數據庫服務器。點擊下一步,顯示圖8-11所示的對話框。

圖8-11 建立ODBC數據源
選擇 ,輸入登錄數據庫使用的用戶名和密碼。這裏的用戶名和密碼是SQLServer裏面可用的用戶名和密碼。點擊下一步,顯示圖8-12所示的對話框。

圖8-12 建立ODBC數據源
選擇要訪問的數據庫,這點選擇pubs,點擊下一步,顯示圖8-13所示的對話框。

圖8-13 建立ODBC數據源
點擊完成,顯示圖 8-14所示的對話框。

圖8-14 建立ODBC數據源
測試數據源若是出現圖 8-15,說明數據源已經建立成功。

圖8-15 建立ODBC數據源
建立Web應用並編寫odbc_connection.jsp頁面,代碼以下。
odbc_connection.jsp
<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ page import="java.sql.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>經過ODBC創建鏈接</title>
</head>
<body>
<%
Connection con = null;
try {
// 加載ODBC驅動
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
// 經過驅動管理器(DriverManager)得到鏈接
con = DriverManager.getConnection("jdbc:odbc:myodbc",
"sa","");
// 若是鏈接不成功,就會出現異常,不會執行下面這個語句
out.println("<H1>");
out.println("經過ODBC數據源鏈接數據庫成功!");
out.println("</H1>");
} catch (Exception e) {// 若是出現異常,會打印堆棧裏異常的信息
e.printStackTrace();
} finally {// 用完後,關閉鏈接,釋放資源
try {
if (con != null) // 防止出現內存泄露
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
%>
</body>
</html>
運行結顯示如圖8-16所示。

圖8-16 odbc_connection.jsp運行結果
【例8-2】經過SQLServer提供的驅動程序得到鏈接
SQL Server的驅動程序須要用到三個jar文件,它們分別爲:msbase.jar、mssqlserver.jar、msutil.jar,而後設置classpath環境變量指向這三個路徑。若是隻是當前Web應用須要使用,能夠將這三個jar文件拷貝到當前Web應用的「WEB-INF/lib」目錄下。
sqlserver_connection.jsp
<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ page import="java.sql.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>經過Sqlserver純驅動程序創建鏈接</title>
</head>
<body>
<%
Connection con = null;
try {
// 加載SQLSERVER的驅動程序
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
// 經過驅動來得到一個鏈接
con = DriverManager.getConnection(
"jdbc:microsoft:sqlserver://localhost:1433;"
+ "databasename=pubs", "sa", "");
// 若是鏈接不成功,就會出現異常,不會執行下面這個語句
out.println("<H1>");
out.println("經過SQLServer純驅動程序鏈接數據庫成功!<br> con="+con);
out.println("</H1>");
} catch (Exception e) {// 若是出現異常,會打印堆棧裏異常的信息
e.printStackTrace();
} finally {// 用完後,關閉鏈接,釋放資源
try {
if (con != null) // 防止出現內存泄露
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
%>
</body>
</html>
運行結果顯示如圖 8-18所示。

圖8-18 SQLServer純Java驅動鏈接數據庫運行結果
【例8-3】經過Oracle提供的驅動程序得到鏈接
下面介紹如何經過Oracle提供的驅動程序得到鏈接。須要使用的只有一個jar文件:classes12.jar。設置環境變量classpath 指向該jar文件。若是隻是當前Web應用須要使用,能夠將這個jar文件拷貝到當前Web應用的「WEB-INF/lib」目錄下。
oracle_connection.jsp
<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ page import="java.sql.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>經過oracle純驅動程序創建鏈接</title>
</head>
<body>
<%
Connection con = null;
try {
// 加載ORACLE9i的驅動程序
Class.forName("oracle.jdbc.driver.OracleDriver");
// 得到鏈接 oracle數據庫的端口號:1521 數據服務器的名字叫ora921
// 登錄的用戶名爲system,密碼爲:itjob (默認密碼爲manager)
con = DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521:ora921", "system","itjob");
// 若是鏈接不成功,就會出現異常,不會執行下面這個語句
out.println("<H1>");
out.println("經過ora921純驅動程序鏈接數據庫成功!<br> con="+con);
out.println("</H1>");
} catch (Exception e) {// 若是出現異常,會打印堆棧裏異常的信息
e.printStackTrace();
} finally {// 用完後,關閉鏈接,釋放資源
try {
if (con != null) // 防止出現內存泄露
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
%>
</body>
</html>
運行結果顯示如圖 8-19所示。

圖8-19 Oracle純Java驅動鏈接數據庫運行結果
【專家提示】Oracle數據庫純Java驅動包並隨安裝Oracle數據庫或客戶端一同安裝,讀者能夠從〔Oracle安裝目錄〕\ jdbc\lib下找到相應的驅動包。
【專家提示】細心的讀者會發現咱們在演示這個例子時瀏覽器的URL顯示爲:
http://localhost:8088/jdbcdemo/oracle_connection.jsp
顯然咱們將Tomcat的默認HTTP端口8080改成8088了,這是由於咱們在本機啓動了Oracle數據庫服務佔用了8080端口。讀者能夠經過運行netstat –a –b –o命令來查看機器端口占用狀況,如圖 8-20所示。

圖8-20 本機端口被佔用狀況
能夠看到8080端口被Oracle數據庫的監聽服務進程TNSLSNR.exe進程所佔用。
【例8-4】經過鏈接池得到鏈接
首先請讀者根據在上面建立數據庫鏈接的經驗,來思考下列問題:
爲何須要鏈接池?
什麼是鏈接池?
如何初始化鏈接池?
如何使用鏈接池?
當使用DriverManager方法來獲取數據庫鏈接時,每一個對新數據庫鏈接的請求都會致使很大的開銷。若是頻繁地獲取新的鏈接,將會影響性能問題。這在Web服務器端編程的時候尤其明顯。請求一個新的Connection對象會帶來大量的開銷和不少潛在的錯誤。爲了最小化開銷,爲何在咱們使用完數據庫鏈接後不是從新使用它們,而是刪除它們呢?JDBC設計者在建立接口ConnectionPoolDataSource時使用這種流行的設計模式,這容許您建立數據庫鏈接池,其中的鏈接在關閉後能夠重用,而不是刪除。
PooledConnection是一個特殊類型的數據庫鏈接,在關閉時不會被刪除,不象常規的Connection對象(當常規的鏈接再也不被使用時,垃圾收集器能刪除它們)。相反,PooledConnection被緩存以備未來再次使用,從而可能帶來大幅度的性能提高。
配置Tomcat5數據庫鏈接池
目前幾乎全部的應用服務器都支持數據庫鏈接池的建立和管理,接下來咱們將具體演示Tomcat中SQLServer數據庫鏈接池的建立和管理步驟。
首先在你要使用鏈接池的Web應用的META-INF目錄下建立一個context.xml文件,如圖8-21所示。

圖8-21 建立一個context.xml文件
啓動Tomcat5後進入Tomcat歡迎頁面,如圖8-21所示。

圖8-22 Tomcat歡迎頁面
點擊「Tomcat Administration」進入Tomcat的管理員登陸頁面,如圖8-22所示。

圖8-23 Tomcat管理員登陸頁面
輸入用戶名 admin 密碼 (安裝時指定若是忘記了能夠打開{Tomcat安裝目錄}\conf\ tomcat-users.xml文件查看)後點擊Login按鈕進入管理配置頁面如圖8-23所示。

圖8-24 Tomcat管理配置頁面
選擇jdbcdemo web應用程序下的Data Sources選擇Create New Data Source建立一個新的數據源,如圖 8-24所示。

圖8-25 Tomcat數據鏈接池管理配置頁面
填寫以下參數:
JNDI Name:jdbc/sqlserver(未來以此來查找數據庫鏈接池)。
Data Source URL(數據源URL):
jdbc:microsoft:sqlserver://localhost:1433;databasename=pubs
User Name:sa
Vaildation Query:select 1
而後點擊Save按鈕保存數據庫鏈接池的設置,如圖 8-25所示。

圖8-26 Tomcat數據鏈接池管理配置頁面
點擊「Commit Changes」按鈕向服務器提交設置。

圖8-27 Tomcat數據鏈接池管理配置頁面
點擊肯定按鈕完成配置
pool_connection.jsp
<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ page import="java.sql.*,javax.naming.*,javax.sql.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>經過數據庫鏈接池創建鏈接</title>
</head>
<body>
<%
Connection con = null;
try {
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/sqlserver");
con = ds.getConnection();
out.println("<H1>");
out.println("第一次經過數據庫鏈接池鏈接數據庫成功!<br> con="+con);
out.println("</H1>");
con.close();
con = ds.getConnection();
out.println("<H1>");
out.println("第二次經過數據庫鏈接池鏈接數據庫成功!<br> con="+con);
out.println("</H1>");
con.close();
} catch (Exception e) {// 若是出現異常,會打印堆棧裏異常的信息
e.printStackTrace();
}
%>
%>
</body>
</html>
運行結果,顯示如圖 8-28所示。

圖8-28 pool_connection.jsp頁面運行顯示結果
從運行顯示結果來看咱們兩次取得的數據庫鏈接對象爲同一個對象。
【專家提示】請讀者注意因爲鏈接池對象是在構建Web應用時由容器建立並管理的,此時Web應用並無開始被加載。若是採用Java純驅動來鏈接數據庫的驅動程序包應由原來放在「WEB-INF/lib」目錄移到「{Tomcat安裝目}/shared/lib」目錄下,不然會拋出找不到相應驅動程序包而產生異常。
第9章 XML操做
【本章專家知識導學】
XML(eXtensible Markup Language,可擴展的標記語言)是一種在Internet上被普遍應用的標記語言,它將SGML的豐富功能與HTML的易用性結合到Web的應用中,經常使用來做爲各類網絡應用系統的數據交換報文、描述系統配置參數文件等。
操做XML文件的開源軟件接口包括DOM 、SAX、JDOM等,程序員須要熟悉並掌握這些經常使用的API接口的使用,可以經過這些接口來編寫Java語句來實現對XML文件的處理。
本章將在介紹XML、DTD等基礎知識後,詳細解說DOM 、SAX、JDOM對XML文件的處理方法。
9.1 XML概述
XML便可擴展的標記語言,能夠定義語義標記,是元標記語言。XML不像HTML(Hyper Text Markup Language,超文本標記語言),HTML只能使用規定的標記,不能擴展;而對於XML用戶則能夠定義本身所須要的標記。XML和HTML師出同門,都是從SGML(Standard Generalized Markup Language)延伸發展而來的標記語言。
XML是一個精簡的SGML,它將SGML的豐富功能與HTML的易用性結合起來。XML保留了SGML的可擴展功能,這使XML從根本上有別於HTML。XML要比HTML強大得多,它再也不是固定的標記,而是容許定義數量不限的標誌來描述文件中的資料,容許嵌套的信息結構。HTML只是Web頁面用來顯示數據的通用方法,而XML提供了一個直接處理Web數據的通用方法。HTML着重描述Web頁面的顯示格式,而XML着重描述的是Web頁面的內容的結構。
XML正被愈來愈普遍地應用,它能夠用來表示數據和數據結構;能夠用來定義數據規範;在企業間交換數據時做爲信息的載體——XML報文等。XML已成爲Internet中不可缺乏的技術,JSP做爲Web編程的語言就有可能須要處理XML文件。
程序員能夠自行編寫Java程序操做XML文件,操做時能夠使用DOM、SAX、JDOM等流行的開源軟件接口操做XML文件。然而,在JSP頁面中插入處理XML文件的Java代碼將使得JSP頁面代碼冗長、邏輯複雜。
因爲超文本標記語言HTML的簡單易學、句法簡明緊湊等優勢,使得它在Web主頁上大顯身手。HTML只是提供了在網絡上數據顯示方式的通用方法,它不描述數據間的邏輯結構。可擴展標記語言XML(Extensible Markup Language)從不一樣角度解決了HTML存在的問題。XML同HTML同樣是一種標記語言,它們都來自於標準通用標記語言SGML。可是XML提供了一個描述數據邏輯結構和交換數據的有效手段,顯示方式提交給樣式表來處理,這是它與HTML的最大區別。
總而言之,XML 是一種元標記語言,該語言提供一種描述結構數據的格式。這有助於更精確地聲明內容,方便跨越多種平臺的更有意義的搜索結果。此外,XML 將起用新一代的基於 Web 的數據查詢和處理應用程序。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
編寫XML
XML文件的編輯能夠使用一些基本的文本編輯器進行,如記事本、寫字板等。固然,若是使用所見即所得的編輯器就更方便了,如XML.Spy。在編寫好代碼後將文件另存爲後綴名爲xml的文件。在任何支持XML的瀏覽器中打開XML文件(或直接雙擊文件)便可看到顯示結果。一個完整的XML文件通常有三個部分構成:XML版本說明、文件類型定義和文件主體,下面看一個簡單的XML文件結構的例子。
【例9-1】一個簡單的XML文件示例
links.xml
<?xml version="1.0" encoding="gb2312"?>
<links>
<link>
<text>JSP Insider</text>
<url newWindow="no">http://www.jspinsider.com</url>
<author>周雄偉</author>
<date>
<day>16</day>
<month>6</month>
<year>2007</year>
</date>
<description>A JSP information site.</description>
</link>
<link>
<text>The makers of Java</text>
<url newWindow="no">http://java.sun.com</url>
<author>Sun Microsystems</author>
<date>
<day>17</day>
<month>6</month>
<year>2007</year>
</date>
<description>Sun Microsystem's website.</description>
</link>
<link>
<text>The standard JSP container</text>
<url newWindow="no">http://jakarta.apache.org</url>
<author>Apache Group</author>
<date>
<day>18</day>
<month>6</month>
<year>2007</year>
</date>
<description>Some great software.</description>
</link>
</links>
該文件用來保存用戶數據,雙擊links.xml文件,該文件在IE瀏覽器中的顯示效果如圖9-1所示。

圖9-1 一個簡單的XML文件示例運行效果圖
文件的第一行以下:
<?xml version="1.0" encoding="gb2312"?>
這是XML 處理指令聲明的第一句,即XML版本說明,它以「<?」開始,以「?>」結束。每一個XML文件都是從一個XML版本說明開始,其做用是告訴瀏覽器或者其它處理程序:這個文件是XML文件。XML版本信息說明格式以下:
<?xml version="版本號" standalone="yes/no" encoding="UTF-8"?>
其中:
version:表示文件遵照的XML規範的版本,在本例中的version 是1.0;
standalone:表示文件內部包含文件類型定義DTD。若是無,參數爲no,默認值爲no;
encoding:表示文件所用的字符編碼,通常是UTF-8或UTF-16,默認UTF-8。若是但願XML文件中能夠使用中文標誌和處理中文字符,必須說明爲gb2312。
【專家提示】<? xml version=…?> 必須是文件的第一行,而且前面不能有空格。
例子中接下來的語句是XML文件主體。XML文件類型定義了文件的邏輯結構,與XML文件類型對應的數據叫XML文件的主體,也簡稱爲XML文件。XML文件主體部分是由XML元素屬性值組成的。一個XML 元素由一個起始標記、一個結束標記,以及夾在這兩個標記之間的數據內容所組成,它用於標識XML文件元素的屬性值。其基本形式以下:
<標記名> 數據內容 </標記名>
其中文件根元素則是一個能夠包含多個嵌套子元素的頂層元素。在例9-1中<links>和 </links>就是根元素,它包含了另外的四個元素。
在XML文件中,標記大小寫是有區別的,而且必須配對使用。<P>和<p>是不一樣的標誌。在定義元素時,先後標誌大小寫要保持同樣。例如<author>張馳</author>,寫成<Author>張馳</author>是錯誤的。
【專家提示】XML是爲了便於閱讀和理解而在XML文件中附加的信息,它們將不會被掃描程序解釋或瀏覽器顯示。註釋的語法格式與HTML中的同樣。
【專家提示】一個XML 元素的下一級節點能夠用「標記名=數據內容」這種「name=value」鍵值對的方式表示。如例子中的第一個date節點能夠表示爲:
……..
<link day="16" month="6" year="2007">
</link>
…….
XML文件的類型定義簡稱DTD(Document Type Describtion,文檔類型描述),它指明瞭文件主體必須符合的規範。例子中沒有DTD,這部分的知識在將下一節中講述。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
DTD
XML文件的類型定義簡稱DTD,它指明瞭文件主體必須符合的規範。在一個DTD中,具體規定了引用該DTD的XML文件可以使用哪些標記、父元素中可以包括哪些子元素、各個元素出現的前後順序、元素可包含的屬性、元素和屬性值的數據類型,以及可以使用的實體及符號規則等。
DTD能夠在XML文件內部直接定義,也能夠是一個徹底獨立的文件。DTD由許多約定和聲明語句構成,這些語句能夠包含在XML文件內部,被稱爲內部DTD;也能夠獨立保存爲一個文件,而稱爲外部DTD,此時,在XML文件使用到它時只要直接引用它就能夠了。
DTD主要具備下列幾方面的做用:
(1)能夠驗證XML 文件數據的有效性。
(2)能夠爲某類XML文件提供統一的格式和相同的結構。
(3)能夠保證在必定範圍內,XML 文件數據的交流和共享。
(4)應用程序設計人員根據DTD 就可以知道對應XML 文件的邏輯結構,從而編寫出相應的處理應用程序。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
DTD的基本結構
在一份DTD 中,包含了對XML 文件所使用的元素、元素間的關係、元素可用的屬性、可以使用的實體等的定義規則。一份DTD 其實是若干條有關元素、屬性、實體等定義和聲明語句的集合。
例9-1中links.xml文件中的XML文件的類型定義DTD能夠是以下的內容:
<? DOCTYPE links[
<!ELEMENT link(text,URL,athuor,date)>
<!ELEMENT text(#PCDATA)>
<!ELEMENT URL(#PCDATA)>
<!ELEMENT athuor(#PCDATA)>
<!ELEMENT date(#PCDATA)>
<!ELEMENTdater(day,month,year)
<!ELEMENT day(#PCDATA)>
<!ELEMENT month(#PCDATA)>
<!ELEMENT year(#PCDATA)>
]>
在DTD中能夠包含下列各類聲明語句:
(1)DTD 聲明開始語句。
(2)元素類型聲明語句。
(3)屬性列表聲明語句。
(4)實體聲明語句。
(5)註釋語句。
下面對這些內容進行簡單的說明。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
DTD聲明與引用
DTD的聲明根據使用狀況的不一樣,通常能夠份內部DTD、外部DTD和混合DTD的引用。
(1)引用內部DTD
DTD的聲明語法格式以下:
<!DOCTYPE 根元素名稱 [DTD聲明語句序列]>
其中:
「<!DOCTYPE」表示DTD聲明的開始,關鍵字DOCTYPE必須大寫。
根元素名稱是指定XML文件的根元素名稱,這個根元素名稱必須精確地與文件中實際的根元素名稱一致。
DTD聲明語句序列是指包含在一對方括號([ ])以內的若干條語句,用來對XML文件中所使用的元素、屬性和實體等進行具體聲明。
【專家提示】在XML文件中引用內部DTD時,應該在文件開頭的XML聲明語句中添加standalone="yes" 的說明。
(2)引用外部DTD
引用外部DTD首先要建立外部DTD。外部DTD 是一個獨立於XML 文件的文件,使用.dtd爲其文件擴展名。此種文件實際上也是一個文本文件,可用任何文本編輯器建立。在外部DTD 中,除了沒有內部DTD 中的「<!DOCTYPE 根元素名稱」 語句以外,其餘聲明語句都是同樣的。
根據外部DTD性質的不一樣,又可將其分爲私有DTD文件和公共DTD文件。私有DTD文件是指並未公開的DTD文件,一般屬於某個組織內部或我的全部;公共DTD文件則是爲某一應用領域或行業所制定,被國際上的標準組織或行業組織普遍承認的、公開的、標準的DTD文件。
引用私有DTD文件的語法格式爲:
<!DOCTYPE根元素名稱SYSTEM DTD的URL>
引用公共DTD文件的語法格式爲:
<!DOCTYPE根元素名稱PUBLIC DTD名 DTD的URL>
【專家提示】在XML文件中引用外部DTD時,應該在開頭的XML聲明語句中添加standalone="no" 說明。
(3)混合引用DTD
混合引用DTD是指在一個帶有內部DTD的XML文件中,再引用一個或多個外部DTD來共同規範文件中的內容。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
DTD對元素的聲明
元素聲明的語法格式:
<!ELEMENT element_name element_definition>
其中:<!ELEMENT: 元素聲明語句的開始,關鍵字ELEMENT必須大寫。
element_name: 所聲明的元素名稱。
element_definition:對該元素內容的定義,用來規定該元素能夠包含的內容。
【專家提示】靈活控制元素出現次數以及元素的分組與嵌套。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
DTD對屬性的聲明
DTD屬性聲明的語法:
<! ATTLIST Element_Name
Attribute_Name Type [added_declare]
Attribute_Name Type [added_declare]
……
>
其中:
<!ATTLIST:表示屬性定義語句的開始,ATTLIST是關鍵字,必須大寫。
Element_Name:元素名,用來指定對該元素的屬性進行聲明。
Attribute_Name:該元素具備的某個屬性名,屬性的命名規則與元素的命名規則是一致的。
Type:屬性的數據類型。
added_declare:屬性的附加聲明,是一個可選項。
對於DTD屬性聲明的內容比較多,使用也不是不少,對這一部分感興趣的讀者能夠參考有關XML的專門書籍。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
實體的聲明與引用
在XML規格中,實體(Entity)具備普遍的含義,一般是指有效的XML文件自己、外部的DTD子集、定義成DTD中外部實體的外部文件或在DTD中定義的用引號括起來的字符串等與XM 文件相關的儲存單元。XML的實體都有一個名稱,用這個名稱來代替這些數據。
XML有兩種類型的實體。一種是在XML文件中使用的實體;另外一種是參數實體,只在DTD文件中使用。
在DTD文件中使用的實體的定義格式爲:
<!ENTITY [%] Entity_Name Entity_Value >或
<!ENTITY [%] Entity_Name SYSTEM Entity_URL>
其中:
<!ENTITY :表示開始聲明一個實體,關鍵字ENTITY必須大寫。
[%]:[]表示可選項,%表示聲明的是一個參數實體。
Entity_Name :表示內部參數實體的名稱。
Entity_Value :表示實體的內容。
SYSTEM :是定義爲外部實體的關鍵字。
Entity_URL :外部實體文件的URL。
已定義的實體在文件中的引用格式爲:&實體名;
例如定義版權信息的實體:
<!DOCTYPE copyright [<!ENTITY copyright "版權全部 全部人:周雄偉">]>
若是版權信息內容和他人共享一個XML文件,也能夠外部引用它,外部引用格式實體爲©right。
【例9-2】帶實體元素的XML文件示例
entity.xml
<?xml version="1.0" encoding="GB2312"?>
<!DOCTYPE copyright [<!ENTITY copyright "版權全部 全部人:周雄偉">]>
<myfile>
<title>lucene開發設計</title>
<author>周雄偉等</author>
<email> daweycs@163.com</email>
<date>20020715</date>
©right;
</myfile>
帶實體元素的XML文件示例entity.xml文件在IE中顯示如圖9-2所示。

圖9-2 帶實體元素的XML文件示例運行效果圖
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
命名空間(Namespaces)
XML中標誌都是用戶建立的,在不一樣的DTD文件中,有可能出現含義不一樣但名稱相同的標誌。當在一個XML文件中使用多個DTD文件時,就有可能出現標誌同名的矛盾,這會引發數據混亂。
例以下面的文件表示桌子:
<table>wood table</table>
下面這一個文件卻表示表格:
<table>namelist</table>
若是須要同時處理這兩個文件,就會發生名字衝突。
Namespaces實際上就是名字空間。引進了Namespaces這個概念就能解決這個問題。Namespaces經過給標誌名稱加一個Namespaces名(URL)定位以區別這些名稱相同的標誌。
Namespaces名一樣須要在XML文件的開頭部分說明,說明的格式以下:
<document xmlns:yourname='URL'>
其中yourname是定義的Namespaces的名稱,URL就是名字空間的網址。
假設上面的"桌子<table>"文件來自http://www.zhuozi.com,能夠說明爲
<document xmlns:itsname='http://www.zhuozi.com'>
而後在後面的標誌中使用定義好的名字空間:
<itsname :table>wood table</table>
這樣就將這兩個<table>區分開來。
【專家提示】設置URL並非說這個標誌真的要到那個網址去讀取,僅僅做爲一種區別的標誌而已。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
DOM
在Java中對XML的解析接口經常使用的有3大類:基於DOM(Document Object Model)的解析接口、基於SAX(Simple API for XML)的解析接口和基於JDOM(Java Document Object Model)技術的解析接口。解析器實際上就是一段代碼,它讀入一個XML文件並分析其結構。目前主流的解析器有:JAXP(Java API for XML Processing)、Xerces(Apache)、XML4J(IBM)和xalan等,主流的解析器都支持SAX和DOM。支持JDOM的解析器目前只有SUN公司發佈的jdom包。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
DOM的類
DOM即文件對象模型。在應用程序中,基於DOM的XML分析器將一個XML文件轉換成了一個對象模型的集合(這個集合一般被稱爲DOM樹),應用程序能夠經過對該對象模型的操做,實現對XML文件中數據的操做。
(1)Document類
Document類描述了整個XML的文件語法結構,它包含了一系列Node類造成的樹形結構。程序員能夠先掃描XML源文件,獲得相應的Document對象,遍歷這顆樹來獲得XML文件的全部內容,這是對XML文件操做的起點。而後再繼續其餘對XML文件的操做。
Document類包含了建立相關類對象的方法,主要有:
createAttribute(String):用給定的屬性名建立一個Attribute對象.,而後可以使用setAttributeNode方法將其放置在一個Element對象上面。
createElement(String):用給定的參數建立一個Element對象,表明XML文件中的一個標誌,而後能夠在這個Element對象上添加屬性或進行其它操做。
createTextNode(String):用給定的字符串建立一個Text對象,Text對象表明了標誌或者屬性中所包含的純文本字符串。若是在一個標誌內沒有其它的標誌,那麼標誌內的文本所表明的Text對象是這個Element對象的惟一子對象。
getElementsByTagName(String):返回特定標誌元素的NodeList對象。
getDocumentElement():返回一個表明DOM根節點的Element對象,也就是表明XML文件根元素的那個對象。
(2)Node對象
Node類是DOM結構中最爲基本的類,它描述了文件樹中的一個抽象的節點。它包含類型爲Element、Attr、Text和其餘類的特徵。Node對象引用的其成員變量來操做XML文件。Node包含的主要方法有:
appendChild(org.w3c.dom.Node):爲這個節點添加一個子節點,並放在全部子節點的最後,若是這個子節點已經存在,則先把它刪掉再添加進去。
getFirstChild():若是節點存在子節點,則返回第一個子節點,對等的,還有getLastChild()方法返回最後一個子節點。
getNextSibling():返回DOM樹中這個節點的下一個兄弟節點,對等的,還有getPreviousSibling()方法返回其前一個兄弟節點。
getNodeName():根據節點的類型返回節點的名稱。
getNodeType():返回節點的類型。
getNodeValue():返回節點的值。
hasChildNodes():判斷是否是存在有子節點。
hasAttributes():判斷這個節點是否存在有屬性。
getOwnerDocument():返回節點所處的Document對象
insertBefore(org.w3c.dom.Node new,org.w3c.dom.Node ref):在給定的一個子對象前再插入一個子對象。
removeChild(org.w3c.dom.Node):刪除給定的子節點對象。
replaceChild(org.w3c.dom.Node new,org.w3c.dom.Node old):用一個新的Node對象代替給定的子節點對象。
(3) NodeList對象
NodeList對象,顧名思義,就是表明了一個包含了一個或者多個Node的列表。能夠經過下列方法得到列表中的元素:
getLength():返回列表的長度。
item(int):返回指定位置的Node對象。
(4) Element對象
Element類描述XML文件中的標誌元素,繼承於Node,亦是Node的最主要的子對象。在標誌中能夠包含有屬性,於是Element對象中有存取其屬性的方法,而任何Node中定義的方法,Element都繼承下來。Element對象所包含的主要方法有:
getElementsByTagName(String):返回一個NodeList對象,它包含了在這個標誌中其下的子孫節點中具備給定標誌名字的標誌。
getTagName():返回一個表明這個標誌名字的字符串。
getAttribute(String):返回標誌中給定屬性名稱的屬性的值。在這兒須要注意的是,由於XML文件中容許有實體屬性出現,而這個方法對這些實體屬性並不適用。這時候須要用getAttributeNodes()方法來獲得一個Attribute對象來進行進一步的操做。
getAttributeNode(String):返回一個表明給定屬性名稱的Attribute對象。
(5) Attribute對象
Attribute對象表明了某個標誌中的屬性。Attribute繼承Node,可是由於Attr其實是包含在Element中的,它不能被看做是Element的子對象。在DOM中Attributer並非DOM樹的一個節點,因此Node中的getparentNode(),getpreviousSibling()和getnextSibling()返回的都將是null。也就是說,Attribute是Element類的一部分,它並不做爲DOM樹中單獨的一個節點出現。這一點在使用的時候要同其它的Node子對象相區別。
DOM類在DOM中都是用接口描述語言IDL定義的,於是,DOM能夠映射到任何面向對象的語言,只要它實現了DOM所定義的接口就能夠了。許多公司和廠家提供了符合DOM規範的DOM接口和程序包。下面以微軟的DOM接口爲例,講述DOM的使用。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
DOM讀取XML文件
DOM讀取XML文件一般要用到如下五個基本的步驟:
(1)創建一個解析器工廠。
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
(2)以利用這個工廠來得到一個具體的解析器對象。
DocumentBuilder builder= factory.newDocumentBuilder();
(3)利用DocumentBuilder的parse()方法接受一個XML文件名做爲輸入參數,返回一個Document對象。Document對象表明了一個XML文件的樹模型。
Document doc=builder.parse("candidate.xml");
(4)使用Document對象的getElementsByTagName()方法,咱們能夠獲得一個NodeList對象,它是XML文件中的標籤元素列表,能夠使用NodeList對象的item()方法來獲得列表中的每個Node對象。
NodeList nl =doc.getElementsByTagName("PERSON");
Element node=(Element) nl.item(i);
(5)經過Node對象的getNodeValue()方法提取某個標籤內的內容。
node.getElementsByTagName("NAME").item(0).getFirstChild().getNodeValue()
下面咱們來看一個具體的DOM讀取XML文件的示例。
【例9-3】DOM讀取XML文件示例
本例將DOM讀取XML文件示例程序是對例9-1的links.xml文件的用戶數據讀取出來並用表格的方式在IE瀏覽器上顯示。源程序以下:
display.jsp
<%@ page contentType="text/html;charset=gb2312"%>
<%@page import="javax.xml.parsers.*,java.io.*,java.util.*, "%>
<%@page import=org.w3c.dom.*,org.apache.xml.serialize.* "%>
<html>
<head>
<title> DOM讀取XML文件示例</title>
</head>
<body>
<table border=1>
<!--輸出表頭-->
<tr >
<td>content</td>
<td>url</td>
<td>author</td>
<td>date</td>
<td>description</td>
</tr>
<%
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();//(1)
DocumentBuilder builder=factory.newDocumentBuilder();//(2)
Document doc=builder.parse("link.xml");//(3)
doc.normalize();
NodeList links =doc.getElementsByTagName("link");//(4)
<!--輸出數據-->
for (int i=0;i<links.getLength();i++){
Element link=(Element) links.item(i);//(4)
out.print("<tr>");
out.println("<td>"+link.getElementsByTagName("text").item(0).getFirstChild().getNodeValue()+"</td>");//(5)
out.println("<td>"+link.getElementsByTagName("url").item(0).getFirstChild().getNodeValue()+"</td>");//(5)
out.println("<td>"+link.getElementsByTagName("author").item(0).getFirstChild().getNodeValue()+"</td>");//(5)
Element linkdate=(Element) link.getElementsByTagName("date").item(0); //(4)
String day=linkdate.getElementsByTagName("day").item(0).getFirstChild().getNodeValue();//(5)
String month=linkdate.getElementsByTagName("month").item(0).getFirstChild().getNodeValue();
String year=linkdate.getElementsByTagName("year").item(0).getFirstChild().getNodeValue();
out.println("<td>"+day+"-"+month+"-"+year+"</td>");
out.println("<td>"+link.getElementsByTagName("description").item(0).getFirstChild().getNodeValue()+"</td>");//(5)
out.println();
}
%>
</table>
</body>
</html>
該程序基本上徹底遵循上面講到的DOM讀取XML文件五個基本的步驟(程序中有具體的註釋),只是第(4)、(5)部在反覆屢次使用,程序的基本原理很是簡單。其運行的結果如圖9-3所示。

圖9-3 DOM讀取XML文件示例運行結果圖
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
修改XML文件
修改XML文件就是在修改了DOM樹後從新寫入到XML文件中去的問題了。在修改XML文件一般會遇到兩個方面的問題:
(1)是在XML文件中增長記錄
在XML文件中增長記錄,首先要在DOM樹中增長一個節點元素,而後在這個節點上增長子節點元素,並給相應的葉節點賦值,最後把DOM樹保存到XML文件中。
(2)是在XML文件中修改節點的值。
修改XML文件中節點的值,先是讀入到DOM樹中,再遍歷DOM樹,在遍歷的過程當中找到相應的節點並修改其值,在把修改的DOM保存到XML文件中。
這裏咱們先看一個在XML文件中增長記錄的示例。
【例9-4】用DOM修改XML文件示例
該示例仍然用例9-1的應用環境,功能是對links.xml增長一條數據記錄。增長的數據記錄的XML內容以下:
<link>
<text>Wudong's Homepage</text>
<url newWindow="no">http://www.wudong.com</url>
<author>Wudong Liu</author>
<date>
<day>6</day>
<month>10</month>
<year>2006</year>
</date>
<description>A site from Wudong Liu,give u lots of suprise!!!</description>
</link>
具體程序實現的源代碼以下。
domchangxml.jsp
<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="javax.xml.parsers.*, javax.xml.transform.*,javax.xml.transform.dom.*"%>
<%@ page import="javax.xml.transform.stream.*,java.io.*,java.util.*, org.w3c.dom.*, org.apache.xml.serialize.* "%>
<html>
<head>
<title> DOM修改XML文件示例</title>
</head>
<body>
<% DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document doc=builder.parse("links.xml");
doc.normalize();
//---取得變量----
String text="Wudong's Homepage";
String url="www.wudong.com";
String author="Wudong Liu";
String discription="A site from Wudong Liu, give u lots of suprise!!!";
//建立一個link對象
Text textseg;
Element link=doc.createElement("link");
//XML文件中添加一個link項目的具體元素
Element linktext=doc.createElement("text");
textseg=doc.createTextNode(text);
linktext.appendChild(textseg);
link.appendChild(linktext);
Element linkurl=doc.createElement("url");
textseg=doc.createTextNode(url);
linkurl.appendChild(textseg);
link.appendChild(linkurl);
Element linkauthor=doc.createElement("author");
textseg=doc.createTextNode(author);
linkauthor.appendChild(textseg);
link.appendChild(linkauthor);
String day="6";
String month="10";
String year="2006";
Element linkdate=doc.createElement("date");
Element linkdateday=doc.createElement("day");
textseg=doc.createTextNode(day);
linkdateday.appendChild(textseg);
Element linkdatemonth=doc.createElement("month");
textseg=doc.createTextNode(month);
linkdatemonth.appendChild(textseg);
Element linkdateyear=doc.createElement("year");
textseg=doc.createTextNode(year);
linkdateyear.appendChild(textseg);
linkdate.appendChild(linkdateday);
linkdate.appendChild(linkdatemonth);
linkdate.appendChild(linkdateyear);
link.appendChild(linkdate);
Element linkdiscription=doc.createElement("description");
textseg=doc.createTextNode(discription);
linkdiscription.appendChild(textseg);
link.appendChild(linkdiscription);
//建立好的節點添加到DOM樹中
doc.getDocumentElement().appendChild(link);
//用XSLT把DOM樹輸出
TransformerFactory tFactory =TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("links.xml"));
Transformer transform(source, result);
%>
<table border=1>
<!--輸出表頭-->
<tr >
<td>content</td>
<td>url</td>
<td>author</td>
<td>date</td>
<td>description</td>
</tr>
<% //輸出顯示數據
NodeList links =doc.getElementsByTagName("link");
for (int i=0;i<links.getLength();i++){
link= (Element) links.item(i);
out.print("<tr>");
out.println("<td>"+link.getElementsByTagName("text").item(0).getFirstChild().getNodeValue()+"</td>");
out.println("<td>"+link.getElementsByTagName("url").item(0).getFirstChild().getNodeValue()+"</td>");
out.println("<td>"+link.getElementsByTagName("author").item(0).getFirstChild().getNodeValue()+"</td>");
linkdate=(Element) link.getElementsByTagName("date").item(0);
day=linkdate.getElementsByTagName("day").item(0).getFirstChild().getNodeValue();
month=linkdate.getElementsByTagName("month").item(0).getFirstChild().getNodeValue();
year=linkdate.getElementsByTagName("year").item(0).getFirstChild().getNodeValue();
out.println("<td>"+day+"-"+month+"-"+year+"</td>");
out.println("<td>"+link.getElementsByTagName("description").item(0).getFirstChild().getNodeValue()+"</td>");
out.println();
}
%>
</table>
</body>
</html>
該程序首先在DOM 樹中增長一條記錄,將DOM樹保存到links.xml文件中,而後再將DOM樹中的內容顯示出來,程序的流程很是清晰明瞭(與上面講到步驟的一致),但要注意各類方法,特別是把DOM樹輸出使用XSLT顯得特別簡單。程序的運行結果如圖9-4所示,與例9-3比較多了一條記錄數據。

圖9-4 DOM修改XML文件示例運行結果圖
程序的運行後,links.xml文件在IE中顯示如圖9-5所示。

圖9-5 程序的運行後links.xml文件在IE中顯示結果
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
SAX
SAX即XML簡單應用程序接口。SAX提供了一種對XML文件進行順序訪問的模式,這是一種快速讀寫XML數據的方式。當使用SAX分析器對XML文件進行分析時,會觸發一系列事件,並激活相應的事件處理函數,從而完成對XML文件的訪問,因此SAX接口也被稱做事件驅動接口。
SAX是一種輕量型的方法。在處理DOM的時候,須要讀入整個的XML文件,而後在內存中建立DOM樹,生成DOM樹上的每一個Node對象。
當文件比較小的時候,這不會形成什麼問題,可是一旦文件變大,處理DOM就會變得至關費時費力。特別是其對於內存的需求,將是成倍的增加,以致於在某些應用中使用DOM是一件很不經濟的事,一個較好的替代解決方法就是SAX。
XML不只規定了如何表示和顯示數據,還提供了標準的API供處理XML數據,這也就是咱們稱之爲智能數據或數據標準的緣由。
SAX(The Simple API for XML)是基於事件的XML分析API,功能比較簡單。 這一API是事件驅動的,又稱"順序訪問"協議。每當它看到一個新的XML標記(或遇到一個錯誤,或想告訴你什麼事時)就用一個SAX解析器註冊你的句柄,激活你的回調方法。
DOM 定義了分析程序應當顯露的標準命令集,使您可以在程序中訪問 HTML 和 XML 文件內容。支持 DOM 的 XML 分析程序取出 XML 文件中的數據,並經過一組能夠對它編程的對象來顯露它。DOM將一個XML文件轉換成你程序中的一個對象集合。而後你能夠任意處理對象模型。這一機制也稱爲"隨機訪問"協議,由於你能夠在任什麼時候間訪問數據的任何一部分,而後修改、刪除或插入新數據。 DOM的特色是功能強大,但分析時間長,佔用資源多。
SAX 提供了處理 XML 文件的快速、低內存的另外一種方法。在使用 DOM 分析 XML 文件時,它在內存中創建了完整的文件樹。相比而言,SAX 將遍歷文件,並將新元素的開始或結束等通知分析事件的調用應用程序。使用 SAX 的一個最佳功能是分析長文件。例如,用 SAX 分析器,應用程序能夠監視發生的事件,只將文件中必要的部分讀入內存。
在Tomcat5.5中已經安裝了SAX解析器,提供了SAX方式的API接口。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
SAX的類
SAX方式解析XML文件最重要的類就是ContentHandler,ContentHandler類的方法無須調用,它們就象一個事件監聽器,在解析XML文件的過程當中會自動觸發相應的事件來調用方法。此類的經常使用方法以下:
(1)startDocument()
當遇到文檔的開頭時調用這個方法,能夠在其中作一些預處理的工做。調用方法以下:
void startDocument()
(2)endDocument()
當文檔結束時會調用這個方法,能夠在其中作一些善後的工做。調用方法以下:
void endDocument()
(3)startElement()
當讀到一個標籤開始時,會觸發事件並調用這個方法。調用方法以下:
void startElement(String namespaceURI,String localName,String qName,Attributes atts)
其中,參數namespaceURI指的是名域,在本書的實例中無須用到,參數localName爲使用名域時的標籤名,若是不使用名域,此參數值均爲null。參數qName爲標籤名,參數atts是標籤的屬性集。
(4)endElement()
在遇到結束標籤時,會調用這個方法。調用方法以下:
void endElement(String namespaceURI,String localName,String qName)
其中,參數含義同startElement()。
(5)characters()
這個方法用來處理在XML文件中讀到的字符串,以及讀到的這個字符串在這個數組中的起始位置和長度,它的參數是一個字符數組,能夠很容易用String類的一個構造方法來得到這個字符串的String類:String charEncontered=new String(ch,start,length)。
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
SAX讀取XML文件
SAX解析器工做的過程至少包含3步。
(1)和DOM同樣,須要創建一個解析器工廠。
SAXParserFactory spf = SAXParserFactory.newInstance();
(2)建立一個解析器對象。
SAXParser saxParser = spf.newSAXParser();
(3)將解析器和XML文件聯繫起來,開始解析。
saxParser.parse(new File(filename),new sax());
在進行具體的應用中(包括用SAX讀取XML文件)主要使用ContentHandler類的方法自動觸發相應的事件來調用這些方法進行的工做,下面是一個用SAX讀取XML文件的示例程序。
【例9-5】用SAX讀取XML文件示例
saxParseUserXML1.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="javax.xml.parsers.*,org.xml.sax.*,org.xml.sax.helpers.*,
org.xml.sax.helpers.DefaultHandler,java.io.*"%>
<html>
<head><title>用SAX解析並遍歷user.xml</title></head>
<body>
<%!
static class SAXParseUser extends DefaultHandler{
StringBuffer tempString=new StringBuffer();
//文件解析開始
public void startDocument() throws SAXException {
tempString.append("開始解析xml文件......<br>");
}
//標籤解析開始
public void startElement(String namespaceURI, String localName,String qName, Attributes atts) throws SAXException{
tempString.append("開始解析結點,結點名稱:"+qName+"<br>");
//解析獲得標籤全部的屬性
for(int i=0;i<atts.getLength();i++){
tempString.append(" 屬性"+atts.getQName(i)+",值爲:"+atts.getValue(i)+"<br>");
}
}
//標籤解析結束
public void endElement(String namespaceURI,String localName,String qName) throws SAXException{
tempString.append("解析結點結束,結點名稱:"+qName+"<br>");
}
//字符串解析
public void characters(char[] ch,int start,int length){
tempString.append(" 解析出字符串,值爲:'"+(new String(ch,start,length))+"'<br>");
}
//文件解析結束
public void endDocument() throws SAXException {
tempString.append("解析xml文件結束!<br>");
}
//獲得解析結果
public StringBuffer getPrintXML(){
return tempString;
}
}
%>
<%//生成SAX解析器工廠長
SAXParserFactory spf = SAXParserFactory.newInstance();
XMLReader xmlReader = null;
SAXParser saxParser=null;
SAXParseUser saxParseUser=new SAXParseUser();
String filename=pageContext.getServletContext().getRealPath("/link.xml");
try {
// 建立一個解析器SAXParser對象
saxParser = spf.newSAXParser();
// 獲得SAXParser中封裝的SAX XMLReader
xmlReader = saxParser.getXMLReader();
//設置解析時處理事件的對象
xmlReader.setContentHandler(saxParseUser);
//開始解析XML文件
xmlReader.parse(filename);
}catch (Exception ex) {
System.out.println(ex);
}
%>
<!--輸出解析結果-->
<table border=1>
<!--輸出表頭-->
<tr >
<td>content</td>
</tr>
<%
out.println("<td>"+saxParseUser.getPrintXML()+"</td>");
%>
</table>
</body>
</html>
程序的註釋很清晰,這個例子須要注意的是ContentHandler類自己的特色:ContentHandler類的方法無須調用,它們就象一個事件監聽器,在解析XML文件的過程當中會自動觸發相應的事件來調用方法。在實際開發過程當中能夠把ContentHandler類的繼承類聲明爲JavaBean。程序的運行結果如圖9-6所示。

圖9-6 用SAX讀取XML文件示例運行結果
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
JDOM
JDOM的處理方式是與DOM相似的操做。是SUN公司發佈的一種簡單方便的XML處理接口。JDOM設計者的目標是:「Java + XML = JDOM」。2002年的JavaOne會議上JDOM的主要創始人Jason Hunter有一篇精彩的演講介紹了JDOM技術,題目就是「JDOM Makes XML Easy」在那篇文件裏,JDOM被拿來與DOM比較,JDOM是爲了在Java中提供比DOM和SAX更爲方便的XML處理接口而開發的。在http://jdom.org能夠下載JDOM的最新版本。JDOM的jar組件包文件是jdom.jar。
JDOM的處理方式有些相似於DOM,但它主要是用SAX實現的,沒必要擔憂處理速度和內存的問題。另外,JDOM中幾乎沒有接口,所有是類,主要的類有:
Attribute(屬性)、CDATA(內容)、Comment(註釋)、Document(文件)、Element(元素)Namespace(命名空間)、ProcessingInstruction(處理指令)和Text(文本)。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
JDOM的類
JDOM中提供了以下7個包,各自的功能以下:
org.jdom——提供描述XML文件的基本類。
org.jdom.input——提供DOMBuilder和SAXBuilder類, 用來讀取及解析已有的XML文件。
org.jdom.output——提供創建XML文件的類,有DOMOutput、SAXOutput、XMLOutput等類。
org.jdom.adapters——該包是用來與DOM進行溝通的。
org.jdom.filter——包含了xml文檔的過濾器類。
org.jdom.transform——包含了將jdom xml文檔接口轉換爲其餘xml文檔接口。
org.jdom.xpath——包含了對xml文檔xpath操做的類.
在org.jdom中提供的類主要有:
Document——文件類,提供設置或獲取根元素、元素內容、註釋、處理命令等的方法。
Element——元素類,提供設置或獲取元素的子元素、內容、屬性等的方法。
Attribute——屬性類,提供設置或獲取元素屬性名、屬性值的方法。
Entity——實體類,提供設置或獲取實體名、內容的方法。
DocType——DTD聲明類,提供設置或獲取DTD聲明及內容的方法。
ProcessingInstruction——處理命令類,提供設置或獲取處理命令及內容的方法。
org.jdom中還提供了Comment(註釋類)、CDATA、Namespace等一些類。
下面來看一下具體的類的經常使用方法,以及這些經常使用方法的使用。
一、Document類
(1)Document的操做方法
Element root = new Element("GREETING");
Document doc = new Document(root);
root.setText("Hello JDOM!");
或者簡單的使用
Document doc = new Document(new Element("GREETING").setText("Hello JDOM!t"));
這點和DOM不一樣。Dom則須要更爲複雜的代碼,以下:
DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();
DocumentBuilder builder =factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element root =doc.createElement("root");
Text text = doc.createText("This is the root");
root.appendChild(text);
doc.appendChild(root);
【專家提示】JDOM不容許同一個節點同時被2個或多個文檔相關聯,要在第2個文檔中使用原來老文檔中的節點的話。首先須要使用detach()把這個節點分開來。
(2)從文件、流、系統ID、URL獲得Document對象
DOMBuilder builder = new DOMBuilder();
Document doc = builder.build(new File("jdom_test.xml"));
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(url);
在新版本中DOMBuilder 已經不多使用DOMBuilder.builder(url),用SAX效率會比較快。
(3)DOM的Document和JDOM的Document之間的相互轉換使用方法
DOMBuilder builder = new DOMBuilder();
org.jdom.Document jdomDocument = builder.build(domDocument);
DOMOutputter converter = new DOMOutputter();// work with the JDOM document…
org.w3c.dom.Document domDocument = converter.output(jdomDocument);
二、XMLOutPutter類
JDOM的輸出很是靈活,支持不少種io格式以及風格的輸出。
Document doc = new Document(...);
XMLOutputter outp = new XMLOutputter();
outp.output(doc, fileOutputStream); // 用XMLOutputter對象輸出JDOM文檔對象
outp.setTextTrim(true); // Compressed output
outp.output(doc, socket.getOutputStream());
outp.setIndent(" ");// 設置緊縮編排使用的字符串
outp.setNewlines(true);
outp.output(doc, System.out);
三、Element類
(1)瀏覽Element樹
Element root = doc.getRootElement();//得到根元素element
List allChildren = root.getChildren();// 得到全部子元素的一個list
List namedChildren = root.getChildren("name");// 得到指定名稱子元素的list
Element child = root.getChild("name");//得到指定名稱的第一個子元素
JDOM給了咱們不少很靈活的使用方法來管理子元素(這裏的List是java.util.List)
List allChildren = root.getChildren();
allChildren.remove(3); // 刪除第四個子元素
allChildren.removeAll(root.getChildren("jack"));// 刪除叫「jack」的子元素
root.removeChildren("jack"); // 便捷寫法
allChildren.add(new Element("jane"));// 加入
root.addContent(new Element("jane")); // 增長子節點元素
allChildren.add(0, new Element("first"));
(2)移動Element
在JDOM裏移動Element很簡單:
Element movable = new Element("movable");
parent1.addContent(movable); // 向Document中添加子元素
parent1.removeContent(movable); //向Document中刪除子元素
parent2.addContent(movable); // add
在Dom裏移動Element:
Element movable = doc1.createElement("movable");
parent1.appendChild(movable); //向Document中添加子元素
parent1.removeChild(movable); //向Document中刪除子元素
parent2.appendChild(movable); // 出錯!
(3)Element的text內容讀取
String desc = element.getText();//獲得元素文本值
String desc = element.getTextTrim();//獲得元素文本值並去除左右空格
(4)Elment內容修改
element.setText("A new description");//設置元素的文本
四、Attribute類
<table width="100%" border="0"> </table>
String width = table.getAttributeValue("width");//得到attribute
int border = table.getAttribute("width").getIntValue();
table.setAttribute("vspace", "0");//設置attribute
table.removeAttribute("vspace");// 刪除一個或所有attribute
table.getAttributes().clear();
使用JDOM經過程序創建一個新的XML文件,或者對一個已有XML文件進行轉換(存取以及修改、添加等操做)。
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
使用JDOM建立和讀取XML文件
使用JDOM建立一個新XML文件的通常步驟是:
(1) 創建元素及其內容
創建一個元素(Element對象)做爲根結點;
創建根結點的子結點(若是有):建一新元素,加入到根結點中做爲子結點;
創建子結點的下面一層子結點:
……
直至建完葉子。
創建DOM結構樹時能夠橫向一層一層地依次創建,也能夠縱向向下建完葉子再回頭創建另外一結點,創建順序不限。
(2)以根結點爲根元素創建文件(Document對象)
(3)創建XML文件
(4)使用org.output包中的方法創建輸出流對象
(5)使用輸出流對象的output方法將Document對象輸出到文件中,完成XML文件的創建。
【例9-6】用JDOM讀取XML文件示例
本例將利用JDOM編寫一個JSP程序(CreateXML.java),該程序實現創建一個新的XML文件「books.xml」,並用表格輸出在瀏覽器XML文件books.xml的數據。
源程序以下:
jdomreadxml.jsp
<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="org.jdom.*,org.jdom.input.*,org.jdom.output.XMLOutputter,
java.io.*,org.jdom.output.Format,java.util.*"%>
<html>
<head>
<title> JDOM讀取XML文件示例</title>
</head>
<body>
<%
Element root,ele,name,name1,name2,name3;
//Element root=new Element("教材表")
root=new Element("教材表"); //創建根元素<教材表>
//創建根元素的第一個子元素<教材>
ele=new Element("教材"); //建新元素<教材>
root.addContent(ele); //將<教材>加入根元素, 成爲根元素的子元素
name=new Element("書名"); //建新元素<書名>
ele.addContent(name); //將<書名>加入<教材>中, 成爲<教材>的子元素
name.setText("Java網絡編程"); //設置<書名>的內容
name1=new Element("做者"); //建新元素<做者>
ele.addContent(name1); //將<做者>加入<教材>中, 成爲<教材>的第2個子元素
name1.setText("陳春穎等");
name2=new Element("出版社"); //建新元素<出版社>
ele.addContent(name2); //將<出版社>加入<教材>中, 成爲<教材>的第3個子元素
name2.setText("高等教育出版社");
name3=new Element("價格"); //建新元素<價格>
ele.addContent(name3); //將<價格>加入<教材>,成爲<教材>的第4個子元素
name3.setText("46.0"); //設置<價格>的內容
//創建根元素的第二個子元素<教材>
ele=new Element("教材");
name=new Element("書名");
name1=new Element("出版社");
name2=new Element("做者");
name3=new Element("價格");
name.setText("專家導學JSP應用開發");
name1.setText("電子工業出版社");
name2.setText("周雄偉等");
name3.setText("51.0");
ele.addContent(name);
ele.addContent(name1);
ele.addContent(name2);
ele.addContent(name3);
root.addContent(ele); //將<教材>加入根元素, 成爲根元素的第2個子元素
//創建根元素的第二個子元素<教材>
ele=new Element("教材");
name=new Element("書名");
name1=new Element("出版社");
name2=new Element("做者");
name3=new Element("價格");
name.setText("Lucene開發");
name1.setText("電子工業出版社");
name2.setText("周雄偉等");
name3.setText("55.0");
ele.addContent(name);
ele.addContent(name1);
ele.addContent(name2);
ele.addContent(name3);
root.addContent(ele); //將<教材>加入根元素, 成爲根元素的第3個子元素
Document doc=new Document(root); //以根元素創建文件
FileOutputStream f=new FileOutputStream("books.xml");
XMLOutputter out1=new XMLOutputter(); //創建輸出流
Format format=Format.getPrettyFormat(); //格式化文件
format.setEncoding("gb2312"); //格式設爲gbk2312中文將顯示
out1.setFormat(format);
out1.output(doc,f); //將文件輸出到XML文件中
%>
<table border=1>
<!--輸出表頭-->
<tr >
<td>書名</td>
<td>價格</td>
<td>出版社</td>
<td>做者</td>
</tr>
<%//---獲得數據---
SAXBuilder builder = new SAXBuilder();//建立對象
//創建Document對象
Document readDocument = builder.build(pageContext.getServletContext().getRealPath("books.xml"));
//獲得根元素
Element rootElement = readDocument.getRootElement();
//獲得根無素的子元素列表,實際上就是user元素列表
List list = rootElement.getChildren();
//-----輸出數據----
for(Iterator i = list.iterator();i.hasNext();){
Element current = (Element)i.next();
out.println("<tr>");
//----輸出書名--
out.println("<td>"+current.getChildText("書名")+"</td>");
//----輸出價格--
out.println("<td>"+current.getChildText("價格")+"</td>");
//----輸出出版社--
out.println("<td>"+current.getChildText("出版社")+"</td>");
//----輸出做者--
out.println("<td>"+current.getChildText("做者")+"</td>");
out.println("</tr>");
}
%>
</table>
</body>
</html>
結合使用JDOM建立一個新XML文件的通常步驟和源程序的註釋,這個程序不難理解,程序的運行結果如圖9-7所示。

圖9-7 DOM讀取XML文件示例運行結果
該程序運行後,在該程序的目錄下即生成XML文件「books.xml」,雙擊「books.xml」文件,便可看到如圖9-8所示效果。

圖9-8 books.xml的運行結果
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月06日
使用JDOM修改XML文件
使用JDOM修改XML文件與DOM修改XML文件同樣,也包含兩個方面的。是在XML文件中在XML文件中增長記錄和是在XML文件中修改節點的值兩個方面,它們的進行的基本原理相似。用JDOM由現有XML文件生成DOM模型時,對一個XML文件進行轉換過程如圖9-9所示,能夠分爲以下幾步:
(1)創建一個解析器
(2)解析XML文件並傳回Document對象
(3)JDOM提供的方法存取這個Document對象

圖9-9 XML轉換DOM模型
前面DOM講了在XML文件中增長記錄的示例,這裏咱們來說一個在XML文件中修改節點值的例子。
【例9-7】JDOM修改XML文件示例
本例將編寫一個JSP程序,它利用JDOM讀出例9-6所生成的XML文件「books.xml」的內容,並對其進行修改後再寫回XML文件「books.xml」中,源程序以下:
jdomchangxml.jsp
<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="javax.xml.parsers.*,org.jdom.*,org.jdom.output.XMLOutputter,java.io.*,java.util.*"%>
<%@ page import="org.jdom.*,org.jdom.input.*,org.jdom.output.XMLOutputter,java.io.*,
org.jdom.output.Format,java.util.*"%>
<html>
<head>
<title> JDOM修改XML文件示例</title>
</head>
<body>
<%
SAXBuilder sb = new SAXBuilder(); //創建一個解析器
//構造一個Document,讀入books.xml文件的內容
Document doc = sb.build(new FileInputStream("books.xml"));
Element root = doc.getRootElement(); //獲得根元素
java.util.List books = root.getChildren(); //獲得根元素全部子元素的集合
Element book = (Element)books.get(0); //獲得第1個子元素<教材>
//爲第1個元素<教材>添加一條屬性
Attribute a = new Attribute("有課件","true");
//book.addAttribute(a);
book.setAttribute(a);
//爲第1個元素<教材>添加一個元素<做者>
Element author = new Element("做者"); //建新元素<做者>
author.setText("yinzhaolin"); //設置<做者>的內容
book.addContent(author); //將<做者>加入<教材>中
book.removeChild("價格"); //刪除子元素<價格>
book = (Element)books.get(1); //獲得第2個元素<教材>
//修改價格
Element price = book.getChild("價格"); //獲得指定的子元素<價格>
price.setText("56"); //將價格改成20元
XMLOutputter out1 = new XMLOutputter();//創建輸出流
out1.output(doc, new FileOutputStream("books.xml")); //將文件輸回到XML文件中
%>
<table border=1>
<!--輸出表頭-->
<tr >
<td>書名</td>
<td>價格</td>
<td>出版社</td>
<td>價格</td>
</tr>
<%//---獲得數據---
Element newroot = doc.getRootElement();
//獲得根無素的子元素列表,實際上就是user元素列表
List list = newroot.getChildren();
//-----輸出數據----
for(Iterator i = list.iterator();i.hasNext();){
Element current = (Element)i.next();
out.println("<tr>");
//----輸出書名--
out.println("<td>"+current.getChildText("書名")+"</td>");
//----輸出做者--
out.println("<td>"+current.getChildText("出版社")+"</td>");
//----輸出出版社--
out.println("<td>"+current.getChildText("做者")+"</td>");
//----輸出價格--
out.println("<td>"+current.getChildText("價格")+"</td>");
out.println("</tr>");
}
%>
</table>
</body>
</html>
程序的源碼進行了詳細的註釋,對比之前的代碼,JDOM比DOM和SAX方式操做XML文件明顯要方便,並且效率比DOM方式要高。程序的運行結果如圖9-10所示

圖9-10 JDOM修改XML文件示例運行結果
上面的程序修改了例9-6所創建的XML文件books.xml,修改後的books.xml顯示的結果如圖9-11。

圖9-11 修改後的XML文件顯示結果
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
XML文件與數據庫操做
XML文件與數據庫的操做應用很是普遍,既能夠用XML文件對數據庫進行鏈接與配置,也能夠把數據庫的表記錄用XML文件進行備份。其中數據庫表記錄集轉換到XML文件大致能夠分兩步:
(1)創建數據庫和表,利用ODBC中設置數據源,並指向該數據庫。
(2)把數據庫的記錄集轉換成XML文件。其步驟以下:
利用select語句創建須要的記錄集(ResultSet);
得到記錄集的結構;
把記錄集轉換成XML文件。
下面看一個JDOM把數據庫的錶轉化成XML文件示例。
【例9-8】JDOM把數據庫的錶轉化成XML文件示例
本例將編寫使用JDOM技術的JSP應用程序,它讀出Access數據庫student.mdb中學生信息表(information)表的記錄集,並將它們轉換成名爲DB.xml的XML文件。student.mdb的information表結構以下。
表9-1 學生信息表結構

源程序以下:
jdomchangDBtoxml.jsp
<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="javax.xml.parsers.*,org.jdom.*,org.jdom.output.XMLOutputter,java.io.*,java.util.*, java.sql.*,org.jdom.output.Format"%>
<html>
<head>
<title> JDOM把數據庫的錶轉化成XML文件示例</title>
</head>
<body>
JDOM把數據庫的錶轉化成XML文件<br>
<%
//創建數據庫鏈接並獲取學生表的記錄集和結構
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //加載橋驅動程序
Connection con=DriverManager.getConnection("jdbc:odbc:Demo"); //創建數據庫鏈接
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery("select * from information"); //獲取結果集
rs.next();
out.println(rs.getString("字段1"));
//得到結果集的結構
ResultSetMetaData rsmd=rs.getMetaData();
//得到結果集的列數,也就是數據項的數目
int numcols=rsmd.getColumnCount();
//記錄集到XML文件的轉換
Element root,ele,name; //定義Element類的對象根元素(root)
root=new Element("student"); //創建根元素
//循環, 將結果集中的每一條記錄轉換成一個元素(標記名爲「第…個記錄」)
while(rs.next())
{ele=new Element("第"+rs.getRow()+"條紀錄"); //設置元素,名爲「第…個記錄」
out.println(ele);
for(int i=1;i<=numcols;i++) //循環,將一條記錄中的每一個字段轉換成一個元素
{// getColumnLabel(i) 獲取第i個列的字段名(列數從0開始)。
//out.println(rs.getString(i));
name=new Element(rsmd.getColumnLabel(i)); //以得到的字段名爲標記名設置元素
name.setText(rs.getString(i)); //獲取字段內容做爲字段名元素的內容
ele.addContent(name); //將字段名元素置爲記錄的子元素
}
root.addContent(ele); //將記錄元素置爲根元素的子元素
}
Document doc=new Document(root); //以根元素創建文件
FileOutputStream f=new FileOutputStream("DB.xml");
XMLOutputter out1=new XMLOutputter(); //將文件輸出造成XML文件
Format format=Format.getPrettyFormat(); //格式化文件
format.setEncoding("gb2312"); //編碼設爲gb2312中文將顯示正常
out1.setFormat(format);
out1.output(doc,f);
rs.close(); con.close(); //關閉各個對象
out.println("數據庫表Information已成功地轉化成XML文件DB.xml!");
%>
</table>
</body>
</html>
程序的運行結果如圖9-12所示。

圖9-12 JDOM把數據庫的錶轉化成XML文件
程序運行後在工程的目錄下生成XML文件「DB.xml」,雙擊「DB.xml」文件,便可看到如圖9-13所示結果。

圖9-13 由數據庫記錄集轉換獲得的XML文件顯示結果
版權方受權希賽網發佈,侵權必究
第 9 章:XML操做做者:鄧子云,赫斌等 來源:希賽網 2014年03月05日
小結
XML在Web開發中應用普遍,已經進入Java程序員必備的知識範疇。本章從XML的基本概念講起,由淺入深,介紹了XML的文件結構以及DTD知識,主要講解XML文件的三種處理方式:DOM\SAX和JDOM。
DOM和SAX是經常使用的兩種操做XML文件的接口。DOM方式先將XML文件讀入內存,創建起一棵文檔樹,經過對這棵文檔樹的操做來完成對XML文件的操做。SAX API是事件驅動的,又稱"順序訪問"協議。每當它看到一個新的XML標記(或遇到一個錯誤,或想告訴你什麼事時)就用一個SAX解析器註冊你的句柄,激活你的回調方法。
DOM 定義了分析程序應當顯露的標準命令集,使您可以在程序中訪問 HTML 和 XML 文件內容。DOM的特色是功能強大,但分析時間長,佔用資源多。
SAX是一種輕量型的方法,它是基於事件的XML分析API,功能比較簡單。SAX 提供了處理 XML 文件的快速、低內存的另外一種方法。建議較小的XML文件或須要修改XML時使用DOM接口,速度要求較高時採用SAX接口。
JDOM組合了DOM和SAX的優勢,功能特別強大,還提供了Document,Element,Comment,DocType,Attribute,Text等Java類,能夠利用這些類建立、遍歷並修改JDOM文檔以及把數據庫的錶轉換成XML文件。
版權方受權希賽網發佈,侵權必究
第 10 章:JavaMail做者:鄧子云,赫斌等 來源:希賽網 2014年03月06日
構建JavaMail的開發環境
對於Java平臺而言,JavaMail算是比較晚加入的API,目前在Java網站(http://java.sun.com/products/javamail/)上最新版本是JavaMail1.4API,本章中將使用它來做爲開發工具。
1.mail.jar
讀者能夠到如下的網址下載最新的JavaMail API:
http://java.sun.com/products/javamail/downloads/index.html
下載後獲得的文件名爲javamail-1_4.zip。首先將javamail-1_4.zip解壓縮後,mail.jar是最重要的文件,它裏面就是JavaMail API的類,除mail.jar以外,它還內附dsn.jar、imap.jar、javamailapi.jar、pop3.jar、smtp.jar。
【專家提示】讀取能夠用WinRar工具查看dsn.jar、imap.jar、javamailapi.jar、pop3.jar、smtp.jar幾個文件的內容,會發現它們僅僅是mail.jar文件的拆分而已,因此一般在開發過程當中只須要選用mail.jar文件便可。
2.activation.jar
除了mail.jar以外,讀者還能夠到以下的網址下載最新的JavaBeans Activation Framework(JAF):
http://java.sun.com/products/javabeans/jaf/
JAF目前最新版本爲1.1。
接下來將activation.jar和mail.jar這兩個jar文件拷貝至當前Web應用的「WEB-INF/lib」目錄下,如圖10-1所示:

圖10-1 構建JavaMail開發環境
這些前期工做都準備好後,接下來就是學習JavaMail的開發步驟了。
版權方受權希賽網發佈,侵權必究
第 10 章:JavaMail做者:鄧子云,赫斌等 來源:希賽網 2014年03月06日
JavaMail API
JavaMail應用程序接口(API)用於發送和接收郵件。它不只獨立於平臺,能夠在Windows、Macintosh和Linux上使用,還獨立於底層傳輸協議,能夠使用郵局協議(Post Office Protocol,POP3)和Internet郵件訪問協議(IMAP)接收消息。JavaMail中的消息是使用簡單郵件傳輸協議(Simple Mail Transfer Protocol,SMTP)服務器來發送的。
JavaMail API的工做原理如圖10-2所示。

圖10-2 JavaMail API的工做原理
在圖10-2中,發件人使用Transport對象發送消息。Transport對象將消息提交到網絡,而後發送給收件人。發送給收人的消息存儲在消息服務器中。存儲由許多個文件夾和郵件組成,收件人能夠訪問該文件夾並讀取消息。
在JavaMail API中定義四個主要組件:Message、Folder、Sotre和Session.
Message
Message類是一個抽象類,定義郵件信息以內容類型等屬性,包含標題和內容:標題包含全部的尋址信息,而內容包含數據。Message類的部分經常使用方法以下:
setFrom:指定消息的發件人。
setRecipients:指定收件人的地址。
setSubject:指定消息的主題。
setText:指定消息的文本。
setSentDate:指定消息的發送日期。
setReplyTo:指定消息回覆導向的地址。
getFlags:返回當前消息的標記。
RECENT:指明收到的新消息。
SEEN:指明已查看的消息。
Folder
Folder類是一個抽象類,Folder包含消息和子文件夾。Folder對象用於消息的通訊和管理。默認狀況下,Folder類處於關閉狀態,在這種狀態下不能查看消息和子文件夾。要查看消息和子文件夾,須要使用Folder類的open()方法打開文件夾。Folder類的部分經常使用的方法以下:
open:打開文件,能夠用兩種模式打開文件夾。
READ_ONLY模式:以只讀模式打開文件夾。
READ_WRITE模式:以讀寫模式打開文件夾。在這種模式下,用戶能夠編寫、更新和刪除消息。
create:新建一個文件夾。
exists:檢查文件夾是否存在。
getFolder:得到文件夾。
getMessage:得到指定的消息對象。
Store
Store類是一個抽象類,消息存儲在文件夾(如Inbox和Drafts等)中,而這些文件夾存儲在消息存儲器中(Store)。Store類提供對文件夾的方法並並驗證鏈接,Store類的方法還用於查看消息和文件夾。在鏈接Store以前,用戶須要建立一個會話。建立Store的語法爲:
Store store=obj_session.getStore(protocol);
store.connect(hostname,username,password);
其中,getStore(protocol)得到實現指定協議的Store對象,服務器使用該協議發送和接收消息;connect(hostname,username,password)鏈接到指定地址,並接受主機名、用戶名和密碼做爲參數。
Session
Session類是JavaMail API的最高級別的類。它定義了用來與郵件系統進行通訊的郵件會話,使用戶能夠使用相應的getXXX()方法來訪問Store和Transport對象。還用於存儲信息與服務器創建會話鏈接。Session類可以控制和加載類,能夠建立共享和非共享會話,而共享會話能夠被多個應用程序共享。建立非共享會話的語法爲:
Session session=Session.getDefaultInstance(p,null) ;
其中,Session.getDefaultInstance(p,null)得到默認的Session對象。若是未設置默認對象,就新建一個Session對象並做爲默認對象安裝。p是屬性對象,null表示沒有驗證程序,任何人均可以得到默認會話。
【思考1】JavaMail組件中爲何Message、Folder和Store都被定義爲抽象類?咱們若是取得它們相應的實例對象?
這節將學習編寫一個最簡單的發信程序,編寫郵件程序時,使用JavaMail要導入一些包,這些包分別以下:
java..util.*:定義集合框架、日期和時間工具,以及事件模型的集合。
java.io.*:經過數據流,序列化和文件系統來提供系統輸入和輸出。
javax.mail.*:定義對全部郵件系統都通用的類。
javax.mail.internet.*:定義特定於Internet郵件系統的類。
javax.activation.*:由JavaMail API使用,以管理MIME數據。
構造JavaMail發郵件程序涉及的步驟如圖10-3所示。

圖10-3 構建JavaMail發郵件程序的步驟
版權方受權希賽網發佈,侵權必究
第 10 章:JavaMail做者:鄧子云,赫斌等 來源:希賽網 2014年03月06日
建立JavaMail會話
Session對象管理用以與消息傳送系統進行交互的配置選項和用戶驗證信息,建立會話的語法爲:
Properties props = new Properties();
props.put("mail.smtp.host", host);
props.put("mail.smtp.auth", "true");
Session mailSession = Session.getDefaultInstance(props);
mailSession.setDebug(true);
其中,props.put("mail.smtp.host", host)指定發送郵件時所使用的SMTP服務器,props.put("mail.smtp.auth", "true")指定發送郵件時所使用的SMTP服務器是否須要進行身份驗證。
其中,mailSession.setDebug(boolean )指定是否在系統控制檯顯示發送郵件的DEBUG信息。如:

圖10-4 發送郵件的提示信息
【專家提示】setDebug(true)時,會將JavaMail所作的每一步工做的調試信息在系統控制檯上輸出。當發送郵件的數據量較大和數量較多時會引發系統I/O阻塞致使系統運行緩慢,因此當程序員開發調試完成正式發佈運行時要將setDebug(false)。
版權方受權希賽網發佈,侵權必究
第 10 章:JavaMail做者:鄧子云,赫斌等 來源:希賽網 2014年03月06日
構造消息
建立會話和設置屬性以後,構造要發送的消息因爲Message類是一個抽象類,咱們使用Message類的子類MimeMessage來建立構造消息的實例。建立消息實例的語法爲:
//經過會話實例建立新的消息實例
Message message=new MimeMessage(mailSession);
//設置發件人信息
message.setFrom(new InternetAddress(from));
//設置收件人信息
message.addRecipient(Message.RecipientType.TO,new InternetAddress(to));
//設置抄送人信息
message.addRecipient(Message.RecipientType.CC,new InternetAddress("orion@csai.cn"));
//設置郵件主題
message.setSubject(subject);
//設置郵件文本內容
message.setText(content);
//設置發信日期
message.setSentDate(new java.util.Date());
//保存郵件設置信息
message.saveChanges();
【專家提示】調用完Message類的setFrom()、setRecipients()、setSubject()和setText()方法後,必定要調用saveChanges()方法才保存相應的設置信息。
【專家提示】RecipientType.表示郵件以何種方式傳送給收人相應屬性有TO直送、CC(Carbon Copy,抄送)和BCC(Bind Carbon Copy,暗送)等。
版權方受權希賽網發佈,侵權必究
第 10 章:JavaMail做者:鄧子云,赫斌等 來源:希賽網 2014年03月06日
發送消息
簡單郵件傳輸協議(Simple Mail Transfer Protocol,SMTP)是用於發送郵件的協議。建立會話和構造消息以後,得到Transport對象,而後使用這個類的Send()方法發送消息。
Transport transport = mailSession.getTransport("smtp");
transport.connect(host, user, password);
transport.sendMessage(message, message.getAllRecipients());
transport.close();
其中:getTransport(「SMTP」)返回實現了SMTP協議的傳輸對象。
【例10-1】發送簡單的郵件
先作一個JavaMailSend.html的用戶界面讓用戶輸入數據,而後再傳關到JavaMailSend.jsp作處理。
JavaMailSend.html
<html>
<head>
<title>CH10 - JavaMailSend.html</title>
<meta http-equiv="Content-Type" content="text/html; charset=GB2312">
</head>
<body>
<h2>利用JavaMail來發送電子郵件</h2>
<form name="Form" method="post" action="JavaMailSend.jsp">
<p>郵件主機:<input type="text" name="Host" size="30" maxlength="30"></p>
<p>賬號:<input type="text" name="User" size="30" maxlength="30"></p>
<p>密碼:<input type="password" name="Password" size="30" maxlength="30"></p>
<p>寄信人:<input type="text" name="From" size="30" maxlength="30"></p>
<p>收信人:<input type="text" name="To" size="30" maxlength="30"></p>
<p>主題:<input type="text" name="Subject" size="30" maxlength="30"></p>
<p>內容:</p><p><textarea name="Message" cols=40 rows=5></textarea></p>
<input type="submit" value="發送">
<input type="reset" value="清除">
</form>
</body>
</html>
JavaMailSend.html頁面的執行結果如圖10-5所示,其中包括郵件主機、在郵件主機上註冊的賬號、密碼、寄信人、收信人、主題和內容。當用戶填好數據後,按下【發送】,就會將窗體數據傳送到JavaMailSend.jsp作發送電子郵件的工做。

圖10-5 JavaMailSend.html的執行結果
JavaMailSend.jsp
<%@ page import="javax.mail.*" %>
<%@ page import="javax.mail.internet.*" %>
<%@ page import="javax.activation.*" %>
<%@ page import="java.util.*,java.io.*" %>
<%@ page contentType="text/html;charset=GBK" %>
<html>
<head>
<title>CH10 - JavaMailSend.jsp</title>
</head>
<body>
<h2>利用JavaMail來傳送電子郵件 </h2>
<% //設置中文參數的編碼
request.setCharacterEncoding("GBK");
//接收相應的參數
String host = request.getParameter("Host");
String user = request.getParameter("User");
String password = request.getParameter("Password");
String From = request.getParameter("From");
String to = request.getParameter("To");
String Subject = request.getParameter("Subject");
String messageText = request.getParameter("Message");
Properties props = new Properties();
//指定SMTP服務器
props.put("mail.smtp.host", host);
//指定是否須要SMTP驗證
props.put("mail.smtp.auth", "true");
try {
//建立JavaMail會話
Session mailSession = Session.getDefaultInstance(props);
//在控制檯顯示debug信息
mailSession.setDebug(true);
//構造新的消息對象
Message message = new MimeMessage(mailSession);
////發件人
message.setFrom(new InternetAddress(From));
//收件人
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
//抄送人
message.addRecipient(Message.RecipientType.CC,
new InternetAddress("jspadmin@csai.cn"));
//郵件主題
message.setSubject(Subject);
//郵件內容
message.setText(messageText);
//發信日期
message.setSentDate(new java.util.Date());
message.saveChanges();
//構建傳送對象
Transport transport = mailSession.getTransport("smtp");
transport.connect(host, user, password);
transport.sendMessage(message, message.getAllRecipients());
transport.close();
out.println("<h5>郵件已順利傳送至:"+to+"</h5>");
}
catch (MessagingException mex) {
mex.printStackTrace();
}
%>
</body>
</html>

圖10-6 JavaMailSend.jsp執行結果
JavaMailSend.jsp範例中,筆者以csai.cn的郵件服務器來作測試,讀者也能夠使用其餘免費電子郵信箱的郵件服務器,只要它有提供SMTP的服務。
【專家提示】若是讀取在運行上述示例時系統控制檯出現以下錯誤提示

圖10-7 錯誤的異常信息
有多是您機器防火牆軟件阻止了郵件傳送程序,請您更改防火牆設置。
登陸orion@csai.cn郵箱查看結果如圖 10-8所示

圖10-8 郵箱查看信件
版權方受權希賽網發佈,侵權必究
第 10 章:JavaMail做者:鄧子云,赫斌等 來源:希賽網 2014年03月06日
接收郵件
接下來將編寫接收郵件程序將前面發送的郵件從服務器上收下來,構造郵件接收程序的步驟如圖10-9所示。

圖10-9 構造郵件接收程序
版權方受權希賽網發佈,侵權必究
第 10 章:JavaMail做者:鄧子云,赫斌等 來源:希賽網 2014年03月06日
登陸Store
Store對象具備一個用於鏈接到Store的connect()方法。此方法提供簡單的驗證,要求輸入用戶名和密碼。鏈接Store的語法爲:
Properties props=new Properties();
props.put("mail.pop3.host",host);
Session mailsession=Session.getDefaultInstance(props);
Store store=mailsession.getStore("pop3");
store.connect(host,user,password);
版權方受權希賽網發佈,侵權必究
第 10 章:JavaMail做者:鄧子云,赫斌等 來源:希賽網 2014年03月06日
列出INBOX中的郵件
文件夾名INBOX是一個保留名字,表明全部消息第一次到達系統的位置。收到的消息存儲在消息存儲器中的文件夾中。列出INBOX中全部消息的語法爲:
Folder inbox=store.getDefaultFolder().getFolder("INBOX");
inbox.open(Folder.READ_WRITE);
Message[] message=inbox.getMessages();
其中,getFolder("INBOX") 將得到INBOX文件夾並將其存儲在對象中。
inbox.open(Folder.READ_WRITE) 將以讀寫模式打開文件夾,採用這種模式在收取服務器端的郵件能夠刪除服務器端的副本並釋放服務器空間。
getMessage() 返回文件夾中全部消息對象。
版權方受權希賽網發佈,侵權必究
第 10 章:JavaMail做者:鄧子云,赫斌等 來源:希賽網 2014年03月06日
讀取消息
在JavaMail中,POP3是用於接收消息的協議。要讀取消息,可鏈接到Store並打開指定文件夾,檢索數組中的消息,讀取消息的語法爲:
for (int i = 0; i < message.length; i++) {
message[i].setFlag(Flags.Flag.DELETED,true);
out.println("郵件主題:"+message[i].getSubject()+"<br>");
out.println("郵件發送者:"+message[i].getFrom()[0]+"<br>");
out.println("發送時間:"+message[i].getSentDate()+"<br>");
out.println("內容:"+message[i].getContent()+"<br>");
}
inbox.close(true);
store.close();
其中,setFlag(Flags.Flag.DELETED,true) 將消息標記爲刪除。
Inbox.close(true) 關閉INBOX文件夾,參數爲true表示刪除其中標記爲刪除的消息。
【專家提示】在讀取消息後請使用Store對象的close()方法關閉存儲器,若是再次鏈接到一個已經鏈接的存儲器將發生錯誤。
【例10-2】接收郵件
先來作一個JavaMailReceiver.html的用戶界面讓用戶輸入數據,而後再傳送到JavaMailReceiver.jsp作處理。
JavaMailReceiver.html
<html>
<head>
<title>CH10 - JavaMailReceiver.html</title>
<meta http-equiv="Content-Type" content="text/html; charset=GB2312">
</head>
<body>
<h2>利用JavaMail來接收電子郵件</h2>
<form name="Form" method="post" action="JavaMailReceiver.jsp">
<p>郵件主機:<input type="text" name="Host" size="30" maxlength="30"></p>
<p>賬號:<input type="text" name="User" size="30" maxlength="30"></p>
<p>密碼:<input type="password" name="Password" size="30" maxlength="30"></p>
<input type="submit" value="接收">
<input type="reset" value="清除">
</form>
</body>
</html>
JavaMailReceiver.html的執行結果如圖10-10所示,其中包括郵件主機、在郵件主機上註冊的賬號、密碼。當用戶填好數據後,按下【接收】,就會將窗體數據傳送到JavaMailReceiver.jsp作接收電子郵件的工做。

圖10-10 JavaMailReceiver.html執行結果
JavaMailReceiver.jsp
<%@ page import="javax.mail.*" %>
<%@ page import="javax.mail.internet.*" %>
<%@ page import="javax.activation.*" %>
<%@ page import="java.util.*,java.io.*" %>
<%@ page contentType="text/html;charset=GBK" %>
<html>
<head>
<title>CH10 - JavaMailSend.jsp</title>
</head>
<body>
<h2>利用JavaMail來接收電子郵件 </h2>
<%
//設置中文參數的編碼
request.setCharacterEncoding("GBK");
//接收相應的參數
String host = request.getParameter("Host");
String user = request.getParameter("User");
String password = request.getParameter("Password");
try {
Properties props=new Properties();
//指定的POP3郵件服務器
props.put("mail.pop3.host",host);
//建立郵件會話
Session mailsession=Session.getDefaultInstance(props);
//建立Store對象
Store store=mailsession.getStore("pop3");
//登陸到Store
store.connect(host,user,password);
//得到INBOX文件夾
Folder inbox=store.getDefaultFolder().getFolder("INBOX");
//以讀寫模式打開INBOX文件夾
inbox.open(Folder.READ_WRITE);
//從INBOX文件夾中取得全部的消息對象
Message[] message=inbox.getMessages();
//循環讀取消息
for (int i = 0; i < message.length; i++) {
message[i].setFlag(Flags.Flag.DELETED,true);
out.println("郵件主題:"+message[i].getSubject()+"<br>");
out.println("郵件發送者:"+message[i].getFrom()[0]+"<br>");
out.println("發送時間:"+message[i].getSentDate()+"<br>");
out.println("內容:"+message[i].getContent()+"<br>");
}
//關閉文件夾,並刪除標記爲刪除的消息
inbox.close(true);
//關閉登陸的Store
store.close();
}
catch (MessagingException ex) {
ex.printStackTrace();
}
%>
</body>
</html>

圖10-11 JavaMailReceiver.jsp執行結果
版權方受權希賽網發佈,侵權必究
第 10 章:JavaMail做者:鄧子云,赫斌等 來源:希賽網 2014年03月06日
Multipart消息
前面我講述的郵件消息都是隻包含文本的消息,在實際應用中一個郵件消息一般除了文本內容以外還包含圖片、HTML網頁和附件文件等。在JavaMail中一條郵件消息可由多個部分組成,每一部分是一個BodyPart(報文部分),或更特殊一點,在操做MIME消息時則是MimeBodyPart。不一樣的報文部分組合到一個稱爲Multipart的容器中,或者又更特殊一點,是一個MimeMultipart容器(如圖 10-12 所示)。要發送一個複雜的郵件消息您要建立每個用於消息文本的部分,並將這多個部分組合成一個multipart(多個部分)。而後您能夠把這個multipart添加到一個合適的註明地址的消息中併發送它。建立Multipart消息的步驟如圖10-13所示。

【例10-2】發送帶附件的郵件
接下來將演示發送一個內容爲HTML格式而且帶有附件的郵件消息指導讀者如何構造Multipart消息。示例的作法是:先將處理好的郵件內容存入到MimeBodyPart對象中;而後將文件存入到另外一個MimeBodyPart對象中;最後把兩個MimeBodyPart對象(一份是郵件內容自己,另外一份是文本或HTML部分)所有存入到Multipart對象,合而爲一加入Message對象中,發送到收信人的郵件服務器。附件的功能須要使用到上傳文件的機制,所以使用了歐萊禮的文件上傳組件。
JavaMailAttachment.html頁面用於接受用戶郵件消息數據錄入並將請求傳送給JavaMailAttachment.jsp處理,JavaMailAttachment.html頁面的源代碼以下。
JavaMailAttachment.html
<html>
<head>
<title>CH10 - JavaMailAttachment.html</title>
<meta http-equiv="Content-Type" content="text/html; charset=GB2312">
</head>
<body>
<h2>利用JavaMail來傳送電子郵件 - 附件</h2>
<form name="SendMessage" Method="post" action="JavaMailAttachment.jsp" enctype="multipart/form-data">
<p>郵件主機:<input type="text" name="Host" size="30" maxlength="30"></p>
<p>賬號:<input type="text" name="User" size="30" maxlength="30"></p>
<p>密碼:<input type="password" name="Password" size="30" maxlength="30"></p>
<p>寄信人:<input type="text" name="From" size="30" maxlength="30"></p>
<p>收信人:<input type="text" name="To" size="30" maxlength="30"></p>
<p>主題:<input type="text" name="Subject" size="30" maxlength="30"></p>
<p>格式:<select name="Type" size="1">
<option value="text/plain">Text</option>
<option value="text/html">HTML</option>
</select></p>
<p>附件:<input type="file" name="FileName" size="20" maxlength="20"></p>
<p>內容:</p><p><textarea name="Message" cols=40 rows=5></textarea></p>
<input type="submit" value="傳送">
<input type="reset" value="清除">
</form>
</body>
</html>
JavaMailAttachment.html頁面的運行結果如圖 10-14所示。

圖10-14 avaMailAttachment.html執行結果
JavaMailAttachment.jsp
<%@ page import="javax.mail.*" %>
<%@ page import="javax.mail.internet.*" %>
<%@ page import="javax.activation.*" %>
<%@ page import="java.util.*,java.io.*" %>
<%@ page import="com.oreilly.servlet.MultipartRequest" %>
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>CH17 - JavaMail2.jsp</title>
</head>
<body>
<h2>利用JavaMail來傳送電子郵件 - 附件</h2>
<%
InternetAddress[] address = null;
request.setCharacterEncoding("GBK");
MultipartRequest multi = new MultipartRequest(request , "." , 5*1024*1024 , "GBK");
String host = multi.getParameter("Host");
String user = multi.getParameter("User");
String password = multi.getParameter("Password");
String From = multi.getParameter("From");
String to = multi.getParameter("To");
String Subject = multi.getParameter("Subject");
String type = multi.getParameter("Type");
String messageText = multi.getParameter("Message");
String FileName = multi.getFilesystemName("FileName");
try {
// 設定所要用的Mail 服務器和所使用的傳輸協議
Properties props = new Properties();
props.put("mail.smtp.host", host); //指定SMTP服務器
props.put("mail.smtp.auth", "true"); //指定是否須要SMTP驗證
// 產生新的Session 服務
Session mailSession = Session.getDefaultInstance(props);
Message msg = new MimeMessage(mailSession);
// 設定傳送郵件的發信人
msg.setFrom(new InternetAddress(From));
// 設定傳送郵件至收信人的信箱
address = InternetAddress.parse(to,false);
msg.setRecipients(Message.RecipientType.TO, address);
// 設定信中的主題
msg.setSubject(Subject);
// 設定送信的時間
msg.setSentDate(new Date());
if (FileName != null)
{
File file = new File(FileName);
// 若是有附件,先將郵件內容部分存起來
MimeBodyPart mbp1 = new MimeBodyPart();
// 設定郵件內容的類型爲 text/plain 或 text/html
mbp1.setContent(messageText, type + ";charset=GB2312");
// 再來對附件做處理
MimeBodyPart mbp2 = new MimeBodyPart();
FileDataSource fds = new FileDataSource(FileName);
mbp2.setDataHandler(new DataHandler(fds));
mbp2.setFileName(MimeUtility.encodeText(fds.getName(), "GB2312", "B"));
// 最後再將二者整合起來,看成一份郵件送出
Multipart mp = new MimeMultipart();
mp.addBodyPart(mbp1);
mp.addBodyPart(mbp2);
msg.setContent(mp);
}else{
// 若沒有附件時,就直接存郵件內容
msg.setContent(messageText,type + ";charset=GB2312");
}
Transport transport = mailSession.getTransport("smtp");
transport.connect(host, user, password);
transport.sendMessage(msg, msg.getAllRecipients());
transport.close();
out.println("郵件已順利發送至:"+to);
}catch (MessagingException mex){
mex.printStackTrace();
}
%>
</body>
</html>
執行結果如圖 10-15所示:

圖10-15 JavaMailAttachment.jsp的執行結果
郵件服務器上的顯示結果如圖 10-16所示。

圖10-16 郵件服務器上顯示結果
【專家提示】JavaMail API只支持ASCII單字節字符串處理,爲了解決附件中文文件名的問題,咱們必須加上一段程序來作轉碼工做。
mbp2.setFileName(MimeUtility.encodeText(fds.getName(), "GB2312", "B"));
其功能是將多字節Unicode字符串轉化爲單字節US-ASCII字符串。
【專家提示】發送附件郵件存在支持附件大小的問題,郵件消息的大小要受到您的SMTP服務器的限制,而不是由JavaMail API限制的。
版權方受權希賽網發佈,侵權必究
第 10 章:JavaMail做者:鄧子云,赫斌等 來源:希賽網 2014年03月06日
小結
JavaMail含有一組用於發送和接收郵件消息的API,通常地發送郵件使用SMTP協議,接收郵件使用POP3協議。
Message類是一個抽象類,可帶有消息的尋址信息和內容;Folder類是一個抽象類,包含子文件夾和消息等內容;Store類是一個抽象類,定義用於訪問文件夾和檢索消息的協議, 要查看文件夾和消息,須要使用它的connect()方法;編寫發送郵件的程序經常使用Transport類的send()方法發送消息;Multipart消息是Message類的對象,Multipart消息能夠有多個BodyPart。
【思考1】JavaMail組件中爲何Message、Folder和Store都被定義爲抽象類?咱們若是取得它們相應的實例對象?
答:JavaMail API定義了一個用來管理郵件的通用接口,而且JavaMail容許程序員經過API裏的接口來撰寫本身的應用程序,而後在執行時期再請求使用某種類型的處理。這樣程序員採用JavaMail編寫郵件消息收發程序具備適應於任何郵件服務器的通用性和跨平臺的優勢。Message類咱們通常使用其相應的子類MimeMessage建立實例,Store類實例用Session的getStore()方法取得,Folder類實例用Store的getFolder()方法取得。
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
表達式語言簡介
第11章 表達式與標籤
【本章專家知識導學】
JSP標籤是在JSP頁面中對JavaBean的封裝功能進一步補充,從而實現Java代碼與HTML分離的一種服務器端程序。這樣作的目的是讓程序的實現與顯示分離,分離的好處是讓美工專心作界面,開發人員專心實現業務。
本章旨在引導讀者學習表達式語言(EL)和JSTL標籤以及如何自定義標籤,將詳細介紹EL的語法和各類運算符的使用,JSTL標籤中的核心標籤、格式標籤、SQL標籤、XML標籤等標籤的用法,最後介紹自定義標籤的實現。經過學習本章內容後讀者應可以利用EL和標籤來開發Web應用,取代傳統直接在頁面上嵌入Java程序的作法,以提升程序的可閱讀性和可維護性。
11.1 表達式語言簡介
表達式語言(EL)是JSP技術的主要特色之一。Java社區組織(JCP,Java Community Process)的JSP標準標籤庫專家組和JSP2.0專家組共同開發了表達式語言。取代傳統直接在頁面上嵌入Java腳本程序以完成複雜功能的作法,以提升程序的閱讀性、維護性和方便性。EL表達式可用於:
靜態文本:包含EL表達式,其值在運行時計算出來。求值後,EL表達式被計算值替換。
標準標籤和自定義標籤的屬性,以幫助顯示網頁上的動態內容。
讀取JavaBean屬性,使用EL表達式能夠簡潔地讀出JavaBean的屬性值。
下面演示一個JSP使用EL示例程序。
【例11-1】在JSP中應用EL的示例
el_example.jsp
<%@ page language="java" contentType="text/html; charset=GBK"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>EL表達式示例</title>
</head>
<body>
${"請選購商品"} <br>
<form action="el_example1.jsp" method="post">
<select name="trade">
<option value="專家導學JSP應用開發">專家導學JSP應用開發</option>
<option value="專家導學Java面向對象編程">專家導學Java面向對象編程</option>
</select>
單價:<input type="text" name="price"/>
數量:<input type="text" name="count"/>
<input type="submit" value="提交">
</form>
</body>
</html>
el_example.jsp運行結果如圖11-1所示。

圖11-1 el_example.jsp運行結果
選擇相應的商品填寫單價和購買數量後點擊「提交」按鈕將參數提交至el_example1.jsp頁面處理。el_example1.jsp將利用JavaBean接收參數並用EL顯示購買結果。
TradeBean.java
package eldemo;
/**
* 定義接收商品定單信息的JavaBean
* @author Administrator *
*/
public class TradeBean {
private String trade;// 商品名稱
private int count;// 購買數量
private float price;//單價
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getTrade() {
return trade;
}
public void setTrade(String trade) {
this.trade = trade;
}
}
el_example1.jsp
<%@ page language="java" contentType="text/html; charset=GBK"%>
<jsp:directive.page import="eldemo.TradeBean"/>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>EL表達式示例</title>
</head>
<%request.setCharacterEncoding("GBK"); %>
<jsp:useBean id="myorder" class="eldemo.TradeBean">
<jsp:setProperty name="myorder" property="*"/>
</jsp:useBean>
<body>
您購買的商品是: ${myorder.trade}<br>
商品單價是:${myorder.price}<br>
您購買的數量是:${myorder.count}<br>
您應支付的總金額是:${myorder.price*myorder.count }
</body>
</html>
el_example1.jsp的運行結果如圖11-2所示。

圖11-2 el_example1.jsp的運行結果
【專家提示】倘若您所用的JSP容器只支持Servlet 2.3/JSP 1.2,如:Tomcat 4.1.29,就不能在JSP 網頁中直接使用EL,須要配合JSTL標籤一塊兒使用,直接使用EL必須安裝支持Servlet 2.4/JSP2.0或以上版本的JSP容器如:Tomcat5.0以上的版本。
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
EL使用語法
JSP中EL表達式語言的使用語法以下:
${EL expression}
其中:
「$」表示EL中表達式的開始;
「{」是起始分隔符;
EL_expression指定表達式;
「}」是結束分隔符;
接下來將從變量,常量、隱式對象、算術運行符和保留字等多個方面講解EL的具體使用方法。
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
.與 [ ] 運算符
EL 提供「.」和「[ ]」兩種運算符來存取數據。下列二者所表明的意思是同樣的:
${myorder.trade}
等同於
${ myorder["trade"] }
. 和 [ ] 也能夠同時混合使用,以下:
${pageScope[「myorder」].trade}
回傳結果爲你選購中商品的名稱。
不過,如下狀況,二者會有差別:
當要存取的屬性名稱中包含一些特殊字符,如 . 或 – 等並不是字母或數字的符號,就必定要使用「[ ]」,例如:
${ myorder.trade-Name }
上述是不正確的方式,應當改成:
${ myorder ["trade-Name"] }
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
變量與文字常量
EL變量能夠用於存儲和訪問JSP程序中的值。默認狀況下,JSP表達式${myorder}的計算結果與調用pageContext.findAttribute("myorder")同樣。EL表達式中的變量能夠引用存儲在標準範圍(page、request、session和application範圍)中的屬性。變量在標準範圍中的默認搜索順序是page、request、session和application。若是須要,能夠使用toString()方法將變量的返回值轉換成爲字符串;若是找不到變量,則返回null值。
在 EL 表達式中,數字、字符串、布爾值和 null 均可以被指定爲文字值。字符串能夠用單引號或雙引號定界。布爾值被指定爲 true 和 false 。
6.5E+3(或6.5E3) 表示雙精度值6500.0;
7D 表示雙精度值7.0;
.01f 表示單精度值0.01;
'Welcome you'和"Welcom you"都是合法的字符串。
【專家提示】在EL中,"應表示爲\",'應表示爲 \', \應表示爲\\,\(斜槓)稱爲轉義符。
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
EL保留字
EL保留字如表11-1所示。
表11-1 EL保留字

程序員編程過程當中,若是要給變量命名,應該避開上述的名字,以避免程序編譯時發生錯誤。
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
隱式對象
EL隱式對象總共有11 個,詳見表11-2所示。
表11-2 EL隱式對象

表 11-2 中列出了 11 個 EL 隱式對象的標識符。不要將這些對象與 JSP 隱式對象混淆,其中只有一個對象是它們所共有的。儘管 JSP 和 EL 隱式對象中只有一個公共對象( pageContext ),但經過 EL 也能夠訪問其它 JSP 隱式對象。緣由是 pageContext 擁有訪問全部其它八個 JSP 隱式對象的特性。
其他全部 EL 隱式對象都是映射,能夠用來查找對應於名稱的對象。能夠用它們來查找特定做用域中的標識符,而不用依賴於 EL 在缺省狀況下使用的順序查找過程。
接下來咱們經過一個示例演示EL中隱式對象的使用方法。
【例11-2】使用EL隱式對象
UserBean.java
package eldemo;
public class UserBean {
private String name;
private String age;
public UserBean() {
}
public void setName(String name) {
this.name = name;
}
public void setAge(String age) {
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
setimplicit.jsp
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="eldemo.*" %>
<html>
<head>
<title>
setimplicit
</title>
</head>
<body bgcolor="#ffffff">
<%
UserBean user=new UserBean();
user.setName("張三");
user.setAge("18");
request.setAttribute("user",user);
UserBean user1=new UserBean();
user1.setName("李四");
user1.setAge("18");
session.setAttribute("user",user1);
pageContext.forward("getimplicit.jsp?bar=foo");
%>
</body>
</html>
getimplicit.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>
getimplicit
</title>
</head>
<body bgcolor="#ffffff">
我是${user.name}<br>
我仍是${sessionScope['user'].name}<br>
參數是:${param.bar}<br>
主機是:${header['host']}<br>
你的瀏覽器是:${header['User-Agent']}
</body>
</html>
setimplicit.jsp往JSP容器的不一樣做用域中存入變量,而後調用getimplicit.jsp將其取。運行結果如圖11-3所示。

圖11-3 setimplicit.jsp運行結果
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
EL運算符
EL 還包括了幾個用來操做和比較 EL 表達式所訪問數據的運算符,表11-3 中彙總了這些運算符。
表11-3 EL運算符

算術運算符支持數值的加法、減法、乘法和除法。還提供了一個求餘運算符。對幾個 EL 表達式應用算術運算符的結果是將該算術運算符應用於這些表達式返回的數值所得的結果。
【例11-3】使用EL的算術運算符
Arithmetic.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>
基本的算述運算
</title>
</head>
<body bgcolor="#ffffff">
<h1>
基本的算述運算表達式
</h1>
<table border="1">
<thead>
<td><b>EL Expression</b></td>
<td><b>Result</b></td>
</thead>
<tr>
<td>\${1}</td>
<td>${1}</td>
</tr>
<tr>
<td>\${1 + 2}</td>
<td>${1 + 2}</td>
</tr>
<tr>
<td>\${1.2 + 2.3}</td>
<td>${1.2 + 2.3}</td>
</tr>
<tr>
<td>\${1.2E4 + 1.4}</td>
<td>${1.2E4 + 1.4}</td>
</tr>
<tr>
<td>\${-4 - 2}</td>
<td>${-4 - 2}</td>
</tr>
<tr>
<td>\${21 * 2}</td>
<td>${21 * 2}</td>
</tr>
<tr>
<td>\${3/4}</td>
<td>${3/4}</td>
</tr>
<tr>
<td>\${3 div 4}</td>
<td>${3 div 4}</td>
</tr>
<tr>
<td>\${3/0}</td>
<td>${3/0}</td>
</tr>
<tr>
<td>\${10%4}</td>
<td>${10%4}</td>
</tr>
<tr>
<td>\${10 mod 4}</td>
<td>${10 mod 4}</td>
</tr>
<tr>
<td>\${(1==2) ? 3 : 4}</td>
<td>${(1==2) ? 3 : 4}</td>
</tr>
</table>
</body>
</html>
頁面運行結果如圖11-4所示。

圖11-4 Arithmetic.jsp運行結果
關係運算符容許比較數字或文本數據,比較的結果做爲布爾值返回。邏輯運算符容許合併布爾值,返回新的布爾值,還能夠將 EL 邏輯運算符應用於嵌套的關係或邏輯運算符的結果。
最後一種 EL 運算符是 empty ,它對於驗證數據特別有用。 empty 運算符采用單個表達式做爲其變量(也即, ${empty input} ),並返回一個布爾值,該布爾值表示對錶達式求值的結果是否是「空」值。求值結果爲 null 的表達式被認爲是空,即無元素的集合或數組。若是參數是對長度爲零的 String 求值所得的結果,則 empty 運算符也將返回 true 。
【例11-4】使用EL的關係運算符
Comparisons.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>
基本的關係運算
</title>
</head>
<body bgcolor="#ffffff">
<h1>
基本的關係運算示例
</h1>
<blockquote>
<u><b>數字處理</b></u>
<code>
<table border="1">
<thead>
<td><b>EL Expression</b></td>
<td><b>Result</b></td>
</thead>
<tr>
<td>\${1 < 2}</td>
<td>${1 < 2}</td>
</tr>
<tr>
<td>\${1 lt 2}</td>
<td>${1 lt 2}</td>
</tr>
<tr>
<td>\${1 > (4/2)}</td>
<td>${1 > (4/2)}</td>
</tr>
<tr>
<td>\${1 > (4/2)}</td>
<td>${1 > (4/2)}</td>
</tr>
<tr>
<td>\${4.0 >= 3}</td>
<td>${4.0 >= 3}</td>
</tr>
<tr>
<td>\${4.0 ge 3}</td>
<td>${4.0 ge 3}</td>
</tr>
<tr>
<td>\${4 <= 3}</td>
<td>${4 <= 3}</td>
</tr>
<tr>
<td>\${4 le 3}</td>
<td>${4 le 3}</td>
</tr>
<tr>
<td>\${100.0 == 100}</td>
<td>${100.0 == 100}</td>
</tr>
<tr>
<td>\${100.0 eq 100}</td>
<td>${100.0 eq 100}</td>
</tr>
<tr>
<td>\${(10*10) != 100}</td>
<td>${(10*10) != 100}</td>
</tr>
<tr>
<td>\${(10*10) ne 100}</td>
<td>${(10*10) ne 100}</td>
</tr>
</table>
</code>
<br>
<u><b>字符的處理</b></u>
<code>
<table border="1">
<thead>
<td><b>EL Expression</b></td>
<td><b>Result</b></td>
</thead>
<tr>
<td>\${'a' < 'b'}</td>
<td>${'a' < 'b'}</td>
</tr>
<tr>
<td>\${'hip' > 'hit'}</td>
<td>${'hip' > 'hit'}</td>
</tr>
<tr>
<td>\${5 > '4'}</td>
<td>${5 > '4'}</td>
</tr>
</table>
</code>
</blockquote>
</body>
</html>
頁面的運行結果如圖11-5所示。

圖11-5 Comparisons.jsp運行結果
【例11-5】使用EL的邏輯運算符
logic.jsp
<%@ page contentType="text/html; charset=GBK"%>
<html>
<body>
<h1>
邏輯 EL
</h1>
<table border="1">
<tr>
<td>
<b>運算</b>
</td>
<td>
<b>EL 表達式</b>
</td>
<td>
<b>結果</b>
</td>
</tr>
<tr>
<td>
與
</td>
<td>
${'${'}true and true}
</td>
<td>
${true and true}
</td>
</tr>
<tr>
<td>
與
</td>
<td>
${'${'}true && false}
</td>
<td>
${true && false}
</td>
</tr>
<tr>
<td>
或
</td>
<td>
${'${'}true or true}
</td>
<td>
${true or true}
</td>
</tr>
<tr>
<td>
或
</td>
<td>
${'${'}true || false}
</td>
<td>
${true || false}
</td>
</tr>
<tr>
<td>
非
</td>
<td>
${'${'}not true}
</td>
<td>
${not true}
</td>
</tr>
<tr>
<td>
非
</td>
<td>
${'${'}!false}
</td>
<td>
${!false}
</td>
</tr>
</table>
${empty user.name}
</body>
</html>
頁面的運行結果如圖11-6所示。

圖11-6 logic.jsp運行結果
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
禁用EL表達式計算
JSP EL表達式包含在符號「${」與「}」之間。在某些特殊應用中我須要Java服務器不自動執行EL表達式計算工做。所以,有時須要禁用EL表達式,在JSP2.0中默認啓用JSP EL表達式。
在JSP頁面中禁用EL表達式計算語法以下:
<%@page isELIgnored="true|false"%>
其中,page表示頁面指令,isELIgnored肯定是否應忽略對EL表達式進行計算。
若是isELIgnored設置爲true,當EL表達式在靜態文本或標籤屬性中出現時將被忽略;若是isELIgnored設置爲false,EL表達式則由JSP容器進行計算。
下面的例子將演示如何經過使用page指令來禁用或啓用EL表達式計算。
【例11-6】禁用EL表達式
eldisable.jsp
<%@ page contentType="text/html; charset=GBK" isELIgnored="true"%>
<html>
<head>
<title>演示表達式的禁用</title>
</head>
<body bgcolor="#ffffff">
<h1>
EL表達式禁用
</h1>
<%
for (int i = 0; i < 10; i++) {
%>
${header["host"]}
<br>
<%
}
%>
</body>
</html>
頁面的運行結果如圖11-7所示。

圖11-7 eldisable.jsp運行結果
能夠看到頁面把EL表達式完整輸出了,並無進行運算,這是由於禁用了EL表達式後,Web容器並能識別EL表達式。
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
JSTL標籤
JSTL(JavaServer Pages Standard TagLibrary,JSP標準標籤庫)包含用於編寫和開JSP頁面的一組標準標籤,它可爲用戶提供一個無腳本環境,在此環境中,用戶能夠使用標籤編寫代碼,而無需使用Java腳本。JSTL包含有許多實用的標籤,其中迭代標籤和條件標籤用於處理頁面流程控制,國際化標籤爲用戶提供所需的特定區域的語言和輸出格式,SQL標籤用於訪問數據庫和更新數據庫表,XML標籤庫用於操做和解析XML數據。

圖11-8 JSTL標籤庫
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
安裝使用JSTL1.1
JSTL1.1 必須在支持Servlet 2.4 且JSP 2.0 以上版本的容器中才可以使用。JSTL 主要由Apache組織的Jakarta Project 所實現。讀者能夠到以下的網址下載獲得JSTL的安裝包:
http://jakarta.apache.org/builds/jakarta-taglibs/releases/standard/
下載後獲得的文件爲jakarta-taglibs-standard-current.zip。下載完後解壓縮,將lib目錄 中的jstl.jar、standard.jar 複製到當前Web應用的「WEB-INF\lib」中,此後就能夠在當前Web應用的JSP 網頁中使用JSTL了。除了複製 .jar 文件外,最好也把tld 文件的目錄也複製到WEB-INF 中,以便往後使用。接下來將介紹幾類經常使用的JSTL標籤的使用方法。
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
核心標籤庫:通用標籤
JSTL標籤核心標籤庫包含通用標籤、條件標籤、迭代標籤、URL標籤。通用標籤用於操做JSP頁面建立存儲在隱式對象中的變量;條件標籤用於對JSP頁面中的代碼進行條件判斷和處理;迭代標籤用於循環遍歷一個對象集合;URL標籤用於控制頁面的跳轉動做。

圖11-9 JSTL的核心標籤庫
要在JSP頁面中使用核心標籤庫,首先須要導入核心標籤庫的URI。
<%taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
【專家提示】上述的功用在於聲明將使用JSTL 的核心標籤庫。倘若沒有上述聲明指令,將沒法使用JSTL的核心功能,這是讀者在使用JSTL 時要特別注意的地方。
在通用標籤中,下面將重點介紹<c:set>、<c:out>、<c:remove>三個標籤的使用方法。
<c:set>標籤主要用來將變量儲存至JSP 隱式對象中或是JavaBean 的屬性中,其語法爲:
語法1:將 value 的值儲存至範圍爲scope 的 varName 變量之中
<c:set value="value" var="varName" [scope="{ page|request|session|application }"]/>
語法2:將本體內容的數據儲存至範圍爲scope 的 varName 變量之中
<c:set var="varName" [scope="{ page|request|session|application }"]>
本體內容
</c:set>
value:要被儲存的值
var:欲存入的變量名稱
scope:指定變量的JSP 範圍
<c:out>標籤主要用來顯示數據的內容,就像是 <%= scripting-language %> 同樣,其語法爲:
語法1:沒有本體(body)內容
<c:out value="value" [escapeXml="{true|false}"] [default="defaultValue"] />
語法2:有本體內容
<c:out value="value" [escapeXml="{true|false}"]>
default value
</c:out>
value:須要顯示出來的值。
Default:若是value 的值爲null,則顯示default 的值。
escapeXml:是否轉換特殊字符,如:<轉換成<
<c:remove>標籤主要用來移除變量,其語法爲:
<c:remove var="varName" [scope="{ page|request|session|application }"] />
var:欲移除的變量名稱。
scope:var變量的JSP 範圍
接下來看一個使用通用標籤的演示示例。
【例11-7】使用通用標籤
coredemo1.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>JSTL標籤庫中通用標籤</title>
</head>
<body bgcolor="#ffffff">
<P>
該 JSP 頁面在一個 session 做用域內的變量中存儲 sessionvariable, 此 Web 應用程序中的其餘 JSP
頁面能夠訪問此變量.
</p>
<c:set var="sessionvariable" scope="session">
${80+8}
</c:set>
在刪除 sessionvariable 以前先顯示它的值:
<c:out value="${sessionScope.sessionvariable}" />
<c:remove var="sessionvariable" scope="session" />
<br>
顯示並刪除後的 sessionvariable 的值.
<br>
<c:out value="${sessionvariable}"> sessionvariable爲NULL </c:out>
</body>
</html>
頁面的運行結果如圖11-10所示。

圖11-10 coredemo1.jsp運行結果
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
核心標籤庫:條件標籤
條件標籤中將重點介紹<c:if>、<c:choose>、<c:when>和<c:otherwise>四個標籤的使用方法。
<c:if>標籤用於有條件地執行代碼。若是test屬性的值爲true,則會執行<c:if>標籤的標籤體。該標籤是一個容器標籤,其語法爲:
語法1:沒有標籤體內容(body)
<c:if test="testCondition" var="varName"
[scope="{page|request|session|application}"]/>
語法2:有標籤體內容
<c:if test="testCondition" [var="varName"]
[scope="{page|request|session|application}"]>
本體內容
</c:if>
test:若是表達式的結果爲true,則執行標籤體內容,false則相反
var:用來儲存test 運算後的結果,即true 或false
scope:變量的JSP 範圍
<c:choose>標籤相似於Java語言的switch語句,它用於執行條件語句塊。
<c:choose>
本體內容( <when> 和 <otherwise> )
</c:choose>
<c:when>標籤的用途就和Java程序中用的when 同樣。
<c:otherwise>標籤在同一個 <c:choose>標籤中,當全部 <c:when>標籤的條件都沒有成立時,則執行<c:otherwise>標籤的標體內容。
【例11-8】使用條件標籤
coredemo2.jsp
<%@ page contentType="text/html; charset=GBK" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>
JSTL標籤庫中條件標籤
</title>
</head>
<body bgcolor="#ffffff">
<%
int i=(int)(Math.random()*10);
pageContext.setAttribute("signalStrength",new Integer(i));
%>
<c:if test="${pageScope.signalStrength < 5}">
<c:set var="signalFailure" value="true"
scope="page" />
</c:if>
<h1> 使用 If 和 Choose</h1>
<c:choose>
<c:when test="${pageScope.signalFailure == true}">
信號斷開
</c:when>
<c:otherwise>
信號打開
</c:otherwise>
</c:choose>
</body>
</html>
頁面的運行結果如圖11-11所示。

圖11-11 coredemo2.jsp運行結果
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
核心標籤庫:迭代標籤
在跌代標籤中咱們將介紹<c:forEach>標籤和<c:forTokens>標籤這兩個標籤的使用方法。
<c:forEach>標籤爲循環控制,它能夠將集合(Collection)中的成員循序瀏覽一遍。運做方式爲當條件符合時,就會持續重複執行<c:forEach>標籤的標籤體內容。其語法爲:
語法1:迭代一集合對象之全部成員
<c:forEach [var="varName"] items="collection" [varStatus="varStatusName"]
[begin="begin"][end="end"] [step="step"]>
本體內容
< /c:forEach>
語法2:迭代指定的次數
<c:forEach [var="varName"] [varStatus="varStatusName"] begin="begin" end="end"
[step="step"]>
本體內容
</c:forEach>
var:用來存放當前指到的成員。
items:被迭代的集合對象(集合對象類型爲Arrays、Collection、Iterator、Enumeration、Map)。
varStatus:用來存放當前指到的相關成員信息。
begin:開始的位置,倘若有begin 屬性時,begin 必須大於等於 0。
end:結束的位置默認值最後一個成員,倘若有end 屬性時,end必須大於begin。
step:每次迭代的間隔數,倘若有step 屬性時,step 必須大於等於0。
<c:forTokens>標籤用來瀏覽一字符串中全部的成員,其成員是由定義符號(delimiters)所分隔的。使用語法以下:
<c:forTokens items="stringOfTokens" delims="delimiters" [var="varName"]
[varStatus="varStatusName"] [begin="begin"] [end="end"] [step="step"]>
本體內容
</c:forTokens>
var:用來存放如今指到的成員。
items:被迭代的字符串。
delims:定義用來分割字符串的字符。
varStatus:用來存放如今指到的相關成員信息。
begin:開始的位置,倘若有begin 屬性時,begin 必須大於等於 0。
end:結束的位置,倘若有end 屬性時,end必須大於begin。。
step:每次迭代的間隔數,倘若有step 屬性時,step 必須大於等於0。
接下來咱們來看一個跌代標籤的示例程序。
【例11-9】使用迭代標籤
coredemo3.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page import="java.util.*"%>
<html>
<head>
<title>JSTL標籤庫中跌代標籤</title>
</head>
<body bgcolor="#ffffff">
<%
String[] numbers = { "1", "2", "3", "4" };
pageContext.setAttribute("numbers", numbers);
Vector vnumbers = new Vector();
vnumbers.add("1");
vnumbers.add("2");
vnumbers.add("3");
vnumbers.add("4");
vnumbers.add("5");
pageContext.setAttribute("vnumbers", vnumbers);
%>
<c:set var="member" value="Joe:Petter;Ryan|John" scope="page" />
<h1>
數組跌代
</h1>
<c:forEach var="numbering" items="${numbers}">
<c:out value="${numbering}" />
<br>
</c:forEach>
<h1>
集合類跌代
</h1>
<c:forEach var="vnumbering" items="${vnumbers}">
<c:out value="${vnumbering}" />
<br>
</c:forEach>
<h1>
自變量循環
</h1>
<c:forEach var="i" begin="1" end="10" step="1">
<c:out value="${i}" />
<br />
</c:forEach>
<h1>
字符串分割
</h1>
<c:forTokens items="${pageScope.member}" delims=":;|" var="membername">
<c:out value="${membername}" />
<br />
</c:forTokens>
</body>
</html>
頁面的運行結果如圖11-12所示。

圖11-12 coredemo3.jsp運行結果
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
核心標籤庫:URL標籤
下面將介紹URL標籤中的<c:import>、<c:redirect>和<c:url>三個標籤的使用方法。
<c:import>標籤能夠把其餘靜態或動態文件包含至自己JSP 網頁。它和JSP動做指令的<jsp:include>最大的差異在於:<jsp:include>只能包含和本身同一個Web應用下的文件;而<c:import>除了能包含和本身同一個web application 的文件外,亦能夠包含不一樣Web應用或者是其餘網站的文件。
語法1:
<c:import url="url" [context="context"] [var="varName"]
[scope="{page|request|session|application}"] [charEncoding="charEncoding"]>
本體內容
</c:import>
語法2:
<c:import url="url" [context="context"]
varReader="varReaderName" [charEncoding="charEncoding"]>
本體內容
</c:import>
url:被包含文件的地址 。
context:在相同Web容器下,其餘web應用必須以「/」開頭。
var:儲存被包含的文件的內容(以String類型存入) 。
scope:變量的JSP 做用域 。
charEncoding:被包含文件以內容的編碼格式 。
varReader:儲存被包含的文件的內容(以Reader類型存入)。
例如:
<c:import url="http://www.csai.cn" />的功能是:用<c:import>把http://www.csai.cn 的內容加到網頁中。
<c:url>標籤主要用來產生一個URL。
語法1:沒有標籤體內容
<c:url value="value" [context="context"] [var="varName"]
[scope="{page|request|session|application}"] />
語法2:有標籤體內容表明查詢字符串(Query String)參數
<c:url value="value" [context="context"] [var="varName"]
[scope="{page|request|session|application}"] >
<c:param> 標籤
</c:url>
value:執行的URL。
context:在相同Web容器下,其餘web應用必須以「/」開頭。
var:儲存被包含文件的內容(以String 類型存入)。
scope:變量的JSP做用域。
例如:
<c:url value="http://www.csai.cn">
<c:param name="figure " value="希賽顧問"/>
</c:url>
會產生一個「http://www.csai.cn?figure=希賽顧問」的超連接。
<c:redirect>標籤能夠將客戶端的請求從一個JSP 網頁導向到其餘文件。
語法1:沒有標籤體內容
<c:redirect url="url" [context="context"] />
語法2:有標籤體內容表明查詢字符串(Query String)參數
<c:redirect url="url" [context="context"] > <c:param> </c:redirect >
url:導向的目標地址 。
context:相同Container 下,其餘web 站臺必須以「/」開頭。
例如:
<c:redirect url="http://www.csai.cn" />,那麼網頁將會自動導向到http://www.csai.cn。
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
I18N與格式化標籤庫
國際化(I18N)與格式化標籤庫可用於建立國際化的Web應用程序,它們對數字和日期、時間的輸出進行了標準化。國際化的應用程序支持多語言。在JSP頁面中導入國際化與格式化標籤庫的語法是:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
本章中咱們將重點介紹經常使用的<fmt:setLocale>、<fmt:bundle>、<fmt:setBundle>、<fmt:message>幾個經常使用標籤的使用方法。
<fmt:setLocale>標籤用於重寫客戶端指定的區域設置。它將區域設置存儲在javax.servlet.jsp.jstl.fmt配置變量中。setLocale是一個空標籤,其使用語法爲:
<fmt:setLocale value="setting" variant="variant"
scope="page/request/session/application"/>
value:包含一個含有兩個小寫字母的語言代碼和一個含有兩個大寫字母的國家或地區代碼。語言和國家或地區代碼應該用連字符或下劃線分隔如:zh_CN。
variant:指定特定於瀏覽器的變量,它是可選的。
scope:指定配置變量的範圍。
接下來看一個使用<fmt:setLocale>示例
【例11-10】使用<fmt:setLocale>標籤
fmt_setlocal.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ page import="java.util.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<html>
<head>
<title>設置local方式來顯示不一樣數值,日期,時間格式</title>
</head>
<body bgcolor="#ffffff">
<%
Date now = new Date();
pageContext.setAttribute("now", now);
out.println("本地:" + request.getLocale().toString() + "<br>");
%>
<H2>
數字格式示例
</H2>
將
<B>123.41234"</B> 格式化爲:
<fmt:formatNumber value="123.41234" type="number"
maxFractionDigits="2" />
<BR>
<HR>
<H2>
貨幣格式示例
</H2>
<c:set var="salary" value="125000" />
工資:
<c:out value="${salary}" />
<BR>
<fmt:setLocale value="en_US" />
用本機的
<B>en_US</B> 將工資格式化爲:
<fmt:formatNumber type="currency" value="${salary}" />
<BR>
日期:
<fmt:formatDate value="${now}" />
<br>
<fmt:setLocale value="zh_CN" />
用本機的
<B>zh_CN</B> 將工資格式化爲:
<fmt:formatNumber type="currency" value="${salary}" />
<BR>
日期:
<fmt:formatDate value="${now}" />
<br>
<HR>
</body>
</html>
頁面的運行結果如圖11-13所示。

圖11-13 fmt_setlocal.jsp運行結果
<fmt:bundle>標籤用於建立一個I18N本地化上下文,並將它的資源包加載到其中。資源包的名稱由<fmt:bundle>標籤的basename屬性指定。此標籤的語法爲:
<fmt:bundle basename="basename">
本體內容
</fmt:bundle>
<fmt:message>標籤用於給出資源包的輸出值。<fmt:message>標籤的語法爲:
<fmt:message key="messagekey ">
其中,key屬性指定消息的關鍵字。
接下來經過一個示例演示<fmt:bundle>和<fmt:message>的用法。
定義好的資源包文件存放在web應用目錄下的「WEB-INF/classes」目錄下,如:
input.properties
title=this is fmtdemo!
hello=hello world
中文內容版爲input_zh_CN1.properties
title=國際演示!
hello=朋友你好
country=你的國家
因爲Java對於資源文件的處理只支持單字節,因此對中文資源須要使用:
native2ascii -encoding gb2312 input_zh_CN1.properties input_zh_CN.properties
對中文資源文件進行編碼生成單字節的input_zh_CN.properties資源文件。
title=\u56fd\u9645\u6f14\u793a!
hello=\u670b\u53cb\u4f60\u597d
country=\u4f60\u7684\u56fd\u5bb6
【例11-11】用標籤使用資源文件
Fmt_resouce1.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<html>
<head>
<fmt:bundle basename="input">
<title><fmt:message key="title" /></title>
</head>
<body bgcolor="#ffffff">
<h1>
<fmt:message key="hello" />
</h1>
</fmt:bundle>
</body>
</html>
運行結果,如圖11-14所示。

圖11-14 Fmt_resouce1.jsp運行結果
接下來按圖 11-15所示的方式修改瀏覽器的語言設置。

圖11-15 修改瀏覽器的語言設置
修改後Fmt_resouce1.jsp的運行結果,如圖11-16所示。

圖11-16 Fmt_resouce1.jsp運行結果
<fmt:setBundle>:建立一個I18N本地化上下文,並將它存儲在範圍變量中。該標籤是一個空標籤。其語法爲:
<fmt:setBundle basename="basename" var="varName"
scope="page/request/session/application"/>
basename:指定資源包的名稱。
var:指定導出的範圍變量的名稱,它存儲I18N本地化上下文。
scope:指定var的範圍。
接下來經過一個示例程序看看如何使用<fmt:setBundle>。
【例11-12】使用<fmt:setBundle>標籤
Fmt_resouce.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<html>
<head>
<fmt:setLocale value="zh_CN" scope="page" />
<fmt:setBundle basename="input" scope="page" />
<title><fmt:message key="title" /></title>
</head>
<body bgcolor="#ffffff">
<h1>
<fmt:message key="hello" />
</h1>
</body>
</html>
Fmt_resouce.jsp的運行結果如圖11-17所示。

圖11-17 Fmt_resouce.jsp運行結果
採用這種方式載入資源包會發現就算採用圖11-15的方式修改瀏覽器的語言設置其運行結果始終如圖11-17所示。
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
SQL標籤庫
JSTL的SQL標籤用於訪問各類關係數據庫,是爲了基於Web的小型應用程序而設計的。它提供的各類標籤可用於在JSP頁面內直接訪問數據庫,在JSP頁面中導入SQL標籤庫的語法是:
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>
這樣每一個SQL標籤庫中的標籤都冠以一個<sql>前綴,本章咱們將重點介紹<sql:setDataSource>、<sql:query>、<sql:update>、<sql:transaction>等幾個經常使用標籤的使用方法。
<sql:setDataSource>標籤用於爲數據庫設置數據源。它是一個空標籤,容許用戶爲數據庫設置數據源信息,其語法爲:
<sql:setDataSource DataSource="datasource" url="jdbcurl"
driver="driverclassdriver" user="username" password="usepwd"
var="varname" scope="page|request|session|application"/>
DataSource:能夠是Java命名和目錄接口(JNDI,Java Naming and Directory Interface)資源的路徑或JDBC參數字符串。
url:是與數據庫關聯的URL。
driver:是一個JDBC參數,其值爲驅動程序的類名。
user:是數據庫的用戶名。
password:是用戶的密碼。
var:是指定數據源的導出範圍變量的名稱。
scope:指定範圍。
【專家提示】在<sql:setDataSource>中,若是使用了DataSource屬性,則沒法使用url屬性。
<sql:query>標籤用於搜索數據庫並返回包含數據行的結果集。其語法爲:
<sql:query var="varname" dataSource="datasource"
scope="page|request|session|application" maxRows="maxrows"
startRow="startRow">
要執行的SQL語句
<sql:param/>
</sql:query>
var:爲查詢結果指定導出的範圍變量的名稱。
scope:指定變量的範圍。
dataSource:指定與要查詢的數據庫關聯的數據源。
maxRows:指定結果中所包含的數據的最大行數。
startRow:指定從指定索引開始的數據行。
<sql:update>標籤用於執行INSERT、UPDATE和DELETE語句。若是全部數據行都沒有受到插入、更新或刪除操做的最響,則會返回0。其語法爲:
<sql:update datasource="datasource" var="varName"
scope="page|request|session|application ">
SQL語句
<sql:param/>
</sql:update>
其中:
SQL語句:指定UPDATE、INSERT或DELETE語句。
dataSource:是與要更新的數據庫關聯的數據源。
var:爲數據庫更新的結果指定導出的範圍變量的名稱。
scope:指定變量的範圍。
<sql:transaction>標籤用於爲<sql:query>標籤和<sql:update>標籤創建事務處理上下文。
<sql:transaction dataSource="datasource" isolation="isolationLevel">
使用<sql:query>或<sql:update>語句
</sql:transaction>
dataSource:設置SQL的數據源,它能夠是字符串或一個DataSource對象。
isolation:設置事務處理的隔離級別。隔離級別能夠是read_committed、read_uncommitted、repeatable_read或serializable。
接下來演示一個使用SQL標籤的示例程序。
【例11-13】使用SQL標籤
sqldemo.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>
<html>
<head>
<title>sqldemo</title>
</head>
<body bgcolor="#ffffff">
<h1>
使用 SQL 標籤庫
</h1>
<c:set var="valprice" value="1000" />
<sql:setDataSource
driver="com.microsoft.jdbc.sqlserver.SQLServerDriver"
url="jdbc:microsoft:sqlserver://localhost:1433;DataBaseName=pubs"
user="sa" password="" var="conn" />
<sql:transaction dataSource="${conn}">
<sql:update var="newTable">
CREATE TABLE ProductDetails
(
ProductId int IDENTITY (1000, 1) NOT NULL primary key,
ProductName varchar (20) NOT NULL ,
ProductType varchar (15) NOT NULL ,
Price varchar (5) NOT NULL ,
Brand varchar (25) NOT NULL ,
Description varchar (50) NOT NULL
)
</sql:update>
</sql:transaction>
<sql:update var="newrow" dataSource="${conn}">
INSERT INTO ProductDetails(ProductName, ProductType,
Price, Brand, Description)
VALUES('JSP專家導學 ', '編程書籍', '1000', 'Lee', '適合大專院校的教材或參考書籍')
</sql:update>
<sql:query var="products" dataSource="${conn}">
select * from ProductDetails
</sql:query>
<table border="1">
<c:forEach items="${products.rows}" var="row">
<tr>
<td>
${row.ProductName}
</td>
<td>
${row.ProductType}
</td>
<td>
${row.Price}
</td>
<td>
${row.Description}
</td>
</tr>
</c:forEach>
</table>
</body>
</html>
頁面的運行結果如圖11-18所示。

圖11-18 sqldemo.jsp運行結果
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
XML標籤庫
JSTL提供了一些有關XML的標籤,讓開發人員能夠不用深刻了解SAX和DOM等API,就能夠輕易地處理XML文件。在JSP頁面中導入XML標籤庫的語法是:
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
這裏將介紹<x:parse>、<x:out>和<x:set>幾個標籤的使用方法。
<x:parse>標籤用來解析XML文件。使用<x:parse>標籤的語法爲:
<x:parse {var="var" [scope="{page|request|session|application}"] |varDom="var"
[scopeDom="{page|request|session|application}"]}
[systemId="systemId"] [filter="filter"]>
須要解析的XML文檔
</x:parse>
var:儲存解析後的XML文件。
scope:變量的JSP範圍。
varDom:儲存解析後的XML文件(類型爲org.w3c.dom.Document)。
scopeDom:的範圍。
systemId :XML文件的URI。
filter:XMLFilter過濾器。
<x:out> 標籤主要用來取出XML中的節點值。
<x:out select=」XPathExpression」 [escapeXml=」{true|false}」]/>
其中:
select XPath語句。
escapeXml 是否轉換特殊字符,例如:<轉換成&It;
【專家提示】有關XPath的內容請讀者參考本系列叢書中《專家導學Java與XML應用開發》相關內容。
<x:set> 將從XML文件中取得內容存儲至JSP範圍中。
語法爲:
<x:set select="XPathExpression" var="var"
[scope="{page|request|session|application}"]/>
其中:
select:XPath語句。
var:將從XML文件中取得的內容儲存至varName中。
scope:變量的JSP範圍。
【例11-14】使用XML標籤
Books.xml
<?xml version="1.0" encoding="GBK"?>
<books>
<book lang="java">
<title>《Java 編程思想》</title>
<author>Bruce Eckel</author>
</book>
<book lang="java">
<title>《JSP 專家導學》</title>
<author>希賽顧問團</author>
</book>
<book lang=".net">
<title>《專家導學.NET開發框架》</title>
<author>希賽顧問團</author>
</book>
</books>
xmldemo.jsp
<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<html>
<head>
<title>XML標籤示例程序</title>
</head>
<body>
<x:parse var="sampleXml">
<c:import charEncoding="GBK" url="Books.xml"/>
</x:parse>
<h3>裝載XML文件成功</h3>
<h3>顯第一本書的標題:</h3>
<x:out select="$sampleXml//title"/><br/>
<h3>查找.net書:</h3>
<x:set select="$sampleXml//book[@lang='.net']" var="DoNetBook" />
<x:out select="$DoNetBook"/>
</body>
</html>
頁面的運行結果如圖11-19所示。

圖11-19 xmldemo.jsp運行結果
【專家提示】使用XML標籤時,Web應用環境中除在「WEB-INF/lib」目錄下加入jstl.jar和standard.jar外還應加入xalan.jar和xercesImpl.jar兩個文件。
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
自定義標籤
標籤把服務器端複雜的處理邏輯封裝起來,提供給表示層的編寫人員調用,書寫標籤就象書寫HTML代碼同樣容易,同時也容易被理解和閱讀。然而,JSTL提供的標籤畢竟有限,有時,程序員也須要本身編寫標籤,封裝一些處理邏輯。
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
簡單標籤(Simple Tag)
在JSP1.1時,新增了JSP標籤函數,它最大的功用在於讓用戶可以自行制訂一個標籤,例如前面所講的JSTL標籤都是屬於此類。以往開發標籤時,不是繼承TagSupport,就是繼承BodyTagSupport類,而後實現doStartTag()、doEndTag()或doAfterBody()方法,並且還要搞清楚這些方法的回傳值,如:EVAL_BODY_INCLUDE,EVAL_PAGE、SKIP_BODY、SKIP_PAGE、EVAL_BODY_AGAIN等等。
JSP2.0爲了簡化開發標籤的複雜性,所以增長了一個製做Simple Tag的SimpleTagSupport類。SimpleTagSupport類是實現SimpleTag接口的,它只需要實現一個doTag()的方法便可,而再也不須要一堆回傳值。使用標籤處理程序實現自定義標籤三個步驟:
編寫標籤處理程序(Java 類)。
編寫標籤庫描述符(提供有關標籤和庫文件的元信息的 XML 文件)
JSP 實現(包含自定義標籤的 JSP 文件)
【例11-15】開發簡單的自定義標籤
標籤處理程序的源代碼以下。
SimpleTagDemo.java
package customtag;
import javax.servlet.jsp.tagext.*;
import java.io.*;
import java.util.*;
import javax.servlet.jsp.*;
/**
* @author Administrator
*
*/
public class SimpleTagDemo extends SimpleTagSupport {
private int num;
public void setNum(int num) {
this.num = num;
}
public void doTag() throws JspException, IOException {
JspWriter out = this.getJspContext().getOut();
out.println("<h1>演示" + num + "次輸出標籤體的內容</h1>");
for (int i = 0; i < num; i++) {
getJspContext().setAttribute("count", String.valueOf(i + 1));
getJspBody().invoke(null);
}
}
}
標籤描述tld文件的內容以下。
simpledemo.tld
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>
A tag library exercising SimpleTag handlers.
</description>
<tlib-version>1.0</tlib-version>
<short-name>SimpleTagLibrary</short-name>
<uri>/SimpleTagLibrary</uri>
<tag>
<description>Outputs Hello, World</description>
<name>simpletagdemo</name>
<tag-class>customtag.SimpleTagDemo</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>num</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
tlib-version:是必須元素,指定標記庫函數的版本號,例如:
<tlib-version>1.0.123.123.234</tlib-version>。
short-name:爲標記庫指定一個縮略名稱,用它能夠做爲標記庫的缺省名字空間,如:
< short-name >demotaglib</ short-name >
info:用來描述標記的文檔信息,缺省值爲空
uri:用來指定鏈接到標記的附加源文件,即TLD的公共可用副本。
tag:是標記描述文件中最重要的一個元素,與其它元素不一樣的是,它能夠有子元素。tag元素有六個子元素:name、tagclass、teiclass、bodycontent、info、attribute。name子元素用戶指定的標記名稱;tag-class子元素指定標記處理類,此處應該是全限定名稱,即帶包名的類;bod-ycontent子元素說明標記體的類型,分爲四種:empty、jsp、scriptless、tagdependent,empty表示沒有標記體,jsp表示標記體能夠爲jsp代碼,scriptless表示標記中不能用jsp腳本,tagdependent表示標籤中的內容交給標記處理程序去進行處理;info記錄標記的描述信息;attribute用來指定零個或者多個標記屬性,這個元素又有三個子元素:name, required, rtextprvalue,name子元素是必須設定的元素,用來表示大小寫敏感屬性名稱,required子元素是必須設定的元素,標識屬性是否必定要存在,默認爲false,若是設置爲flase,則在標記處理程序中不會自動去調用屬性的setAttribute方法,rtextprvalue子元素用來講明屬性是否能夠是動態生成的,但設定爲true時,屬性既能夠是一個常量值,也能夠由表達式動態生成。
simpletagdemo.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ taglib uri="/WEB-INF/simpledemo.tld" prefix="mytag"%>
<html>
<head>
<title>simpletagdemo演示示例</title>
</head>
<body bgcolor="#ffffff">
<h1>
結果
</h1>
<mytag:simpletagdemo num="7">
重複輸出數據:${count} of 7<br>
</mytag:simpletagdemo>
</body>
</html>
頁面的運行結果如圖11-20所示。

圖11-20 simpletagdemo.jsp運行結果
【思考1】JSP標記與JavaBean有何區別?
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
標籤文件
標籤文件是JSP2.0新增的主要功能之一。根據JSP2.0規範中的定義:所謂的Tag File就是讓JSP網頁開發人員能夠直接使用JSP語法來製做標籤,而不須瞭解Java語言。
全部Tag File文件的擴展名都爲.tag或.tagx。倘若Tag File包含其餘完整或片斷的Tag File,JSP2.0規範建議擴展名爲.tagf。
JSP2.0標籤文件的新特性有:
Tag File的七個隱式對象
request、response、out、jspContext、session、application、config。
Tag File的指令

新增的幾個動做
<jsp:attribute>標籤用來指定自定義標籤屬性塊,必要時能夠做爲代碼段輸出。
<jsp:doBody>標籤告訴容器去處理body,而且將處理結果添加到response中。你能夠有選擇性的使用「var」 屬性,捕獲處理的結果,並在下一步進行處理。
<jsp:invoke>標籤對做爲屬性傳遞的特定參數進行操做
【例11-16】開發與使用標籤文件
datetag.tag
<%@tag pageEncoding="GBK"%>
<%@tag import="java.util.*,java.text.*"%>
<%@variable name-given="fulldate" scope="AT_BEGIN"%>
<%
DateFormat fullformate = DateFormat.getDateInstance(DateFormat.FULL);
Date now = new Date();
jspContext.setAttribute("fulldate", fullformate.format(now));
%>
<jsp:doBody/>
simpletagdemo2.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ taglib prefix="mytag" tagdir="/WEB-INF/tags/"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>datetag</title>
</head>
<body bgcolor="#ffffff">
<h1>
日期tag標籤文件演示
</h1>
<mytag:datetag>
標籤體的輸出:${fulldate}<br>
</mytag:datetag>
頁面的輸出:${fulldate}
</body>
</html>
頁面的運行結果如圖11-21所示。

圖11-21 simpletagdemo2.jsp運行結果
sumtag.tag
<%@tag pageEncoding="GBK"%>
<%@attribute name="items" required="true" rtexprvalue="true"%>
<%@attribute name="great" fragment="true"%>
<%@attribute name="less" fragment="true"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@variable name-given="sum" variable-class="java.lang.Object"%>
<c:if test="${not empty items}">
<c:forEach items="${items}" var="item">
<c:set var="sum" value="${item+sum}" />
</c:forEach>
<c:if test="${sum>=1000}">
<jsp:invoke fragment="great" />
</c:if>
<c:if test="${sum<1000}">
<jsp:invoke fragment="less" />
</c:if>
</c:if>
sumtag.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ taglib prefix="mytag" tagdir="/WEB-INF/tags/"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>sumtag</title>
</head>
<body bgcolor="#ffffff">
<h1>
tag標籤文件演示
</h1>
<mytag:sumtag items="111,222,333">
<jsp:attribute name="great">
<font color="red"> SUM: ${sum}</font>
</jsp:attribute>
<jsp:attribute name="less">
<font color="blue"> SUM: ${sum}</font>
</jsp:attribute>
</mytag:sumtag>
</body>
</html>
頁面的運行結果如圖11-22所示。

圖11-22 sumtag.jsp 運行結果
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
小結
經過本章學習讀者應能掌握EL表達式語言的語法及各類運算符的使用;熟練運用掌握JSTL標籤核心標籤、I18N與格式化標籤庫、SQL標籤庫和XML標籤使用方法;還能用兩種自定義標籤的定義方法(簡單標籤和標籤文件)來開發標籤。在學習完本章後讀者應可以利用EL和標籤技術來開發Web應用,取代傳統直接在頁面上嵌入Java程序的作法,以提升程序的閱讀性、維護性和方便性。
版權方受權希賽網發佈,侵權必究
第 11 章:表達式與標籤做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
思考解答
【思考1】JSP標記與JavaBean有何區別?
答:JavaBean存在先天的不足,它只是可複用的組件,獨立於運行環境而包裝了一些數據和業務邏輯功能,沒法得到運行環境信息,沒法與jsp頁面進行更加深層次的交互。
自定義標記機制,解決了JavaBean的這種缺陷,標記庫的處理類,不但具備javabean的功能,並且能夠jsp的環境信息傳送到類中間,不但能獲得jsp傳遞過來的屬性,並且還能得與jsp共用頁面環境,jsp 頁面中能夠經過session、page與標記處理程序進行數據通訊,這一點是javaBean所不能實現的。
第12章 Web圖表開發
【本章專家知識導學】
Web統計圖形和報表的開發每每是令程序員感到頭痛、棘手的問題,但在各類管理信息系統倒是很常見的,好在JSP開發如今已經有了許多開源的組件,有了這些組件,程序員就沒必要再編寫大量的代碼,也沒必要關注Java底層的圖形圖象知識,只需編寫少許的代碼便可快速開發出漂亮的統計圖形和報表,還能實現打印、導出成Excel、Word文件等強大的功能。
本章將給讀者介紹兩款快速進行Web統計圖形和報表的開發工具——JFreeChart和JavaReport。JFreeChart用於圖形的開發;JavaReport既可用於圖形的開發也可用於報表的開發。掌握這兩個組件來開發出適用的圖形和報表並不難,下面就一塊兒來學習。
12.1 JFreeChart組件介紹
程序員開發Java Web系統常常碰到須要開發Web圖形與報表的情形,若是是C/S模式的開發,由於有集成開發工具的支持,如Microsft Visual Studio,開發圖形與報表變得快捷,然而Web開發就顯得比較麻煩了。
有程序員可能嘗試過調用Office的ocx組件的方式來顯示圖形,這要求客戶端必需要安裝有office軟件,但有時客戶端使用的多是WPS Office或其它的辦公軟件,這就使得Web系統失去了通用性。那麼有沒有別的方法實現呢?JDK中帶有圖形開發的軟件包AWT,然而,從事應用軟件系統開發的程序員並不是圖形圖像方面的專家,短期內沒法掌握JDK中AWT的開發,何況這還要求程序員瞭解較多的底層API。所以,能夠考慮使用比較成熟的第三方的組件包來實現。
JFreeChart是一個開源的組件包,它提供了Java中經常使用統計圖形的快速開發API,程序員只要掌握少許的接口就能繪製出漂亮的圖形,並且這些圖形不只可用於帶有客戶端界面的Java應用程序中,也能夠是在JSP, Servlet, Java Applet中。本章中將主要介紹在JSP中如何使用JFreeChart組件包開發經常使用的圖形,若是要在Servlet、應用程序或Java Applet中實現相似的功能,可自行參考JSP編程方法實現的程序來編寫代碼。
JFreeChart可用於建立餅圖、線圖、柱狀圖、散點圖、甘特圖等。能夠從以下的網址獲得許多有關於JFreeChart的詳細信息:
http://www.jfree.org/jfreechart/
本書使用的JFreeChart版本是至本書成稿之日最新的1.0.5,可從以下的網址下載獲得:
http://downloads.sourceforge.net/jfreechart/jfreechart-1.0.5.zip?modtime=1174667923&big_mirror=0
從如下的地址能夠獲得JFreeChart1.0.5的HTML格式的詳細API說明文檔:
http://downloads.sourceforge.net/jfreechart/jfreechart-1.0.5-javadocs.zip?modtime=1174668033&big_mirror=0
要在JSP中用JFreeChart開發Web圖表,就須要安裝JFreeChart組件包。將JFreeChart的zip壓縮包jfreechart-1.0.5.zip解壓縮,解壓縮軟件能夠使用WinRar、WinZip等。在解壓後獲得的目錄的lib子目錄中的全部jar包拷貝到Web應用的WEB-INF/lib目錄下,便可在JSP中使用JFreeChart了。
【專家提示】上段所述的這種安裝方法僅對當前Web應用有效,若是要讓當前網站中的全部的Web應用均可以使用JFreeChart1.0.5,則應將jar包拷貝到Tomcat5的安裝目錄的common/lib子目錄中。
JFreeChart1.0.5須要JDK1.3版本或更高版本的JDK環境做爲支持,使用了JDK中的Java 2D API來做圖。JFreeChart1.0.5還使用到了JCommon組件,能夠從以下的地址獲得有關JCommon的更多信息:
http://www.jfree.org/jcommon/index.html
JFreeChart1.0.5的lib子目錄中已帶用JCommon組件包jcommon-1.0.9.jar,沒必要再行安裝JCommon組件。
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
JFreeChart的應用
下面開始學習使用JFreeChart。這裏並不想立刻就介紹JFreeChart的類、API等參考性的內容,先看簡單的實例,再學會一些複雜一點的實例,再給出經常使用的類及其API參考。若是須要給圖形制做一些特效或細膩的顯示效果,請讀者參考JFreeChart的javadocs以瞭解更詳細的API。
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
建立第一個簡單的餅圖
用JFreeChart建立Web圖形須要通過三個步驟:
第一步:建立一個包含要在Web圖形中顯示的數據的數據集對象。
第二步:建立一個用於做圖的JFreeChart對象。
第三步:向目標做圖。Web圖表的做圖目標爲response.getOutputStream(),即response對象的輸出流。
【例12-1】 一個簡單的餅圖
下面以建立一個簡單的餅形圖(用戶年齡階段分佈統計圖)爲例。
第一步:建立一個包含要在Web圖形中顯示的數據的數據集對象。代碼以下:
String dataName[]=new String[]{"0-30歲","30-50歲","50-70歲","70歲以上"};//顯示數據系列
int dataValueCount[]={4,5,4,6};//數據系列對應的值
DefaultPieDataset pieDataset = new DefaultPieDataset();
for(int i=0;i<dataName.length;i++)
pieDataset.setValue(dataName[i],dataValueCount[i]);
【專家提示】餅圖的數據集對象能夠是實現了JFreeChart組件中的PieDataset接口的類的實例,讀者能夠自行編寫類實現,也能夠使用JFreeChart組件中已有的已實現了PieDataset接口的DefaultPieDataset類,更加方便和快捷。
第二步:建立一個用於做圖的JFreeChart對象。代碼以下:
String titleString="用戶年齡階段分佈統計圖";//圖的標題
JFreeChart chart = ChartFactory.createPieChart(titleString,//圖形標題
pieDataset,//數據集
true, //是否顯示圖例
true, //是否有工具提示
false//是否有URL
);
ChartFactory是一個工廠類,可用於建立JFreeChart對象。這裏使用的方法是createPieChart()方法,參數做了簡單的設置。建立JFreeChart對象的方法還有許多種形式,這裏僅給出簡單的一種,有興趣能夠參考本章後續的JFreeChart經常使用類的說明。
第三步:向目標做圖。代碼以下:
ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,500,300);
下面結出本實例的完整代碼。
firstPie.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="org.jfree.chart.JFreeChart,org.jfree.chart.ChartUtilities,
org.jfree.chart.ChartFactory,org.jfree.data.general.DefaultPieDataset"%>
<html>
<body>
<%
//第一步:建立一個包含要在Web圖形中顯示的數據的數據集對象
String dataName[]=new String[]{"0-30歲","30-50歲","50-70歲","70歲以上"};//顯示數據系列
int dataValueCount[]={4,5,4,6};//數據系列對應的值
DefaultPieDataset pieDataset = new DefaultPieDataset();
for(int i=0;i<dataName.length;i++)
pieDataset.setValue(dataName[i],dataValueCount[i]);
//第二步:建立一個用於做圖的JFreeChart對象
String titleString="用戶年齡階段分佈統計圖";//圖的標題
JFreeChart chart = ChartFactory.createPieChart(titleString,pieDataset,true,true, false);
//第三步:向目標做圖。
ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,500,300);
%>
</body>
</html>
程序的運行效果如圖12-1所示。

圖12-1 第一個簡單的餅圖
【專家提示】若是數據集中的數據來源於數據庫中,則能夠在第一步中編寫程序從數據庫中取出數據,再設置數據集中的數據,第二步與第三步仍照舊,便可以圖形方式顯示數據庫中的數據了。
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
建立條形圖
用JFreeChart建立條形圖主要須要用實現了CategoryDataset接口或IntervalXYDataset接口的類的實例來做爲數據集對象,經常使用JFreeChart中自帶的已實現了CategoryDataset接口的DefaultCategoryDataset類。
【例12-2】 建立條形圖
建立條形圖一樣須要經歷與建立餅形圖相似的三步。本例將生成一個表示用戶年齡階段分佈的條形圖。
第一步:建立一個包含要在Web圖形中顯示的數據的數據集對象。代碼以下:
String dataName[]=new String[]{"0-30歲","30-50歲","50-70歲","70歲以上"};//顯示數據系列
int dataValueCount[]={4,5,4,6};//數據系列對應的值
//------建立數據集,並設置值------
DefaultCategoryDataset categoryDataset = new DefaultCategoryDataset();
for(int i=0;i<dataName.length;i++)
categoryDataset.addValue(dataValueCount[i],dataName[i],dataName[i]);
第二步:建立一個用於做圖的JFreeChart對象。代碼以下:
String titleString="用戶年齡階段分佈統計圖";//圖的標題
JFreeChart chart = ChartFactory.createBarChart(titleString,//圖形標題
"用戶年齡階段",//分類軸標籤(默認爲橫向)
"數量",//數值軸標籤(默認爲縱向)
categoryDataset,//數據集
PlotOrientation.VERTICAL,//圖形顯示方向,豎向
true,//是否顯示圖例
true,//是否有工具提示
false//是否有URL
);
第三步:向目標做圖。
ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,500,300);
下面結出本實例的完整代碼。
barChartd.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="org.jfree.chart.JFreeChart,org.jfree.chart.ChartUtilities,
org.jfree.chart.ChartFactory,
org.jfree.chart.plot.PlotOrientation,
org.jfree.data.category.DefaultCategoryDataset"%>
<html>
<body>
<%
//第一步:建立一個包含要在Web圖形中顯示的數據的數據集對象
String dataName[]=new String[]{"0-30歲","30-50歲","50-70歲","70歲以上"};//顯示數據系列
int dataValueCount[]={4,5,4,6};//數據系列對應的值
//------建立數據集,並設置值------
DefaultCategoryDataset categoryDataset = new DefaultCategoryDataset();
for(int i=0;i<dataName.length;i++)
categoryDataset.addValue(dataValueCount[i],dataName[i],dataName[i]);
//第二步:建立一個用於做圖的JFreeChart對象
String titleString="用戶年齡階段分佈統計圖";//圖的標題
JFreeChart chart = ChartFactory.createBarChart(titleString,"用戶年齡階段","數量",
categoryDataset,PlotOrientation.VERTICAL,true,true,false);
//第三步:向目標做圖。
ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,500,300);
%>
</body>
</html>
程序的運行效果如圖12-3所示。

圖12-3 建立條形圖
條形圖的顯示也能夠做一些定製性的修改,經常使用的修改有:
(1)修改圖形的背景顏色
修改條形圖的背景顏色使用以下的方法:
chart.setBackgroundPaint(new Color(0xBBBBDD));
chart是JFreeChart實例的名稱。
(2)修改圖形的柱狀條顏色
修改圖形的柱狀條顏色須要使用setSeriesPaint()方法,但這個方法並不是JFreeChart類的方法,而須要先用JFreeChart類的實例的getCategoryPlot()獲得一個CategoryPlot對象,再用CategoryPlot對象的getRenderer()方法獲得一個BarRenderer對象,用BarRenderer對象的setSeriesPaint()方法來設置柱狀條的顏色,如:
CategoryPlot plot = chart.getCategoryPlot();
BarRenderer renderer = (BarRenderer) plot.getRenderer();
renderer.setSeriesPaint(0, Color.red);
renderer.setSeriesPaint(1, Color.green);
renderer.setSeriesPaint(2, Color.blue);
(3)柱狀條的間距
JFreeChart容許修改類型軸的一些設置,如:
第一條柱狀條與數值軸之間的空白間距。
柱狀條之間的空白間距。
最後一條柱狀條後的空白距離。
此三項的設置方法示例以下:
CategoryPlot plot = chart.getCategoryPlot();
CategoryAxis axis = plot.getDomainAxis();
axis.setLowerMargin(0.02); //百分之二
axis.setCategoryMargin(0.10); //百分之十
axis.setUpperMargin(0.02); //百分之二
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
建立線形圖
JFreeChart也能夠建立線形圖,這時使用的數據集能夠是CategoryDataset接口或XYDataset的實現類的實例。
【例12-3】 建立線形圖
建立線形圖一樣須要經歷與建立餅形圖相似的三步。本例將實現輸出一個學生物理、化學、數學三門課程6次考試成績的線圖。
第一步:建立一個包含要在Web圖形中顯示的數據的數據集對象。代碼以下:
//------數據線------
String dataLine1="物理";
String dataLine2="化學";
String dataLine3="數學";
//------數據列------
String dataCol1="1";
String dataCol2="2";
String dataCol3="3";
String dataCol4="4";
String dataCol5="5";
String dataCol6="6";
//------建立數據集,並設置值------
DefaultCategoryDataset categoryDataset = new DefaultCategoryDataset();
categoryDataset.addValue(60,dataLine1,dataCol1);
categoryDataset.addValue(70,dataLine1,dataCol2);
categoryDataset.addValue(83,dataLine1,dataCol3);
categoryDataset.addValue(90,dataLine1,dataCol4);
categoryDataset.addValue(92,dataLine1,dataCol5);
categoryDataset.addValue(85,dataLine1,dataCol6);
categoryDataset.addValue(63,dataLine2,dataCol1);
categoryDataset.addValue(45,dataLine2,dataCol2);
categoryDataset.addValue(67,dataLine2,dataCol3);
categoryDataset.addValue(76,dataLine2,dataCol4);
categoryDataset.addValue(90,dataLine2,dataCol5);
categoryDataset.addValue(87,dataLine2,dataCol6);
categoryDataset.addValue(50,dataLine3,dataCol1);
categoryDataset.addValue(76,dataLine3,dataCol2);
categoryDataset.addValue(84,dataLine3,dataCol3);
categoryDataset.addValue(96,dataLine3,dataCol4);
categoryDataset.addValue(88,dataLine3,dataCol5);
categoryDataset.addValue(80,dataLine3,dataCol6);
第二步:建立一個用於做圖的JFreeChart對象。代碼以下:
//------建立線圖------
String titleString="XXXXXX學生成績線圖";//圖的標題
JFreeChart chart = ChartFactory.createLineChart(titleString,//圖形的標題
"第幾回考試",//區域軸標籤
"成績",//數值軸標籤
categoryDataset,//數據集
PlotOrientation.VERTICAL,//圖形顯示方向,豎向
true,//是否顯示圖例
true,//是否有工具提示
false//是否有URL
);
第三步:向目標做圖。代碼以下
ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,500,300);
下面結出本實例的完整代碼。
lineChart.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="org.jfree.chart.JFreeChart,org.jfree.chart.ChartUtilities,
org.jfree.chart.ChartFactory,
org.jfree.chart.plot.PlotOrientation,
org.jfree.data.category.DefaultCategoryDataset"%>
<html>
<body>
<%
//------數據線------
String dataLine1="物理";
String dataLine2="化學";
String dataLine3="數學";
//------數據列------
String dataCol1="1";
String dataCol2="2";
String dataCol3="3";
String dataCol4="4";
String dataCol5="5";
String dataCol6="6";
//------建立數據集,並設置值------
DefaultCategoryDataset categoryDataset = new DefaultCategoryDataset();
categoryDataset.addValue(60,dataLine1,dataCol1);
categoryDataset.addValue(70,dataLine1,dataCol2);
categoryDataset.addValue(83,dataLine1,dataCol3);
categoryDataset.addValue(90,dataLine1,dataCol4);
categoryDataset.addValue(92,dataLine1,dataCol5);
categoryDataset.addValue(85,dataLine1,dataCol6);
categoryDataset.addValue(63,dataLine2,dataCol1);
categoryDataset.addValue(45,dataLine2,dataCol2);
categoryDataset.addValue(67,dataLine2,dataCol3);
categoryDataset.addValue(76,dataLine2,dataCol4);
categoryDataset.addValue(90,dataLine2,dataCol5);
categoryDataset.addValue(87,dataLine2,dataCol6);
categoryDataset.addValue(50,dataLine3,dataCol1);
categoryDataset.addValue(76,dataLine3,dataCol2);
categoryDataset.addValue(84,dataLine3,dataCol3);
categoryDataset.addValue(96,dataLine3,dataCol4);
categoryDataset.addValue(88,dataLine3,dataCol5);
categoryDataset.addValue(80,dataLine3,dataCol6);
//------建立線圖------
String titleString="XXXXXX學生成績線圖";//圖的標題
JFreeChart chart = ChartFactory.createLineChart(titleString,"第幾回考試","成績",
categoryDataset,PlotOrientation.VERTICAL,true,true,false);
ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,500,300);
%>
</body>
</html>
程序的運行效果如圖12-4所示。

圖12-4 生成線形圖
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
經常使用API介紹
JFreeChart的組件包中的類至關之多,須要對圖形多越多的個性化設置或要開發越複雜的圖形,就須要瞭解這些組件包中更多的類及其API。JFreeChart中經常使用有以下一些包:
(1)org.jfree.chart:這個包包含了JFreeChart最爲重要也是最爲經常使用的幾個類和接口。
(2)org.jfree.chart.data:數據集相關的接口和類。
(3)org.jfree.chart.plot:繪圖相關的類和接口。
(4)org.jfree.chart.data.general:經常使用的數據集相關的接口和類。
還有許多其它的包,就再也不一一介紹,有興趣的讀者可進一步參考JFreeChart的開發參考手冊。
下面介紹開發中最爲經常使用的幾個類(或接口)。
(1)JFreeChart類
即org.jfree.chart.JFreeChart,這個類用於協調整個畫圖的處理過程。生成這個類一般使用ChartFactory類。JFreeChart主要的方法有:
public void draw(Graphics2D g2, Rectangle2D area)
此方法用於在圖形設備上的特定區域畫圖。參數g2代碼一個圖形,參數area表包容這個圖形的矩形容器。Java中提供了幾個圖形設備:屏幕、打印機、圖形緩衝區。JFreeChart繪圖是由不一樣的Java.awt.Graphics2D包中的抽象類實現的,只有利用它們,JFreeChart才能向不一樣的圖形設備輸出圖形。
(2)ChartFactory類
這個類是一個工廠類,即org.jfree.chart.ChartFactory,它提供了一些比較方便的建立圖形對象的方法。此類經常使用的方法有:
public static JFreeChart createPieChart(String title,PieDataset dataset, boolean legend, boolean tooltips, boolean urls)
此方法用於建立一個標準的餅圖。參數title爲要建立的餅圖的標題;參數dataset爲建立餅圖所使用的特定的數據集(能夠爲空);參數legend表是不是一個圖例;參數tooltips用於配置圖形是否生成提示信息,參數urls配置圖形是否生成URL。
public static JFreeChart createBarChart(String title,String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset,PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls)
此方法用於根據dataset數據集生成條形圖;參數categoryAxisLabel指定橫向軸(分類軸)的提示字符串;參數valueAxisLabel指出豎向軸(值軸)的提示字符串,其它參數的含義同createPieChart()方法;參數orientation指出條形圖是橫向的仍是豎向的,若是爲豎向的其值可設爲PlotOrientation.VERTICAL。
public static JFreeChart createLineChart(String title,String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset,PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls)
此方法根據dataset數據集生成線圖,其它參數的含義同createBarChart()方法。
(3)ChartUtilities類
即org.jfree.chart.ChartUtilities,經過ChartUtilities類可從chart對象生成PNG格式或JPEG格式的圖片,也可生成帶有點擊範圍的HTML圖片,這些生成圖片的方法都是靜態的。ChartUtilities類有以下經常使用的方法:
public static void writeChartAsPNG(OutputStream out, JFreeChart chart, int width, int height) throws IOException
JFreeChart經過一個開源的PNG格式圖片的解碼器來生成PNG圖片。ChartUtilities類提供了一些方便使用的方法來直接經過輸出流(OutputStream)生成圖片。參數width爲圖形的寬度,參數heigth爲圖形的高度。
public static void writeChartAsJPEG(OutputStream out, JFreeChart chart, int width, int height) throws IOException
public static void writeChartAsJPEG(OutputStream out, JFreeChart chart, int width, int height, ChartRenderingInfo info)
這兩個方法用於生成JPEG格式的圖片。參數的含義同writeChartAsPNG()方法。
(4)PlotOrientation類
即org.jfree.chart.plot.PlotOrientation,此類用於表示圖形的顯示方向,這個類主要有兩個屬性,分別用於表示圖形顯示的兩個方向:橫向和縱向。
PlotOrientation.HORIZONTAL:圖形橫向顯示。
PlotOrientation.VERTICAL :圖形縱向顯示。
(5)DefaultCategoryDataset接口
即org.jfree.data.category.DefaultCategoryDataset,這是一個默認狀況下使用的分類數據集接口。它的構造函數以下:
public DefaultCategoryDataset()
這個函數將生成一個空的數據集。也能夠使用DatasetUtilities類的靜態方法以數組做爲參數來生成一個新的數據集,並用這個數組做爲數據集中的數據。
public addValue(Number value, Comparable rowKey, Comparable columnKey)
此方法用於向數據集中加入一個值。向數據要中增長值時,若是已經存在則會覆蓋。
public setValue(Number value, Comparable rowKey, Comparable columnKey)
此方法的功能同addValue()方法。
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
JavaReport組件介紹
JSP程序員總以爲在開發Web系統時報表是個老大難的問題,要麼須要程序員編寫一大堆的程序,要麼須要使用到第三方的組件以快速開發。在Web系統中通常程序員不能專一於開發報表,諸於調整報表格式之類的工做,而應當把精力集中放在實現系統的業務邏輯、數據邏輯,所以筆者提倡使用成熟的第三方報表組件。
如今市場上林林總總不下20 家專業報表工具,若是再加上各家公司本身開發、用於項目的報表控件、程序等等,用數以百計來形容報表工具的種類並不過度。這裏並不想列羅出各類報表工具,而只是想介紹一款實用的,支持快速開發,可知足大多數應用場合下的報表開發工具——JavaReport。
JavaReport由偉才工做室開發,這個組件簡單易用,只須編寫少許的代碼便可開發出複雜的報表和圖形,中文支持較好,較爲實用。JavaReport可從網上免費下載獲得,網址以下:
http://www.javareport.com.cn/download.htm
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
JavaReport介紹
JavaReport是純Java的實時的Web報表開發平臺。是B/S結構應用系統的報表解決方案。系統採用HTML的方式顯示展現,同時可直接導出Word,Excel,PDF,CSV等各類格式文件,而且保持樣式一致。JavaReport主要有以下優勢:
(1)支持實時的、動態的報表Web統計報表。
(2)具備豐富統計圖形接口,有良好的圖表混合報表擴展能力。
(3)支持純HTML的Web報表展示方式,且無需安裝任何插件。
(4)自動實現數據分頁功能、上下翻頁等功能。
(5)報表能夠動態導出成Word,Excel,PDF,CSV各類格式的文檔。
(6)中文支持不錯,不存在多種編碼亂碼問題,爲程序員省心很多。
有許多的問題在JavaReport組件內已經解決,如報表的導出功能、打印功能和數據的分頁處理等。在不少B/S結構體系的系統開發時,分頁是開發過程當中要重點考慮的問題。但在JavaReport中,就不須要考慮上下翻頁,跨頁分頁,由於這些問題報表引擎已經實現了。在設計報表的過程當中,把Report類看成容器類,統計圖類,表格類,標籤類,圖片類等,把它們看成組件類。至於跨頁分頁,上下翻頁由報表引擎自動完成。JavaReport系統中有自動跨頁分頁的功能,當表格超過當前頁的大小時,系統會自動把接着部分放到下一頁。報表設計在開發過程當中是感受不到要跨頁的存在,只有一個所有數據完整的表格對象。
若是要把引入圖片文件加入到報表中,可以使用報表系統的Report類,經過這個類的addImage()方法把Image對象加進來,若是須要自定義圖像,可經過第三方畫圖程序(例如是JFreeChart程序)生產須要的統計圖/圖片,而後再把圖像加到報表中去。
本書中使用的JavaReport版本是V3.0,JavaReport根據客戶的應用須要,按照功能和性能的等級,分紅三個版本:專業版,服務器版,企業版。本書使用企業版。JavaReport三個版本產品都是無償使用的。也就是說這三個版本都不須要購買License許可,能夠自由使用JavaReport的全部功能。
專業版客戶(Client)的IP最大鏈接數限制爲10個,也就是JavaReport同時並行處理線程的最大數受限制。限制是爲了不繫統資源佔用過大,使系統反應遲鈍。該版本適合中小型的應用系統,保障應用系統正常運行。
服務器版在最大鏈接數沒有受限,它能充分發揮服務器的個部分硬件設備的做用;相對要求服務器的設備配置高,保障最優性能效率。該版本適合大中型的應用系統使用。
企業版提供垃圾回收機制管理,自動處理在內存中無用對象的引用;支持多服務器處理模式,提供在多個服務器的集羣功能和服務器之間負載均衡功能。提升服務器羣的負載能力和和快速響應能力。該版本適合負載繁重的應用系統使用。
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
安裝JavaReport
在下載獲得的文件中找到JavaReport-V3-Enterprise-Released.jar這個jar文件,把這個文件的路徑加入到classpath系統變量中,這樣本機上的全部Web應用均可以使用JavaReport了。若是隻須要讓某個Web應用可以使用JavaReport,則應當把jar文件拷貝到Web應用的WEB-INF\lib目錄下。
【專家提示】若是Web應用的WEB-INF目錄下沒有lib子目錄,就新建一個lib子目錄。
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
經常使用的JavaReport類
JavaReport生成的報表在顯示時的狀況如圖12-5所示。

圖12-5 JavaReport生成的報表顯示時的狀況
最上面的一欄中有許多的按鈕,稱爲報表導航按鈕,其中就有將報表導出成文件的按鈕,鼠標在按鈕上懸停不久後即會有文字提示按鈕的功能。報表導航按鈕的後面預留了一些空餘的地方,用於程序員自定義一些按鈕。JavaReport把一張報表分爲表頭、報表中的內容、表尾三個部分,一張報表中能夠有多個表格。
JavaReport的組件包中有許多的類,體系龐大而複雜,在這裏僅列出一些經常使用的類來做出說明,有興趣的可參考詳細的API手冊。
(1)WebReportEngine類
即com.javareport.http.WebReportEngine,這個類是整個JavaReport中的Web引擎的開發接口。全部的JSP或Servlet從這個類繼承下來,程序員只須要覆蓋createReport()函數就能實現報表開發工做中大部分的需求,諸如怎樣在Web上顯示、怎樣造成Word、PDF文件等之類的功能由JavaReport報表引擎來完成,程序員就沒必要再考慮這些實現的細節了。
若是是在JSP頁面中,在首部需加入以下的語句:
<%@ page extends="com.javareport.http.WebReportEngine"%>
表示JSP頁面類繼承自com.javareport.http.WebReportEngine。
【專家提示】有的讀者可能以爲不理解,什麼叫JSP類?JSP實質上就是一個Java類,我表面上看來它是一個動態的網頁,在Web引擎中會最終將它編譯成一個Java類,再執行這個Java類。
若是是在Servlet中,相應的Servlet類聲明時語句以下:
public class Servlet類名稱 extends WebReportEngine{
……
}
WebReportEngine類經常使用的方法有:
public Report createReport(javax.servlet.http.HttpServletRequest request)
throws java.lang.Exception
public java.lang.String validate(javax.servlet.http.HttpServletRequest request)
public java.lang.String getStartScript(javax.servlet.http.HttpServletRequest request)
public java.lang.String getEndScript(javax.servlet.http.HttpServletRequest request)
public java.lang.String getToolbarScript(javax.servlet.http.HttpServletRequest request)
public boolean isShowToolbar()
public int getAllEchoButton()
createReport()方法用於創建報表,並返回報表的實例。這個報表實例能夠在Web上顯示,同時也能夠導出Word, Excel, PDF, CSV, HTML等格式的文檔以供使用。方法中的參數request可用於獲取全部的動態請求的數據。
validate()方法用於對上一個頁面Form提交的參數進行檢查,因爲實時報表須要動態的參數,在這裏進行數據校驗。方法中的參數request可用於獲取全部的動態請求的數據;方法的返回值爲null時表明經過,其餘內容則爲參數錯誤的提示信息。
getStartScript()方法用於構造報表內容在Web頁面上顯示以前執行的JavaScript或VBScript腳本,若是要定製則要重載這個方法。方法中的參數request可用於獲取全部的動態請求的數據;方法返回值爲null時表明沒有腳本內容。
getEndScript()方法用於構造報表內容在Web頁面上顯示以後執行的JavaScript或VBScript腳本,若是要定製則要重載這個方法。方法中的參數request可用於獲取全部的動態請求的數據;方法返回值爲null時表明沒有腳本內容。
getToolbarScript()方法用於定製Web報表在頁面首部顯示的工具欄爲標準的樣式(上下翻頁,導出文件),能夠在此擴展工具欄的內容,如:添加公司主頁的連接,返回上一層連接的「返回」按鈕,若是要定製則要重載這個方法。方法中的參數request可用於獲取全部的動態請求的數據;方法返回值爲null時表明不添加內容。
isShowToolbar()方法用於設定是否在頁面上顯示報表工具欄。若是不想在頁面上顯示報表工具欄,可重載這個方法,並設定返回值爲false。須要注意的是,若是是多頁報表,上下翻頁按鈕就沒法使用。
getAllEchoButton()方法用於自定義顯示在Web頁面中的報表導出文件的按鈕,好比應用中只導出PDF文件,其餘的不須要,就能夠這裏設定。按鈕值從Word按鈕開始是(1,2,4,8,...),須要顯示的按鈕則將它們的值相加就能夠了。要做自定義,須要重載這個方法,並將返回值設爲要顯示的按鈕對應的和值。默認狀況下工具欄上的按鈕如圖12-6所示:

圖12-6 默認狀況下工具欄上的按鈕
(2)Report類
即com.javareport.beans.Report,報表類。這個類的對象用於表明一張報表,是全部報表元素的容器,這是整個系統的核心,也是在瀏覽器上顯示和生成電子文檔(Word,Excel,PDF,Html等)的基礎。
Report類經常使用的方法有:
//--在報表的頁眉添加一條橫直線,參數num表示橫直線的粗細程度,數字越大線越粗
public java.lang.String addHeaderSeparator(int num)
//--在頁眉中添加若干個空格,參數num是要添加的空格的個數
public java.lang.String addHeaderSpace(int num)
//--用於在頁眉中添加若干個【Tab】鍵,參數num是要添加的【Tab】鍵的個數
public java.lang.String addHeaderTab(int num)
//--在頁眉中添加一個換行符號,緊跟後面的內容則從下行第一個字符的位置開始
public java.lang.String addHeaderBreak()
//--在頁眉中添加文本信息內容,緊跟後面的內容則從下行第一個字符的位置開始
public java.lang.String addHeaderText(java.lang.String text)
//--在報表中添加圖表信息內容,參數chart是要添加的圖表
public java.lang.String addChart(ChartImpl chart)
//--設置報表當前的字體,參數是要設置的字體對象,爲Java中java.awt.*包中的Font對象
public void setCurrentFont(java.awt.Font font)
//--設置報表當前的背景顏色
public void setCurrentBackground(java.awt.Color color)
//--設置報表當前的前景顏色
public void setCurrentForeground(java.awt.Color color)
//--在報表中添加圖片信息內容
public java.lang.String addImage(java.awt.Image image)
//--添加項目符號的表示符號。第一種形式添加默認的項目符號(圓點)的表示符號,
//--第二種形式用自定義的圖片內容代替默認的圓點內容
public java.lang.String addBullet()或
public java.lang.String addBullet(java.awt.Image image)
//--在報表中添加一個換行符號,緊跟後面的內容則從下行第一個字符的位置開始。
//--參數num表明換行的數量,即屢次換行
public java.lang.String addNewline(int num)
//--在報表中添加一條橫直線,參數num表示橫直線的粗細程度
public java.lang.String addSeparator(int num)
//--添加若干個空格,參數num表明空格的個數
public java.lang.String addSpace(int num)
//--在報表中添加若干個【Tab】鍵,參數num是要添加的【Tab】鍵的個數
public java.lang.String addTab(int num)
//--在報表中添加文本信息內容,緊跟後面的內容則從下行第一個字符的位置開始
//--參數text爲要添加的文本信息內容
public java.lang.String addText(java.lang.String text)
//--添加報表中的表格信息內容,參數table是要添加的表格
public java.lang.String addTable(Table table)
//--在頁尾添加一條橫直線,參數num爲橫直線的粗細程度
public java.lang.String addFooterSeparator(int num)
//--在頁尾添加若干個空格,參數num表明要添加的空格的個數
public java.lang.String addFooterSpace(int num)
//--在頁尾添加若干個【Tab】鍵,參數num爲要添加的【Tab】鍵的個數
public java.lang.String addFooterTab(int num)
//--在頁尾添加一個換行符號,緊跟後面的內容則從下行第一個字符的位置開始
public java.lang.String addFooterBreak()
//--在頁尾添加文本信息內容,緊跟後面的內容則從下行第一個字符的位置開始
public java.lang.String addFooterText(java.lang.String text)
addHeaderText ()方法和addFooterText()方法中的參數text是要添加的文本信息內容。其中,{P}表明當前頁,{N}表明總頁數,如:「第{P}頁,共{N}頁」。
(3)Table類
即com.javareport.beans.Table,表格類。這個類的對象屬於報表對象Report中的元素。表格在報表中是不可缺乏的,整齊排列着數據內容。表格單元裏面的內容能夠是文本內容,也能夠是圖形和其餘元素,同時這個對象也是表套表的基礎。JavaReport會自動處理表格的跨頁、分頁問題和新頁中的表頭顯示問題,開發過程當中把它想象成連續的就能夠了。
Table類的經常使用方法有:
//--構造函數,參數data爲填充表格內容的二維數組
public Table(java.lang.Object[][] data)
(4)Chart類
即com.javareport.beans.Chart,圖表類。這個類的對象屬於報表對象Report中的元素。統計圖在報表中不可缺乏的,使用戶瀏覽更加直觀,能夠用這個類生成十幾種報表統計圖。Chart類經常使用的方法有:
//--設置圖表中指定的單元或全部單元的數據
public void setData(int i,int j,java.lang.Number data)或
public void setData(java.lang.Number[][] data)
//--設置統計圖的類型,統計圖能夠是:曲線圖,百分比圖等。
public void setStyle(int type)
setData()方法的第一種形式參數說明以下:
參數i指定的二維數據單元的座標x的值;參數j指定的二維數據單元的座標y的值;參數data用於給指定的單元賦值,數據能夠是Byte, Double, Float, Integer, Long, Short,這些數據類型都是Number類的子類。
setData()方法的第二種形式參數data是一個二維的數據,數據能夠是Byte、Double、Float、Integer、Long、Short。
setStyle()方法中的參數type是指定的統計圖類型,總共有十多種,經常使用常量來表示,經常使用的有如下幾種。
Chart.CHART_PIE3D:立體餅圖
Chart.CHART_STACKBAR3D:立體條形圖
Chart.CHART_CURVE:曲線圖
Chart.CHART_LINE:線圖
Chart.CHART_POINT:點圖
Chart.CHART_INVERTED_CURVE:反向曲線圖
Chart.CHART_INVERTED_LINE:反向線圖
Chart.CHART_INVERTED_STACKBAR:橫向的條形圖
(5)RsTable類
即com.javareport.beans.RsTable,記錄集表格類。這個類的對象屬於報表對象Report中的元素。RsTable類具備Table類的所有功能,是針對統計報表中顯示記錄集是一個很是頻繁使用的動做而設計的,開發者使用它時可以用幾行代碼就可把一個JDBC記錄集裏的數據以表格形式列舉顯示出來。RsTable類經常使用的方法有:
//--構造函數,參數rs是填充表格內容的記錄集;參數as是記錄集中列的名稱映射表,
//--好比記錄值中「ID」映射爲「編號」,則報表的表頭名稱列顯示爲「編號」
public RsTable(java.sql.ResultSet rs)或
public RsTable(java.lang.String[] as,java.sql.ResultSet rs)
//--設置表頭與列名的映射關係,參數as是映射關係中的對照表,是一個二維數組
public void setMapping(java.lang.String[][] as)
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
JavaReport的應用
JavaReport不只能用來開發報表,也能開發統計圖形。下面來看看一些常見的使用場合下JavaReport是如何被應用的。
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
開發Web報表的方法
在JSP頁面中與在Servlet中開發Web報表的用法有所不一樣。
(1)在JSP頁面中開發Web報表
開發JSP時,自定義的JSP須要從WebReportEngine類繼承下來:
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="javax.servlet.*"%>
<%@ page import="com.javareport.beans.*"%>
<%@ page extends="com.javareport.http.WebReportEngine"%>
<%!
public Report createReport(HttpServletRequest request) throws Exception {
……
}
……
%>
根據以上的代碼,大多數狀況下重載了createReport()方法就能知足須要了,報表的樣式和內容等設置就在這函數裏來實現;若是須要也能夠重載其餘函數。更詳細的一個編程參考以下:
JSP報表開發模板
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="javax.servlet.*"%>
<%@ page import="com.javareport.beans.*"%>
<%@ page extends="com.javareport.http.WebReportEngine"%>
<%!
/******************************************************************************
* 這是報表系統在應用中給開發人員的JSP模板文件,能夠根據須要調整接口內容。部分函
* 數能夠適當刪除。在開發中通常是實現createReport()函數就能夠,造成實時動態報表
* 就是在這個函數裏實現的。剩下的工做(怎樣在Web上顯示,怎樣造成Work,PDF文件等)
* 交給報表引擎自動實現。
******************************************************************************/
/**
* 創建報表,返回報表的實例。這個報表實例能夠在Web上顯示,同時也能夠導出Word,Excel,
* PDF,CSV,HTML等格式的文檔供使用。
*/
public Report createReport(HttpServletRequest request) throws Exception{
Report report = new Report();
report.addText("This is a template !");
return report;
}
/**
* 這是對上一個頁面Form提交的參數進行檢查,因爲實時報表須要動態的參數,在這裏進
* 行數據校驗。
* 返回值爲null時表明經過,其餘內容則爲參數錯誤的提示信息。
*/
public String validate(HttpServletRequest request){
return null;
}
/**
* 這是報表在Web上顯示時,內容顯示出來前執行的腳本,腳本內容通常爲JavaScript腳
* 本或VBScript腳本。
* 返回值爲null時表明經過沒有腳本內容。
*/
public String getStartScript(HttpServletRequest request){
return null;
}
/**
* 這是報表在Web上顯示時,內容顯示出來後執行的腳本,腳本內容通常爲JavaScript腳
* 本或VBScript腳本。
* 返回值爲null時表明經過沒有腳本內容。
*/
public String getEndScript(HttpServletRequest request){
return null;
}
/**
* 這是報表在Web上顯示時,上面的工具欄爲標準的樣式(上下翻頁,導出文件)。能夠在
* 此擴展工具欄的內容,通常能夠添加公司主頁的連接,返回上一層連接的「返回」按鈕就是
* 在這裏添加腳本的。
* 返回值爲null時表明不添加內容。
*/
public String getToolbarScript(HttpServletRequest request){
return null;
}
/**
* 這是報表在Web上顯示時,若是不想讓工具欄顯示出來,就讓函數的返回值就false就能夠。
* 注意:若是是多頁報表,上下翻頁按鈕就沒法使用。
*/
public boolean isShowToolbar(){
return true;
}
/**
* 這是報表在Web上顯示時,導出文件的按鈕能夠自定義,好比應用中只要導出PDF文件,
* 其餘的不須要,就能夠這裏設定。按鈕值從Work按鈕開始是(1,2,4,8,...),須要
* 顯示的按鈕則將它們的值相加就能夠了。
*/
public int getAllEchoButton(){
return 0xFFFF;
}
%>
(2)在Servlet中開發Web報表
在Servlet中,自定義的servlet須要從WebReportEngine類繼承下來,以下所示:
import javax.servlet.http.*;
import com.javareport.beans.*;
public class ReportExam extends WebReportEngine {
public Report createReport(HttpServletRequest request) throws Exception {
……
}
……
}
下面給出一個Servlet報表開發的詳細模板,以供參考。
Servlet報表開發模板
<%@ page contentType="text/html; charset=GBK" %>
import javax.servlet.http.*;
import com.javareport.beans.*;
public class Template extends WebReportEngine {
/******************************************************************************
* 這是報表系統在應用中給開發人員的JSP模板文件,能夠根據須要調整接口內容。部分函
* 數能夠適當刪除。在開發中通常是實現createReport()函數就能夠,造成實時動態報表
* 就是在這個函數裏實現的。剩下的工做(怎樣在Web上顯示,怎樣造成Work,PDF文件等)
* 交給報表引擎自動實現。
******************************************************************************/
/**
* 創建報表,返回報表的實例。這個報表實例能夠在Web上顯示,同時也能夠導出Word,Excel,
* PDF,CSV,HTML等格式的文檔供使用。
*/
public Report createReport(HttpServletRequest request) throws Exception{
Report report = new Report();
report.addText("This is a template !");
return report;
}
/**
* 這是對上一個頁面Form提交的參數進行檢查,因爲實時報表須要動態的參數,在這裏進
* 行數據校驗。
* 返回值爲null時表明經過,其餘內容則爲參數錯誤的提示信息。
*/
public String validate(HttpServletRequest request){
return null;
}
/**
* 這是報表在Web上顯示時,內容顯示出來前執行的腳本,腳本內容通常爲JavaScript腳
* 本或VBScript腳本。
* 返回值爲null時表明經過沒有腳本內容。
*/
public String getStartScript(HttpServletRequest request){
return null;
}
/**
* 這是報表在Web上顯示時,內容顯示出來後執行的腳本,腳本內容通常爲JavaScript腳
* 本或VBScript腳本。
* 返回值爲null時表明經過沒有腳本內容。
*/
public String getEndScript(HttpServletRequest request){
return null;
}
/**
* 這是報表在Web上顯示時,上面的工具欄爲標準的樣式(上下翻頁,導出文件)。能夠在
* 此擴展工具欄的內容,通常能夠添加公司主頁的連接,返回上一層連接的「返回」按鈕就是
* 在這裏添加腳本的。
* 返回值爲null時表明不添加內容。
*/
public String getToolbarScript(HttpServletRequest request){
return null;
}
/**
* 這是報表在Web上顯示時,若是不想讓工具欄顯示出來,就讓函數的返回值就false就能夠。
* 注意:若是是多頁報表,上下翻頁按鈕就沒法使用。
*/
public boolean isShowToolbar(){
return true;
}
/**
* 這是報表在Web上顯示時,導出文件的按鈕能夠自定義,好比應用中只要導出PDF文件,
* 其餘的不須要,就能夠這裏設定。按鈕值從Work按鈕開始是(1,2,4,8,...),須要
* 顯示的按鈕則將它們的值相加就能夠了。
*/
public int getAllEchoButton(){
return 0xFFFF;
}
%>
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
用JavaReport開發Web統計圖
【例12-4】 用JavaReport在Web中輸出統計圖
JavaReport支持多種統計圖,本例將實現用JavaReport來在JSP頁面中顯示一維數據的圖形,共實現了8種統計圖。
chartReport.jsp
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="com.javareport.beans.*"%>
<%@ page extends="com.javareport.http.WebReportEngine"%>
<%!
public Report createReport(HttpServletRequest request) throws Exception{
//圖片類型數組
int[] chartType = new int[]{
Chart.CHART_PIE3D,Chart.CHART_STACKBAR3D,
Chart.CHART_CURVE,Chart.CHART_LINE,
Chart.CHART_POINT,Chart.CHART_INVERTED_CURVE,
Chart.CHART_INVERTED_LINE,Chart.CHART_INVERTED_STACKBAR};
//單元數據的顯示標籤字符串數組
String[] labels = new String[] {"湖南省","湖北省","廣西壯族自治區","廣東省"};
//實例化報表對象
Report report = new Report();
//在頁眉中添加文本信息內容
report.addHeaderText("希賽軟考學院各省報名人數狀況");
//在報表的頁眉添加一條橫直線
report.addHeaderSeparator(1);
//在頁尾添加一條橫直線
report.addFooterSeparator(1);
//在頁尾添加文本信息內容
report.addFooterText("第{P}頁, 共{N}頁");
//循環輸出各類類型的圖片
for (int i = 0; i < chartType.length; i++) {
try {
//實例化一個圖表對象
Chart chart = new Chart((Number[][])getData(request));
//設置圖表中的單元數據的顯示的標籤
chart.setLabels(labels);
//設置統計圖的類型
chart.setStyle(chartType[i]);
//設置統計圖中顯示的時候把具體的數值也顯示出來
chart.setShowValue(true);
//在報表中添加文本信息內容
report.addText("報表中常見的報表統計圖表("+i+"): ");
//在報表中添加圖表信息內容
report.addChart(chart);
//在報表中添加換行符號
report.addBreak();
report.addBreak();
report.addBreak();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
return report;
}
//讀者可根據須要設置數組的值,或從數據庫中取出值放入數組中以動態顯示數據
public Double[][] getData(HttpServletRequest request){
Double[][] data = new Double[1][4];
data[0][0] = new Double(50);
data[0][1] = new Double(50);
data[0][2] = new Double(35);
data[0][3] = new Double(55);
return data;
}
//定製Web報表在頁面首部顯示的工具欄爲標準的樣式,增長一個"返回"按鈕,返回到首頁
public String getToolbarScript(HttpServletRequest request){
return "<a href=\"../index.htm\"><img src=\""+request.getRequestURI()+
"?op=Resource&name=/resource/back.gif\" border=\"0\" alt=\"返回\"></a>";
}
%>
程序的運行結果如圖12-7所示。

圖12-7 用JavaReport輸出Web統計圖
程序中首先是重載了createReport()方法,在這個方法的方法體中,先用「new Report()」生成了一個報表Report對象report,再設置了報表的頁眉頁腳,而後再用一個for循環輸出了8種Web統計圖。
重載getData()方法的目的是爲了設置顯示的Web統計圖所要表示的數據,這個方法的返回值是一個Double類型的二維數組,因爲第一維只有一行,即至關於一維數據。方法的返回值就是Web統計圖要表示的數據。
重載getToolbarScript()方法的目的是爲了定製Web報表在頁面首部顯示的工具欄爲標準的樣式,增長了一個「返回」按鈕,當點擊時返回到網站的首頁。
從上可見,JavaReport只使用了少許的代碼就輸出了美觀而又實用的Web圖形;實際工程中一維數據的數據來源經常來自於對數據庫中數據查詢的結果,這須要讀者自行編寫代碼實現,有興趣的讀者不妨試試。
例12-4中的代碼只是實現了一維數據的展示,有時也須要展示二維的數據。二維數據圖形與一維數據圖形的區別就是在數據展示上加大了數據的展示量,在同一個單元數據標籤處可顯示屬於同一個單元數據的多個數據。修改一下例12-4中getData()方法的內容,修改後的代碼以下:
public Double[][] getData(HttpServletRequest request){
Double[][] data = new Double[4][4];
data[0][0] = new Double(200); data[0][1] = new Double(250);
data[0][2] = new Double(220); data[0][3] = new Double(280);
data[1][0] = new Double(500); data[1][1] = new Double(700);
data[1][2] = new Double(520); data[1][3] = new Double(900);
data[2][0] = new Double(350); data[2][1] = new Double(400);
data[2][2] = new Double(380); data[2][3] = new Double(320);
data[3][0] = new Double(550); data[3][1] = new Double(590);
data[3][2] = new Double(337); data[3][3] = new Double(340);
return data;
}
則程序運行的結果如圖12-8所示。

圖12-8 用JavaReport輸出二維數據圖形
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
用JavaReport輸出報表
【例12-5】 用JavaReport輸出報表
table.jsp
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.awt.*"%>
<%@ page import="com.javareport.beans.*"%>
<%@ page extends="com.javareport.http.WebReportEngine"%>
<%!
public Report createReport(HttpServletRequest request) throws Exception{
//實例化報表對象
Report report = new Report();
//在頁眉中添加文本信息內容
report.addHeaderText("報表輸出示例");
//在報表的頁眉添加一條橫直線
report.addHeaderSeparator(1);
//在頁尾添加一條橫直線
report.addFooterSeparator(1);
//在頁尾添加文本信息內容
report.addFooterText("第{P}頁, 共{N}頁");
//在報表中添加文本信息內容
report.addText("銷售狀況一覽表(合併表格):");
//在報表中添加換行符號
report.addBreak();
//在報表中添加表格
report.addTable(getTable());
//在報表中添加換行符號
report.addBreak();
return report;
}
//------獲得銷售狀況一覽表(合併表格)對象------
public Table getTable(){
String[][] data = getTotalData();
Table table = new Table(data);
table.setAlignment(Table.H_CENTER + Table.V_CENTER);
table.setColAutoSize(true);
table.setRowBackground(0,Color.LIGHT_GRAY);
table.setRowBackground(1,Color.LIGHT_GRAY);
table.setColBackground(0,Color.LIGHT_GRAY);
table.setRowBackground(7,new Color(255,255,128));
table.setHeaderRowCount(2);
table.setHeaderColCount(1);
table.setRowBorder(table.LINE_THIN);
table.setColBorder(table.LINE_THIN);
table.setCellSpan(0,0,new Dimension(1,2));
table.setCellSpan(0,1,new Dimension(2,1));
table.setCellSpan(0,3,new Dimension(2,1));
table.setCellSpan(0,3,new Dimension(2,1));
return table;
}
//生成銷售狀況數據,實際工程中通常從數據庫中獲取
public String[][] getData(){
String[][] data = new String[6][4];
data[0][0] = "區域"; data[0][1] = "第一季度"; data[0][2] = "第二季度"; data[0][3] = "第三季度";
data[1][0] = "華南地區"; data[1][1] = "¥2,000,000";
data[1][2] = "¥2,500,000"; data[1][3] = "¥2,200,000";
data[2][0] = "華東地區"; data[2][1] = "¥6,000,000";
data[2][2] = "¥4,500,000"; data[2][3] = "¥4,800,000";
data[3][0] = "華中地區"; data[3][1] = "¥500,000";
data[3][2] = "¥400,000"; data[3][3] = "¥700,000";
data[4][0] = "華北地區"; data[4][1] = "¥3,000,000";
data[4][2] = "¥3,200,000"; data[4][3] = "¥2,500,000";
data[5][0] = "東北地區"; data[5][1] = "¥4,000,000";
data[5][2] = "¥5,000,000"; data[5][3] = "¥4,400,000";
return data;
}
//獲得銷售彙總統計數據,實際工程中通常從數據庫中獲取
public String[][] getTotalData(){
String[][] data = new String[8][5];
data[0][0] = "區域"; data[0][1] = "上半年"; data[0][3] = "下半年";
data[1][1] = "第一季度"; data[1][2] = "第二季度";
data[1][3] = "第三季度";data[1][4] = "第四季度";
data[2][0] = "華南地區"; data[2][1] = "¥2,000,000"; data[2][2] = "¥2,500,000";
data[2][3] = "¥2,200,000";data[2][4] = "¥0";
data[3][0] = "華東地區"; data[3][1] = "¥6,000,000"; data[3][2] = "¥4,500,000";
data[3][3] = "¥4,800,000";data[3][4] = "¥0";
data[4][0] = "華中地區"; data[4][1] = "¥500,000"; data[4][2] = "¥400,000";
data[4][3] = "¥700,000";data[4][4] = "¥0";
data[5][0] = "華北地區"; data[5][1] = "¥3,000,000"; data[5][2] = "¥3,200,000";
data[5][3] = "¥2,500,000";data[5][4] = "¥0";
data[6][0] = "東北地區"; data[6][1] = "¥4,000,000"; data[6][2] = "¥5,000,000";
data[6][3] = "¥4,400,000";data[6][4] = "¥0";
data[7][0] = "總計"; data[7][1] = "¥15,500,000"; data[7][2] = "¥15,600,000";
data[7][3] = "¥14,600,000";data[7][4] = "¥0";
return data;
}
//定製Web報表在頁面首部顯示的工具欄爲標準的樣式,增長一個"返回"按鈕,返回到首頁
public String getToolbarScript(HttpServletRequest request){
return "<a href=\"../index.htm\"><img src=\""+request.getRequestURI()+
"?op=Resource&name=/resource/back.gif\" border=\"0\" alt=\"返回\"></a>";
}
%>
程序運行的結果如圖12-9所示。

圖12-9 用JavaReport輸出報表
讀者對照圖12-9再分析一下源代碼應當不難。程序中用到了table類的許多方法,用於設置表格中的各類格式,如合併單元格,背景顏色,前景顏色等。
【專家提示】實際工程中,報表的數據每每來自於數據庫中,所以須要在getTotalData()方法中編寫代碼從數據庫中獲得統計數據,統計的方法是能夠使用特定的SQL語句或取出數據後在Java語句中統計。
輸出報表還有一種更直接的方法,就是用SQL語句查詢出數據庫中的數據後會獲得一個ResultSet對象,如rs,再用以下的語句:
RsTable rsTable = new RsTable(rs)
rsTable對象取爲RsTable類的一個實例。重載以下的方法:
public RsTable getRsTable(HttpServletRequest request) throws Exception
將返回值設爲rsTable便可將數據庫查詢的結果做爲二維表格中的數據直接輸出了,而沒必要再轉換成二維數組中的數據再輸出到報表中,這樣能夠大大減小程序員須要編寫的代碼量。
版權方受權希賽網發佈,侵權必究
第 12 章:Web圖表開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月10日
小結
JFreeChart是一個開源的組件包,它提供了Java中經常使用統計圖形來快速開發API,程序員只須掌握少許的接口就能繪製出漂亮的圖形,並且這些圖形不只可用於帶有客戶端界面的Java應用程序中,也能夠是在JSP、Servlet、Java Applet中。JFreeChart可用於建立餅圖、線圖、柱狀圖、散點圖和甘特圖等,本章重點介紹了條形圖和線形圖的開發。若是讀者想要開發出更復雜和豐富多彩的圖形,可對JFreeChart的API做進一步的研究。
JavaReport是一款國產的第三方組件包,可用於開發Web報表,報表中能夠有數據,也能夠使用其簡單的統計圖形編程接口,以少許的代碼開發出所需的報表,並可導出成PDF、EXCEL等格式文件,且中文支持較好,較爲實用。
版權方受權希賽網發佈,侵權必究
第 13 章:Struts開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
Struts概述
第13章 Struts開發
【本章專家知識導學】
Struts是近年來至關流行的一種web開發框架,是在Model 2的基礎上實現的一個MVC框架,其目標就是但願分離Web程序的表示層、控制層和後臺模型層,使程序員能將更多的精力投入到後臺的業務邏輯設計與開發中,而不是底層的Web基礎架構。
本章首先對Stuts做了簡要的概述,包括MVC模式、JSP模式的發展及Struts的工做原理;接着介紹了Struts的安裝及其配置文件的功能及使用;而後以一個Struts應用程序實例講解了Struts開發Web程序的過程,最後介紹了標籤庫的使用。
這一章旨在讓你們對Struts框架有一個總體認識,讀者可以靈活地運用Struts自行開發各類Web應用程序。
13.1 Struts概述
Struts是一種web開發框架,是在Model 2的基礎上實現的一個MVC框架,能夠在Java Servlet和JSP中用來構建Java Web應用程序,是Apache軟件基金下Jakarta項目的一部分。
爲何叫Struts呢?Struts這個名字來源於在建築和舊式飛機中使用的支持金屬架。當創建一個物理建築時,建築工程師會使用支柱爲建築的每一層提供支持。一樣,軟件工程師能夠使用Struts爲業務應用的每一層提供支持。它的目的是就是幫助你減小運用MVC設計模型開發Web應用時的時間。
爲了更好地理解Struts,讀者須要對MVC模式和Model 2有一個認識,下面就先來說解MVC模式。
版權方受權希賽網發佈,侵權必究
第 13 章:Struts開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
MVC模式
MVC是目前普遍流行的一種軟件設計模式,早在20世紀70年代,IBM就推出了Sanfronscisico項目計劃,這其實就是MVC設計模式的研究。
MVC是Model-View-Controller的簡稱,即把一個應用程序的輸入、處理、輸出流程按照View 、Model、Controller的方式進行分離,這樣一個應用被分紅三個層——視圖層、模型層和控制層。圖13-1顯示了MVC模式各個模塊的功能及相互關係。

圖13-1 MVC模式
一、視圖(View)
視圖是模型的表示,是用戶看到並與之交互的界面,對於Web應用來講,能夠歸納爲HTML界面,但也有可能爲XHTML、XML或Applet。隨着應用的複雜性和規模性,界面的處理也變得具備挑戰性。一個應用可能有不少不一樣的視圖,MVC設計模式對於視圖的處理僅限於視圖上數據的採集和處理,以及用戶的請求,而不包括在視圖上的業務流程的處理。業務流程的處理交予模型(Model)處理。
二、模型(Model)
模型是應用程序的主體,負責業務流程、業務狀態的處理以及業務規則的制定。業務流程的處理過程對其餘層來講是黑箱操做,模型接受視圖請求的數據,並返回最終的處理結果。業務模型的設計能夠說是MVC最主要的核心。目前流行的EJB模型就是一個典型的應用例子,它從應用技術實現的角度對模型作了進一步的劃分,以便充分利用現有的組件,但它不能做爲應用設計模型的框架。它僅僅告訴你按這種模型設計就能夠利用某些技術組件,從而減小了技術上的困難。對一個開發者來講,就能夠專一於業務模型的設計。MVC設計模式告訴咱們,把應用的模型按必定的規則抽取出來,抽取的層次很重要,這也是判斷開發人員是否優秀的設計依據。抽象與具體不能隔得太遠,也不能太近。MVC並無提供模型的設計方法,而只告訴你應該組織管理這些模型,以便於模型的重構和提升重用性。咱們能夠用對象編程來作比喻,MVC定義了一個頂級類,告訴它的子類你只能作這些,但無法限制你能作這些。這點對編程的開發人員很是重要。
三、控制器(Controller)
控制器主要負責View和Model之間的流程控制,也就是完成兩個方向的動做:一個是將View的操做映射到具體的Model,以完成具體的業務邏輯;另外一個是將經過Model處理完的業務數據及時反映到View上。控制層的做用就像是一個分發器,它清楚地告訴你應該選擇什麼樣的模型,選擇什麼樣的視圖,能夠完成什麼樣的用戶請求,而它並不作任何的數據處理。當用戶經過某個視圖的控制器改變了模型的數據時,全部其它依賴於這些數據的視圖都會反映這些變化。所以,不管什麼時候發生了何種數據變化,控制器都會將變化通知全部的視圖,致使顯示的更新。應次,模型、視圖與控制器的分離,使得一個模型可能對應多個視圖,一個視圖可能對應多個模型。
MVC設計模式基於如下設計理念:在一個應用系統中,用戶界面發生變更的可能性最大,控制部分次之,而業務邏輯是最穩定的。所以爲業務邏輯編寫的代碼不該該和反應用戶界面的代碼混雜在一塊兒,而是彼此應該儘量地獨立,由控制器來擔當二者交互的中介。下面咱們以一個基於Internet的電信交話費這一過程爲例介紹一下基於MVC模式的實現,處理過程如圖13-2所示。

圖13-2 電信交話費過程基於MVC模式的實現
版權方受權希賽網發佈,侵權必究
第 13 章:Struts開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
JSP模式的發展
JSP開發模式的發展主要經歷瞭如下三個階段:
一、階段1
早期的Java Web開發應用中,全部工做都交給JSP來處理,如圖13-3所示。

圖13-3 JSP Model
在這種模式下,JSP文件不只要負責生成網頁、控制網頁流程,還要負責處理業務邏輯,給WEB開發帶來了一系列的問題
①強耦合。HTML和Java強耦合在一塊兒,致使頁面設計與邏輯處理沒法分離。
②調試困難。
③可讀性差,不利於維護。在須要更改業務處理邏輯或數據時,可能要牽扯到多個網頁。
二、階段2
隨着技術的進一步發展,JSP頁面功能開始逐步劃分,引入了JavaBean與JSP頁面共同協做完成任務,這就是JSP Model 1,如圖13-4所示。在Model 1 架構中,JSP 直接處理Web 瀏覽器送來的請求,並輔以JavaBean 處理應用相關邏輯。Model 1 架構單純編寫比較容易,但在Model 1 中JSP 可能同時肩負View 與Controller 角色,兩類程序代碼有可能混雜而不易維護。

圖13-4 Model 1
三、階段3
功能進一步劃分,在Model 1的基礎上又引入了Servlet,造成Model 2,如圖13-5所示。Model 2 中將Servlet 歸入架構中扮演前端Controller 角色,將Web 瀏覽器送出的請求集中送至Servlet,Servlet再視需求轉向給對應的JSP 處理。在這一模式中,JSP負責生成動態的網頁,Servlet負責流程控制,JavaBean負責業務邏輯。Model 2 中採用了較佳的MVC 模式,但Model2 容易使系統出現多個Controller,而且對頁面導航的處理也比較複雜,有些人以爲model 2仍不夠好,因而Craig R. McClanahan 於2000年5月提交了一個WEB framework給Java Community,這就是後來的Struts。2001年7月,Struts1.0正式發佈。

圖13-5 Model 2
版權方受權希賽網發佈,侵權必究
第 13 章:Struts開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
Struts的工做原理
做爲一個MVC的框架,Struts對Model、View和Controller都提供了對應的實現組件,圖13-6顯示了Struts框架響應客戶請求時各個組成部分的工做原理。

圖13-6 Struts的組件結構
一、視圖
Struts應用程序中的View主要採用JSP技術和通用標籤庫技術實現。利用Struts提供的自定義標記庫(tag libraries)定義的標記建立的JSP表單,能夠實現和Model部分中的ActionForm的映射,完成對用戶數據的封裝,同時這些自定義標記還提供了像模板定製等多種顯示功能。
二、模型
Struts爲Model部分提供了Action和ActionForm對象:全部的Action處理器對象都是開發者從Struts的Action類派生的子類。Action處理器對象封裝了具體的處理邏輯,調用業務邏輯模塊,而且把響應提交到合適的View組件以產生響應。Struts提供的ActionForm組件對象,它能夠經過定義屬性描述客戶端表單數據。開發者能夠從它派生子類對象,利用它和Struts提供的自定義標記庫結合能夠實現對客戶端的表單數據的良好封裝和支持,Action處理器對象能夠直接對它進行讀寫,而再也不須要和request、response對象進行數據交互。經過ActionForm組件對象實現了對View和Model之間交互的支持。
三、控制器
在Struts中,Controller功能由圖中ActionServlet和ActionMapping對象實現。ActionServlet接受客戶端的請求,而ActionServlet包括一組基於配置的ActionMapping對象,每一個ActionMapping對象實現了一個請求到一個具體的Model部分中Action處理器對象之間的映射。因此,Controller的做用是從客戶端接受請求,而且選擇執行相應的業務邏輯,而後把響應結果送回到客戶端。
Struts的工做流程歸納以下:
一、用戶提出請求,Controller ActionServlet接受此請求並在struts-config.xml文件中檢索與用戶請求相匹配的ActionMapping實例,若是找不到則返回用戶請求路經無效的信息。
二、若是找到,則利用配置的ActionMapping對象把請求映射到Action處理器對象進行處理。Action處理對象訪問ActionForm中的數據,處理和響應客戶請求。Action處理器對象根據處理結果通知Controller,Controller進行下一步的處理。
三、Controller最後將Model處理的結果經過調用View呈現給用戶。
Struts可到以下的網址下載獲得:
http://struts.apache.org/downloads.html
目前Struts的版本比較多,在這兒咱們以struts-1.3.8版本爲例介紹它的安裝方法。解壓後的目錄結構如圖13-7所示。

圖13-7 Struts1.3.8目錄結構
要使用Struts開發應用程序,就必須把Struts的解壓包lib文件夾下的庫文件拷到應用程序的「WEB-INF\lib」文件夾下;把全部擴展名爲tld的標籤庫文件拷到WEB-INF文件夾下,以便使用標籤庫中提供的標記來建立JSP視圖。在Struts1.3.8中,讀者能夠到「src\taglib\src\main\resources\META-INF\tld」文件夾下找到標籤庫文件。此外,開發應用程序時所建立的struts-config.xml和web.xml配置文件也要放到WEB-INF\文件夾下。下面就來給介紹Struts的這兩個配置文件。
一、web.xml文件
web.xml文件是整個web工程的配置文件,它負責對Web工程的ActionServlet類、Struts標籤庫等進行配置。
web.xml文件
<!--web.xml文件以一個xml頭開始,聲明能夠使用的xml版本爲1.0, -->
<!--並給出文件的字符編碼爲UTF-8-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<!--頂層根元素爲web-app -->
<!--注意:xml元素大小寫敏感,如WEB-APP、WEB-app都是非法的,只能寫爲web-app-->
<!--xml還對元素次序敏感,如xml頭和web-app的次序不能改變-->
<!--下面的servlet元素也必須出如今全部servlet-mapping元素以前-->
<!--元素次序不對時,服務器能夠拒絕執行web應用-->
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
>
<servlet>
<!--<servlet-name>元素定義用於Web應用的servlet-->
<!--<servlet-name>和<servlet-class>指定由ActionServlet接受請求,並肯定其如何響應-->
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<!--<init-param>元素定義servlet初始化參數-->
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<!--下面的debug爲整數值,指定將處理的詳細信息寫到控制檯的程度-->
<!--默認值爲0,表示記錄相對最少的日誌信息-->
<init-param>
<param-name>debug</param-name>
<param-value>3</param-value>
</init-param>
<!--detail參數指示將「映射」詳細信息寫到控制檯的程度-->
<init-param>
<param-name>detail</param-name>
<param-value>3</param-value>
</init-param>
<!--使用<load-on-startup>實如今啓動應用程序時裝入servlet的功能-->
<load-on-startup>0</load-on-startup>
</servlet>
<!--<servlet-mapping>元素指定URL結尾的命名模式-->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!--<welcome-file-list>元素指定歡迎頁面-->
<welcome-file-list>
<welcome-file>hello.jsp</welcome-file>
</welcome-file-list>
<!--聲明web應用所使用的Struts標籤庫,也可聲明用戶自定義標籤庫-->
<taglib>
<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
</web-app>
二、struts-config.xml文件
struts-config.xml是建立Struts框架的配置文件,在此文件中對Struts用到的視圖、模型和控制器進行配置。Struts框架容許把應用劃分紅多個組件以提升開發速度,而Struts框架的配置文件struts-config.xml能夠把這些組件組裝起來,決定如何使用它們。
struts-config.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<!-- <form-beans>元素配置了一個ActionForm Bean,名叫HelloForm -->
<!-- 其對應的類爲hello.HelloForm -->
<form-beans>
<form-bean name="HelloForm" type="hello.HelloForm"/>
</form-beans>
<!-- <action-mappings>元素配置了一個Action組件-->
<!--parh屬性指定請求訪問Action的路徑爲HelloWorld.do -->
<!--type屬性指定Action的完整路徑爲hello.HelloWorld -->
<!--scope屬性指定ActionForm Bean的存放範圍爲request -->
<!-- validate屬性指定是否執行表單驗證-->
<!--input屬性指定當表單驗證失敗時的轉發路經爲hello.jsp -->
<action-mappings>
<action path = "/HelloWorld"
type = "hello.HelloAction"
name= "HelloForm"
scope = "request"
validate = "true"
input = "/hello.jsp"
>
<!--<action>元素還包含<forward>子元素,來定義請求轉發路經-->
<forward name="SayHello" path="/hello.jsp" />
</action>
</action-mappings>
<!--<message-resources>元素定義了Resources Bundle使用的資源文件-->
<!-- parameter屬性定義了該資源文件的文件名爲hello. ApplicationResources -->
<!--全名爲hello. ApplicationResources .properties-->
<!--存放路徑爲WEB-INF/classes/hello/ ApplicationResources.properties-->
<message-resources parameter="hello.ApplicationResources "/>
<!--< plug-in >元素配置Struts插件,能夠包含零個或多個<set-property >子元素-->
<!--本例配置了驗證規則Validator插件-->
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property value="/WEB-INF/validator-rules.xml,
/WEB-INF/asset-validation.xml" property="pathnames" />
</plug-in>
</struts-config>
本例中的<action>元素配置了HelloAction組件,對應的類爲hello.HelloAction,請求訪問路徑爲HelloWorld.do,當Action類被調用時,Struts框架應該把已經包含表單數據的HelloForm Bean傳給它,HelloForm Bean存放在request範圍內,而且在調用Action類以前,應該進行表單驗證(表單驗證規則存在於validator-rules.xml 和asset-validation.xml文件中)。若是表單驗證失敗,請求將被轉發到接收用戶輸入的網頁hello.jsp,讓用戶糾正錯誤。
三、ApplicationResources.properties文件
ApplicationResources.properties是Struts中的消息資源文件,用來支持國際化和本地化。除了默認的消息資源文件(使用本地語言編寫)之外,一個web應用能夠包含不少個用不一樣語言編寫的消息資源文件。下面咱們來看一下用Strtus實現國際化和本地化的步驟:
首先要定義資源文件的名稱,通常命名爲ApplicationResources.properties。這個文件包含了用默認語言編寫的在程序中會出現的全部消息,這些消息以「關鍵字-值」的形式存儲。ApplicationResources.properties文件的內容以下:
login.title=Struts Demo
login.heading=<h1>Welcome to the StrutsDemo !</h1>
lgoin.message=Welcome to the StrutsDemo !
login.inputPassword=Please input Password :
login.inputName=Please input Username :
loginOK.title= User Login Successfull
loginOK.message=<h1>Login Successfull !</h1>
error.username.required=<h3><font color="red">UserName is Required !</font></h3>
error.password.required=<h3><font color="red">Password is Required !</font></h3>
error.username.wrong=<h3><font color="red">UserName is Wrong !</font></h3>
error.password.wrong=<h3><font color="red">Password is Wrong !</font></h3>
errors.footer=</ul><hr>
errors.header=<h3><font color="red">Validation Error</font></h3>You must correct the following error(s) before proceeding:<ul>
error.email.exist=<h3><font color="red">emaail 已經存在 !</font></h3>
error.emailpwd.error=<h3><font color="red">emaail 兩次輸入密碼不一致!</font></h3>
error.dlzh.exist=<h3><font color="red">登陸賬號 已經存在 !</font></h3>
error.dlzhpwd.error=<h3><font color="red">登陸賬號 兩次輸入密碼不一致!</font></h3>
這個文件須要存儲在類的路徑下,並且它的路徑要做爲初始化參數傳送給ActionServlet,做爲參數進行傳遞時,路徑的格式要符合完整Java類的標準命名規範。在struts-config.xml中已給你們講過定義方法,在此再也不累述。
其次,爲了實現國際化,全部的資源文件必須都存儲在基本資源文件所在的目錄中。基本資源文件就是用默認地區語言-本地語言編寫的消息。若是基本資源文件的名稱是ApplicationResources.properties,那麼用其餘特定語言編寫的資源文件的名稱就應該是ApplicationResources_xx.properties(xx爲ISO編碼,如英語是en)。這些文件應包含相同的關鍵字,但關鍵字的值是用特定語言編寫的。
最後,ActionServlet的區域初始化參數必須與一個true值一塊兒傳送,這樣ActionServlet就會在用戶會話中的Action.LOCALE_KEY關鍵字下存儲一個特定用戶計算機的區域對象。
版權方受權希賽網發佈,侵權必究
第 13 章:Struts開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月07日
如何利用Struts開發Web應用
Struts能夠集成到不少開發環境中去來開發Web應用程序,在這裏選用MyEclipse+Tomcat +Struts的環境配置。
【例13-1】 第一個Struts程序
下面以一個最簡單的例子來給你們講解一下Struts的應用。該例子將實現一個簡單的用戶登錄功能。處理邏輯如圖13-8所示。

圖13-8 用戶登錄處理流程圖
首先用戶進入登錄界面login.jsp,輸入用戶名和密碼(設都爲struts)。此登陸頁將調用LoginAction 來執行用戶的登陸操做。若是出現驗證錯誤或問題,LoginaAction 將引導用戶返回 login.jsp 頁面。然而,若是登陸成功,應用將轉向 loginSuccess.jsp 頁面,用戶可從新輸入。實現步驟以下:
一、先建立一個 Web Project,經過菜單 File > New > Project > MyEclipse>J2EE Projects> Web Project ,出現如圖13-9所示界面。

圖13-9 配置Web工程
輸入工程名ch13,其它項默認,而後單擊Finish按鈕,這樣咱們就建立了一個Web工程。
二、爲ch13工程添加Struts組件。 選中ch13工程,點擊右鍵,MyEclipse > Add Struts Capabilities… 。出現如圖13-10所示界面。

圖13-10 配置Struts Capabilities
這兒咱們將該項目所建立的類存放到test包下,其它選項默認,點擊Finish按鈕,這樣咱們就把Struts所需的組件添加到項目ch13中,添加後的項目的目錄結構如圖13-11所示。

圖13-11 ch13的目錄結構
四、建立Struts應用。咱們先來建立login.jsp及其ActionForm 和 Action。
經過菜單選擇 File > New > Other... > Web-Struts > Struts 1.1> Struts 1.1 Form,Action & JSP, 如圖13-12所示。

圖13-12 New Form對話框
在Use case中輸入登錄用例的名字login(注意:Use case的名字必須輸入),則Name與Form type兩項則會自動填充。而後選中Form Properties標籤項,點擊Add按鈕,出現如圖13-13所示界面,爲login.jsp表單添加兩個屬性name和password。其中,須要把password屬性的JSP input type設爲password,這樣能夠在輸入密碼時不顯示輸入的內容。

圖13-13 添加表單屬性
而後選中Methods標籤,使複選框處於非選中狀態;選擇JSP標籤,選中複選框,併爲建立的JSP文件指定存放路經。如圖13-14所示。

圖13-14 建立JSP頁面
設置完畢後,單擊 Next 按鈕,出現 New Action 對話框,如圖13-15所示。在此對話框爲一些選項提供了默認值,在此無需修改。

圖13-15 New Action對話框
在此對話框可單擊 Forwards 標籤來定義重定向的屬性,定義後的屬性如圖13-16所示。

圖13-16 定義ActionForwards
至此就完成了login用例的JSP、Action和ActionForm的建立。MyEclipse 會自動更新 struts-config.xml 文件。建立成功後的各文件代碼以下:
login.jsp
<%@ page language="java"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>
<html>
<head>
<title>JSP for loginForm form</title>
</head>
<body>
<html:form action="/login">
name : <html:text property="name"/><html:errors property="name"/><br/>
password : <html:password property="password"/>
<html:errors property="password"/><br/>
<html:submit/><html:cancel/>
</html:form>
</body>
</html>
LoginForm..java
package test.form;
import org.apache.struts.action.ActionForm;
public class LoginForm extends ActionForm {
private String password;
private String name;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
LoginAction.java
package test.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import test.form.LoginForm;
public class LoginAction extends Action {
/**
* Method execute
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
*/
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
LoginForm loginForm = (LoginForm) form;
if(loginForm.getName().equals("struts") &&
loginForm.getPassword().equals("struts"))
{
request.setAttribute("Name", loginForm.getName()); //蔣獲取的輸入的用戶名賦給Name,以便在登錄成功頁面顯示登錄成功的用戶名
return mapping.findForward("success");
}
return mapping.findForward("failure");
}
}
Struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<data-sources />
<form-beans >
<form-bean name="loginForm" type="test.form.LoginForm" />
</form-beans>
<global-exceptions />
<global-forwards />
<action-mappings >
<action
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
type="test.action.LoginAction">
<forward name="failure" path="/login.jsp" />
<forward name="sucess" path="/loginSuccess.jsp" />
</action>
</action-mappings>
<message-resources parameter="test.ApplicationResources" />
</struts-config>
五、下面還須要建立登錄成功的頁面loginSuccess.jsp。這只是單純的一個JSP頁面,咱們只需經過New>JSP,出現如圖13-17所示對話框。

圖13-17 new JSP page對話框
點擊Finish後,編寫代碼以下:
loginSuccess.jsp
<%@ page language="java" pageEncoding="UTF-8" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-tiles" prefix="tiles" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-template" prefix="template" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-nested" prefix="nested" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html:html locale="true">
<head>
<title>loginSuccess.jsp</title>
</head>
<body>
<h2>Hello,<bean:write name="Name" scope="request" />! you successfully logged in!</h2>
</body>
</html:html>
五、把建立的應用程序部署到 Tomcat5服務器 。單擊工具條上的 Deploy J2EE Project to Server…按鈕,按鈕如圖13-18所示,出現圖13-19所示的對話框,在此對話框中,從Project下拉列表框選擇ch13,而後點擊Add按鈕,在彈出的對話框中選擇Tomcat 5,肯定以後顯示Successfully deployed說明部署成功。

圖13-18 Deploy Project按鈕

圖13-19 Project Deployments對話框
六、運行應用程序。在圖13-18所示的工具條中點擊Open MyEclipse Web Browser按鈕,而後在地址欄內輸入http://localhost:8080/ch13/login.jsp,則運行效果如圖13-20所示。

圖13-20 運行login.jsp
若是在兩文本框中分別輸入’」struts」,則顯示圖13-21所示頁面,說明登錄成功。

圖13-21 登錄成功界面
版權方受權希賽網發佈,侵權必究
第 13 章:Struts開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月10日
Struts標籤庫
Struts主要提供瞭如下幾類標籤庫:
一、HTML標籤:用來生成HTML標籤,提供顯示HTML對象的簡便方法。
二、Bean 標籤:用於訪問JavaBeans及其關聯屬性,以及定義一個新的bean。
三、Logic 標籤:用於在JSP中控制流程、支持邏輯構造,管理條件產生的輸出和對象集產生的循環 。
四、Template 標籤:使用動態模板構造普通格式的頁面。
五、Nested標籤:用於表達JavaBean之間的嵌套關係
在本書中咱們只給你們介紹前三個經常使用的標籤庫。
版權方受權希賽網發佈,侵權必究
第 13 章:Struts開發做者:鄧子云,赫斌等 來源:希賽網 2014年03月10日
HTML標籤庫
在文件struts-html.tld中定義了HTML 標籤庫的標記庫描述器。Struts HTML標記能夠大體地分爲如下幾個部分:
一、基本元素
(1)<html:html>標記
<html:html>標記在文件的起始位置產生<html>元素。該標記在1.2之前版本中有一個local屬性,但到了1.2版本之後被lang屬性所取代。以下的語句是使用<html:html>標記的一個示例:
<html:html lang="true">
當使用lang="true"屬性時,頁面將根據客戶端瀏覽器提供的Accept-Language頭部,來設置其locale值。
(2)<html:base>標記
<html:base>標記在文件的<head>處產生一個<base>的HTML元素,用於生成當前網頁的絕對URL路經。這個標籤只有內嵌在head標籤中才有效。
(3)<html:img>標記
<html:img>標記用來指定所顯示的圖像,屬性page用來指定圖像文件的路徑,還可經過heignt、width屬性來指定圖像顯示時的大小。以下的語句是使用<html:img>標記的一個示例:
<html:img page="/logo.gif" height="50" width="200">
這個語句的功能是顯示logo圖像,高度爲50像素,寬度爲200像素。
(4)<html:link>標記和<html:rewrite>標記
<html:link>標記用來產生HTML中的<a>標記,而<html:rewrite>標記只能用來建立超連接中的URI部分,並不生成HTML的<a>元素。以下的語句是使用<html:link>標記的一個示例:
<html:link page="/index.html">Click Here</html:link>
二、基本表單元素
(1)<html:form>標記
<html:form>標記用來顯示HTML表單,能夠在此標記中指定AcitonForm bean的名稱和它的類名。若是沒有設置這些屬性,就須要有配置文件來指定ActionMapping以代表當前輸入的是哪一個JSP頁,以及從映射中檢索的bean名和類。若是在ActionMapping指定的做用域中沒有找到指定的名稱,就會建立並存儲一個新的bean,不然將使用找到的bean。
咱們下面所介紹的各類HTML輸入字段要內嵌在<html:form>標記中。<html:form>標記屬性如表13-1所示。
表13-1 <html:form>標記屬性

以下的語句是使用<html:form>標記的一個示例:
<html:form action="validateEmploee.do" method="post"/>
與表單相關的操做路徑是validateEmployee,而表單數據是經過POST傳遞的。對於這個表單來講,ActionForm bean的其餘信息,如bean名稱類型、做用域,都是從表單指定操做的ActionMapping中檢索獲得的。
(2)<html:text>和<html:textarea>標記
<html:text>和<html:textarea>標記分別表示HTML文�