| |||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
---|---|---|---|---|---|---|---|---|---|
27 | 28 | 29 | 30 | 1 | 2 | 3 | |||
4 | 5 | 6 | 7 | 8 | 9 | 10 | |||
11 | 12 | 13 | 14 | 15 | 16 | 17 | |||
18 | 19 | 20 | 21 | 22 | 23 | 24 | |||
25 | 26 | 27 | 28 | 29 | 30 | 31 | |||
1 | 2 | 3 | 4 | 5 | 6 | 7 |
Java語言規(guī)定標識符是以字母、下劃線"_"或美元符號"$"開始,隨后可跟數字、字母、下劃線或美元符號的字符序列。
Java標識符大小寫敏感,沒有長度限制,可以為標識符取任意長度的名字,但關鍵字不能作為標識符。
n
總結:
這是我在網上找到的資料,本來我以為我知道他們的區(qū)別,認為主要是當前的請求變量是否繼續(xù)有效,但看了這個,了解了請求的作用范圍,才完全明白其中的原因,希望對大家有用。
不要僅僅為了把變量傳到下一個頁面而使用session作用域,那會無故增大變量的作用域,轉發(fā)也許可以幫助你解決這個問題。
重定向:以前的request中存放的變量全部失效,并進入一個新的request作用域。
轉發(fā):以前的request中存放的變量不會失效,就像把兩個頁面拼到了一起。
正文開始:
先是看上去不同,他們的調用分別如下:
request.getRequestDispatcher("apage.jsp").forward(request, response);//轉發(fā)到apage.jsp
response.sendRedirect("apage.jsp");//重定向到apage.jsp
在jsp頁面中你也會看到通過下面的方式實現轉發(fā):
<jsp:forward page="apage.jsp" />
提到轉發(fā)和重定向就不得不提到request作用域。很多初學者都知道當我們提交一個表單時,就創(chuàng)建了一個新的請求。實際上,當我們點擊一個鏈接時,也創(chuàng)建了一個新的請求。那么一個請求的作用域到底有多大呢?例如:
在頁面a.jsp中有一個鏈接<a href="b.jsp?id=1">這是指向b的一個鏈接,而且還帶了一個參數</a>。當我們點擊這個連接的時候,就產生了一個請求,為了明確起見,我們把它叫做requestA->B。現在,在b.jsp頁面中我們就可以從這個請求中獲取信息了。在b.jsp中你可以寫入out.println(request.getParameter("id"))進行測試。下面更復雜一點,我們在b.jsp頁面中增加下面的語句:
request.setAttribute("name","funcreal");
out.println(request.getAttriblute("name"));//成功顯示了name變量的值。
現在在b.jsp中再增加一個鏈接:<a href="c.jsp?age=23">這是指向c的一個鏈接,而且還帶了一個參數</a>,當我們點擊這個連接的時候,將產生一個新的請求,這時requestA-B也就安息了,新的請求叫做requestB-C。同樣的道理,在c.jsp中,我們可以訪問到的變量只有age,因為id,name這兩個變量都屬于requestA-B,此時他已經不存在了。下面是源代碼:
a.jsp
<%@ page c %>
<html>
<body bgcolor="#ffffff">
<a href="b.jsp?id=1">指向b.jsp,而且還帶了一個參數id=1。requestA-B現在誕生了</a>
</body>
</html>
b.jsp
<%@ page c %>
<html>
<body bgcolor="#ffffff">
<%
out.println("id=" + request.getParameter("id"));
request.setAttribute("name","Func Real");
out.println("name=" + request.getAttribute("name"));
%>
<a href="c.jsp?age=23">requestA-B已經結束了。指向c.jsp,而且還帶了一個參數age=23</a>
</body>
</html>
c.jsp
<%@ page c %>
<html>
<body bgcolor="#ffffff">
<%
out.println("id=" + request.getParameter("id"));
out.println("name=" + request.getAttribute("name"));
out.println("age=" + request.getParameter("age"));
%>
</body>
</html>
那么轉發(fā)又是怎么回事呢?現在增加一個頁面叫做d.jsp,并且在c.jsp中</body>前面增加一句<jsp:forward page="d.jsp"/>
d.jsp
<%@ page c %>
<html>
<body bgcolor="#ffffff">
requestB-C的魔爪已經伸到了d.jsp頁面
<%
out.println("age=" + request.getParameter("age"));
%>
</body>
</html>
運行程序,你會發(fā)現c頁面中的內容沒有顯示出來,因為forward是自動執(zhí)行的,地址欄中雖然是c.jsp但實際上,但瀏覽器中顯示的已經是d.jsp的內容了,而且看到了從b.jsp傳過來的參數。你可以簡單得這樣理解:轉發(fā),就是延長了requestB-C的作用域,<jsp:forward page="d.jsp"/>,這一句話實際上是把c.jsp和d.jsp粘到了一起,他們就像是在一個頁面中。
如果你用過struts,那么你就知道為什么在Action中,最后一句幾乎總是mapping.findForward("xxx");了。因為我們在這個Action中設置的請求作用域的變量都將會在下一個頁面(也許是另一個Action)中用到,所以要用轉發(fā)。
總結:
用重定向和轉發(fā)不是一個習慣問題。而是什么情況下必須用什么的問題。
不要僅僅為了把變量傳到下一個頁面而使用session作用域,那會無故增大變量的作用域,轉發(fā)也許可以幫助你解決這個問題。
重定向:以前的request中存放的變量全部失效,并進入一個新的request作用域。
轉發(fā):以前的request中存放的變量不會失效,就像把兩個頁面拼到了一起。
forward是服務器請求資源,服務器直接訪問目標地址的URL,把那個URL的響應內容讀取過來,然后把這些內容再發(fā)給瀏覽器,瀏覽器根本不知道服務器發(fā)送的內容是從哪兒來的,所以它的地址欄中還是原來的地址。
redirect就是服務端根據邏輯,發(fā)送一個狀態(tài)碼,告訴瀏覽器重新去請求那個地址, web應用程序會要求客戶端瀏覽器重新發(fā)出請求地址,客戶端會重新連接至所指定的地址,因此瀏覽器的地址會出現重新導向的信息,重新導向后的請求由瀏覽器發(fā)出。
forward與include共享Request范圍內的對象,而redirect則不行,
forward與include基本上都是轉發(fā)到context內部的資源,而redirect可以重定向到外部的資源
在網上看到很多說法:可是經本人驗證這種說話是不完全正確的,至少動態(tài)<jsp:inlude>指令是可以包含動態(tài)頁面的。
個人認為區(qū)別是:
1<jsp:inlude>在同一個頁面中可以包含盡可能多的條數,不管這個頁面中有什么內容,只要頁面本身合法就行,而<%@ include>偽指令如果被包含頁面有定義變量和方法的話只能包含一條。
(這個是和第二條的編譯方式相一致的)
2動態(tài)包含在請求到來時編譯包含頁面和被包含頁面,如果都是jsp頁面,那么將生成倆個頁面對應的class文件和java文件。而靜態(tài)包含只會生成包含頁面的java文件和類文件。
3所謂動態(tài)包含是指在請求包含頁面的時候遇到動態(tài)包含指令將請求轉到被包含頁面,這時去編譯被包含頁面。靜態(tài)包含是在請求包含頁面時去編譯包含頁面,編譯時遇到靜態(tài)頁面包含偽碼將被包含頁面的內容復制到被包含頁面中進行編譯。
4<jsp:inlude >指令時相對包含頁面的被包含文件路徑,但靜態(tài)包含是相對被包含文件路徑的。(這一點孫鑫老師在《java web 深入詳解》中講的很清楚)
5引用被包含頁面的范圍屬性時動態(tài)包含的指令是與位置相關的,即在<jsp:include>指令之前引用被包含頁面中設置的屬性值是無效的。但是靜態(tài)包含是不區(qū)分包含指令的位置的,可以在包含指令之前引用被包含頁面設置的屬性,是有效的。
倆者是有相同點的:
1 都可以進行交互,request范圍對象中的屬性包含頁和被包含頁之間可以交互使用。
2被包含頁面中引用包含頁面設置的屬性時倆者都和設置包含頁面中范圍屬性的值有關,即在包含被包含頁面之前設置的范圍屬性才有效。
代碼如下: 包含頁面: index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8" buffer="23kb"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>this is 'index.jsp' </title>
</head>
<body>
這是包含頁面<br/>
<%--靜態(tài)包含前引用被包含頁面設置的屬性 --%>
${name }靜態(tài)包含前引用被包含頁面設置的屬性<br/>
<%--包含頁面設置屬性 --%>
<%request.setAttribute("pws","456") ;%>
<%--<%@include file="MyJsp.jsp"%>此處因為MyJsp.jsp中定義了變量,固不可以重復包含 --%>
<%-- --%><%@include file="MyJsp.jsp" %>
${name }包含靜態(tài)頁面之后引用屬性<br/>
<%--此處沒有you.jsp中沒有定義變量,所以可以重復包含 --%>
${wangzhanming }<br/>
<%@include file="you.jsp" %>
<%@include file="you.jsp" %>
${wangzhanming }<br/>
<jsp:include page="MyJsp.jsp" ></jsp:include>
<jsp:include page="MyJsp.jsp" ></jsp:include>
<%request.setAttribute("pws","lyx") ;%>
<%--此處可以重復包含--%>
<jsp:include page="MyJsp.jsp" ></jsp:include>
<%@include file="you.jsp" %>
${name }<br/>
</body>
</html>
設置變量的包含頁面: MyJsp.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%--定義變量 --%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>this is 'MyJsp.jsp' </title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
這是定義變量的包含頁面<br/>
<%--被包含頁面中設置范圍屬性 --%>
<%request.setAttribute("name","wzm"); %>
${name } <br>
<%--被包含頁面中引用包含頁面的屬性 --%>
${pws }<br/>
</body>
</html>
不包含變量設置的被包含頁面: you.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<html>
<head>
<title>this is 'you.jsp' </title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
這是不定義變量的被包含頁面 <br>
<%request.setAttribute("wangzhanming","haoren"); %>
${wangzhanming }<br/>
${pws }<br/>
</body>
</html>
一.指令元素
1.page指令
import
session
contentType
buffer
isTreadSafe
info
errorPage
isErrorPage
2.include指令
3.taglib指令
二.腳本元素
1.聲明元素
2.表達式元素
3.腳本元素
4.注釋元素
三.標準動作元素
1.<jsp:param>
2.<jsp:include>
3.<jsp:forward>
4.<jsp:plugin>
5.<jsp:useBean>
6.<jsp:setProperty>
7.<jsp:getProperty>
四.內置對象
1.request
2.response
3.out
4.session
5.pageContext
6.application
7.config
8.page
9.exception
五.JavaBeans的使用
1.JavaBeans在JSP中的基本使用格式
2.scope范圍的具體設定
3.session事件的運用
4.Bean的保存與讀取
六.JSP中的文件操作
七.JSP運行原理剖析
-------------------------------------------------
在早期,開發(fā)網絡數據庫應用程序主要采用CGI(Common Gateway Interface)技術。編寫CGI程序可以使用不同的程序語言,如Perl、Visual Basic、Delphi或C/C++等。雖然CGI技術已經發(fā)展成熟而且功能強大,但由于其編程困難、效率低下、修改復雜等缺陷,所以有被新技術取代的技術。
在這樣的背景下,新的技術紛紛面世,如ASP(Active Server Page)、PHP(Personal Home Page)、JSP(Java Server Page)等。其中,JSP被許多人認為是未來最有發(fā)展前途的動態(tài)網站技術。
JSP頁面一般由HTML標簽和JSP元素構成,其中的JSP元素則又是由“指令元素”、“腳本元素” 、“標準動作元素” 、“內置對象”四個部分組成。下面,就讓我們一起來探究JSP的奧秘吧……
一. 指令元素
可以把JSP理解為用來通知JSP引擎的消息。JSP不直接生成可見的輸出,用JSP指令設置JSP引擎處理JSP頁面的機制。
一般JSP指令用標簽<%@…%>表示,JSP指令包括page、include和taglib。page指令是針對當前頁面的指令,而include指令用來指定如何包含另外一個文件,taglib指令用來定義和訪問自定義標記庫。這三種指令通常都有默認值,這樣開發(fā)人員就不必顯式的使用每一個指令予以確認。
1. page指令
page指令的設置語法格式是:<%@ page attribute1=”value1” attribute2=”value2”…%>
下面介紹指令中包括的幾個常用屬性,并作簡要說明。
l import
import指令是所有page指令中,唯一可以多次設置的指令,而且累加每個設置。它用來指定jsp網頁中所需要使用到的一些類。例如:
<%@ page import=”java.io.*,java.util.Date”%>
l session
定義當前頁面是否參與http會話。當設置為”true”時,可以獲得隱含名為session的對象,為”false”時,則不能。默認設置為”true”。
l contentType
設置jsp網頁輸出時數據時,所使用的字符壓縮方式,以及所使用的字符集,當編寫中文網頁時,設置如下:
<%@page contentType=”text/html;charset=Gb2312”%>
此屬性的默認值為”text/html;charset=ISO-8859-1”。
l buffer
設置jsp網頁的緩沖區(qū)大小,默認為”8k”,如果設置為”none”,則表示不使用緩沖,所有的響應輸出都將被PrintWriter直接寫到ServletResponse中。
l isTreadSafe
定義當前頁面是否支持線程安全。如果為”true”,則該頁面可能同時收到jsp引擎發(fā)出的多個請求,反之,jsp引擎會對收到的請求進行排隊,當前頁面在同一時刻只能處理一個請求。默認為”true”。
l info
設置頁面的文本信息,可以通過Servlet.getServletInfo()的方法獲得該字符串。
l errorPage
定義指向另一個jsp頁面的URL。當頁面出現一個沒有被捕獲的異常時,錯誤信息將以throw語句拋出,而被設置為錯誤信息網頁的jsp頁面,將利用exception隱含對象,取得錯誤信息。
默認沒有錯誤處理頁面。
l isErrorPage
設置此jsp網頁是否為錯誤處理頁面。默認值為”false”。當設置為”true”時,jsp頁面將可存取隱含的exception對象,并通過該對象取得從發(fā)生錯誤之網頁所傳出的錯誤信息。取得錯誤信息的語法如下:
<% =exception.getMessage()%>
² 一個頁面錯誤處理的例子
產生錯誤的頁面文件為MakeError.jsp,處理錯誤的頁面文件為ErrorPage.jsp,它們的源程序如下:
MakeError.jsp
<%@ page errorPage="ErrorPage.jsp"%>
<html>
<head>
<title>產生錯誤頁面</title>
</head>
<body>
<%
int i=8,j=0;
out.println(ij);
%>
</body>
</html>
ErrorPage.jsp
<%@ page isErrorPage="true"%>
<html>
<head>
<title>錯誤處理頁面</title>
</head>
<body>
<font color=red>
錯誤原因:<%=exception.getMessage()%>
</font>
</body>
</html>
運行程序MakeError.jsp的結果如下:
2. include指令
使用include指令可以把其他的文本文件加入到當前的jsp頁面,格式如下:
<%@ include file=”header.inc”%>
如此,則在當前頁面中加入header.inc源代碼然后再編譯整個文件。
可以使用include指令把一個頁面分成不同的部分,最后合成一個完整的文件,使用jsp的include指令有助于實現jsp頁面的模塊化。
3. taglib指令
(略)
二. 腳本元素
JSP規(guī)格提供了四種類型的腳本元素,包括:
l 聲明
l 表達式
l 腳本
l 注釋
下面分別對它們進行詳細敘述。
1. 聲明元素
聲明用于定義jsp頁面中的變量與函數,這些經過定義的變量和函數,將成為Servlet類的屬性與方法(關于Servlet請參看后文)。聲明并不會產生任何的數據輸出,聲明時可同時設置初始值,提供給其他的聲明、表達式或腳本使用。
聲明的語法格式為:
<%!
//聲明語句
%>
舉例:
<%!
//此處定義的變量將成為此jsp頁面的全局變量
int i = 0;
static int j=100;
String s = “注意”;
%>
<%!
//此處定義的函數將成為此jsp頁面的公共函數
Public int square(int i)
{
return(i*i);
}
%>
² jspInit函數與jspDestroy函數
若要在jsp頁面開始執(zhí)行時進行某些數據的初始化,可以利用jspInit函數完成。此函數將在jsp頁面被執(zhí)行時調用,且當jsp頁面重新整理時,并不會被再度執(zhí)行。當關閉服務器時,jspDestroy函數將被執(zhí)行,可以利用該函數進行數據的善后處理工作。下面舉個簡單的例子說明,文件InitDes.jsp代碼如下:
<%@ page contentType="text/html; charset=GB2312"%>
<%!
public void jspInit()
{
System.out.println("jspInit is called!");
}
public void jspDestroy()
{
System.out.println("jspDestroy is called!");
}
%>
<HTML>
<HEAD><TITLE>jspInit函數與jspDestroy函數的使用</TITLE></HEAD>
<BODY>
<CENTER>
<FONT SIZE = 5 COLOR = blue>jspInit函數與jspDestroy函數的使用</FONT>
</CENTER>
<HR><BR>
</BODY>
</HTML>
首次執(zhí)行此頁面時,Resin服務器輸出如下:
Resin 1.2.2 -- Tue Jan 16 09:53:18 PST 2001
http listening to *:8080
srun listening to 127.0.0.1:6802
jspInit is called!
刷新此頁面數次后,Resin服務器輸出仍然如上。
此時,如果關閉服務器,則輸出如下:
Resin 1.2.2 -- Tue Jan 16 09:53:18 PST 2001
http listening to *:8080
srun listening to 127.0.0.1:6802
jspInit is called!
closing server
jspDestroy is called!
由此,我們得到啟發(fā),在數據庫的開發(fā)過程中,可以利用jspInit函數來進行數據庫的連接工作,用jspDestroy函數來進行數據庫的關畢工作。下面以一個分頁顯示數據庫內容的程序為例子,讓讀者進一步體會jspInit與jspDestroy的功用與好處。
在Pages.jsp這個分頁程序中,我們把數據庫連接的動作寫在jspInit函數中,這樣,每一次重新整理頁面時,就可以避免重新執(zhí)行數據庫的連接動作。如下:
<%@ page contentType="text/html; charset=GB2312"
import="java.sql.*"%>
<%!
int PageSize = 2; //設置每張網頁顯示兩筆記錄
int ShowPage = 1; //設置欲顯示的頁數
int RowCount = 0; //ResultSet的記錄筆數
int PageCount = 0; //ResultSet分頁后的總頁數
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
public void jspInit() //執(zhí)行數據庫與相關數據的初始化
{
try
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//載入驅動程序類別
con = DriverManager.getConnection("jdbc:odbc:test");
//建立數據庫鏈接
stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
//建立Statement對象, 并設置記錄指標類型為可前后移動
rs = stmt.executeQuery("SELECT * FROM products");
//建立ResultSet(結果集)對象,并執(zhí)行SQL語句
rs.last(); //將指標移至最后一筆記錄
RowCount = rs.getRow(); //取得ResultSet中記錄的筆數
PageCount = ((RowCount % PageSize) == 0 ?
(RowCountPageSize) : (RowCountPageSize)+1);
//計算顯示的頁數
}
catch(Exception ex)
{
System.out.println(ex.toString());
}
}
public void jspDestroy() //執(zhí)行關閉各種對象的操作
{
try
{
rs.close(); //關閉ResultSet對象
stmt.close(); //關閉Statement對象
con.close(); //關閉數據庫鏈接對象
}
catch(Exception ex)
{
System.out.println(ex.toString());
}
}
%>
<HTML>
<HEAD>
<TITLE>記錄的分頁顯示</TITLE>
</HEAD>
<BODY>
<CENTER>
<FONT SIZE = 5 COLOR = blue>記錄的分頁顯示</FONT>
</CENTER>
<HR>
<P></P>
<CENTER>
<%
String ToPage = request.getParameter("ToPage");
//判斷是否可正確取得ToPage參數,
//可取得則表示JSP網頁應顯示特定分頁記錄的語句
if(ToPage != null)
{
ShowPage = Integer.parseInt(ToPage); //取得指定顯示的分頁頁數
//下面的if語句將判斷用戶輸入的頁數是否正確
if(ShowPage > PageCount)
{ //判斷指定頁數是否大于總頁數, 是則設置顯示最后一頁
ShowPage = PageCount;
}
else if(ShowPage <= 0)
{ //若指定頁數小于0, 則設置顯示第一頁的記錄
ShowPage = 1;
}
}
rs.absolute((ShowPage - 1) * PageSize + 1);
//計算欲顯示頁的第一筆記錄位置
%>
<H3>目前在第<FONT SIZE = 4 COLOR = red>
<%= ShowPage %></FONT>頁, 共有
<FONT SIZE = 4 COLOR = red>
<%= PageCount %></FONT>頁</H3>
<P></P>
<%
//利用For循環(huán)配合PageSize屬性輸出一頁中的記錄
for(int i = 1; i <= PageSize; i++)
{
%>
<TABLE border=1 bordercolor=RoyalBlue bgcolor=LightBlue>
<TR><TD bgcolor=LightYellow width= 100>
<B>商品名</B></TD>
<TD width= 100><B><%= rs.getString("product_name") %>
</B></TD>
<TD bgcolor=LightYellow width= 100>
<B>價格</B></TD>
<TD width= 100><B><%= rs.getInt("price") %>
</B></TD>
<TD bgcolor=LightYellow width= 100>
<B>描述</B></TD>
<TD width= 100><B><%= rs.getString("description") %>
</B></TD>
</TR>
</TABLE><BR>
<%
//下面的if判斷語句用于防止輸出最后一頁記錄時,
//將記錄指標移至最后一筆記錄之后
if(!rs.next()) //判斷是否到達最后一筆記錄
break; //跳出for循環(huán)
}
%>
<TABLE>
<TR valign=baseline align=center>
<%
//判斷目前所在分頁是否為第一頁,
//不是則顯示到第一頁與上一頁的超鏈接
if(ShowPage != 1)
{
//下面建立的各超鏈接將鏈接至自己,
//并將欲顯示的分頁以ToPage參數傳遞給自己
%>
<TD Width=150>
<A Href=Pages.jsp?ToPage=<%= 1 %>>到第一頁</A>
</TD>
<TD Width=150>
<A Href=Pages.jsp?ToPage=<%= ShowPage - 1 %>>到上一頁</A>
</TD>
<%
}
//判斷目前所在分頁是否為最后一頁,
//不是則顯示到最后一頁與下一頁的超鏈接
if(ShowPage != PageCount)
{
//下面建立的各超鏈接將鏈接至自己,
//并將欲顯示的分頁以ToPage參數傳遞自己
%>
<TD Width=150>
<A Href=Pages.jsp?ToPage=<%= ShowPage + 1%>>到下一頁</A>
</TD>
<TD Width=150>
<A Href=Pages.jsp?ToPage=<%= PageCount %>>到最后一頁</A>
</TD>
<%
}
%>
<TD Width=150>
<FORM action=Pages.jsp method=POST>
到
<!--
供用戶輸入欲查看頁數的文字方塊, 預設值為目前所在的分頁,
當用戶在此文字方塊中完成數據輸入后按下 Enter 即可將數據送出,
相當于按下Submit按鈕, 因此此表單中將省略Submit按鈕
-->
<INPUT type="text" name=ToPage style="HEIGHT: 25px; WIDTH: 40px"
value=<%= ShowPage%> > 頁
</FORM></TD></TR>
</TABLE>
</CENTER>
</BODY>
</HTML>
執(zhí)行后,結果如下圖:
2. 表達式元素
表達式是一個簡化了的out.println語句。
表達式的語法格式為:
<%=//要輸出的數據%>
舉例:
<%=square(5)%>
3. 腳本元素
腳本是java程序的一段代碼,只要符合java語法的語句都可以寫在這里,它是在請求時期執(zhí)行的,它可以使用jsp頁面所定義的變量、方法、表達式或JavaBeans。
腳本的語法格式為:
<%
//java代碼
%>
舉例:
<%
if(age<18)
{
out.println(“你是未成年人?。。。?#8221;);
}
else
{
out.println(“你已經成年了!?。?!”);
}
%>
4. 注釋元素
用來對程序進行說明注釋。注釋大體有下列三種格式:
<!—客戶端注釋à
<!--<%=客戶端動態(tài)注釋%>-->
<%--服務器端注釋--%>
三. 標準動作元素
標準動作元素用于執(zhí)行一些常用的JSP頁面動作,例如:將頁面轉向、使用JavaBean、設置JavaBean的屬性等。在JSP中,標準動作元素共有以下幾種:
l <jsp:param>
l <jsp:include>
l <jsp:forward>
l <jsp:plugin>
l <jsp:useBean>
l <jsp:setProperty>
l <jsp:getProperty>
其中<jsp:useBean>、<jsp:setProperty>、<jsp:getProperty>這三個是專門用來操作JavaBeans的。
下面分別介紹它們。
1. <jsp:param>
<jsp:param>動作用于傳遞參數,必須配合<jsp:include>、<jsp:forward>、<jsp:plugin>動作一起使用。
語法格式:
<jsp:param name = “name1” value = “value1”/>
2. <jsp:include>
<jsp:include>動作用于動態(tài)加載HTML頁面或者JSP頁面。
語法格式:
<jsp:include page = “網頁路徑”>
<jsp:param name = “name1” value = “value1”/>
<jsp:param name = “name2” value = “value2”/>
<jsp:include/>
在jsp頁面中,可以利用下面的語法取得返回的參數:
request.getParameter(“name1”);
若不傳遞參數時,則語法格式如下:
<jsp:include page = “網頁路徑”/>
舉例:
a.jsp頁面代碼如下:
<jsp:include page = "b.jsp">
<jsp:param name = "name1" value = "value1"/>
<jsp:param name = "name2" value = "value2"/>
</jsp:include>
b.jsp頁面代碼如下:
名字1、;<%=request.getParameter("name1")%>
<hr color=red>
名字2、;<%=request.getParameter("name2")%>
執(zhí)行結果如下:
“include標準動作”和“include指令”的差別在于:“include標準動作”包含的頁面在運行時被加入,而“include指令”在編譯時就被加入了。
3. <jsp:forward>
<jsp:forward>動作用于將瀏覽器顯示的頁面導向到另一個HTML頁面或者jsp頁面。
語法格式:
<jsp:forward page = “網頁路徑”/>
當然,<jsp:forward>動作中也可以加入<jsp:param>參數,其設置和獲得參數的方法與<jsp:include>類似。
4. <jsp:plugin>
<jsp:plugin>動作用于加載applet,用途與HTML語法中的<Applet>及<Object>標記相同。該動作是在客戶端執(zhí)行的,這里就不作介紹了。
5. <jsp:useBean>
(見后文的“JavaBeans”的使用)
6. <jsp:setProperty>
(見后文的“JavaBeans”的使用)
7. <jsp:getProperty>
(見后文的“JavaBeans”的使用)
四. 內置對象
在jsp頁面中有一些已經完成定義的對象,稱之為內置對象。這些對象可以不經過定義就直接使用,因為它們是由jsp頁面自己定義的。
jsp程序常用的內建對象有如下幾個:request、response、out、session、pageContext、application、config、page、exception。你可以在jsp頁面中直接使用它們,用以加強jsp程序的功能。
下面分別介紹它們。
1. request
與request相聯系的是HttpServletRequest類。通過getParameter方法可以獲得相應的參數值。
2. response
與response相聯系的是HttpServletResponse類。表示Web頁面針對請求的應答。
3. out
與out相聯系的是PrintWrite類??梢允褂么藢ο髮热葺敵龅巾撁嬷?。
4. session
與session相聯系的是HttpSession類。用來傳遞客戶的會話內容。
5. pageContext
與pageContext相聯系的是pageContext類。用它能方便的訪問本頁面中設置的共享數據。
6. application
與application相聯系的是ServletContext類。用它能夠實現應用程序級別的數據共享。
7. config
與config相聯系的是ServletConfig類。用來在jsp頁面范圍內處理jsp配置。
8. page
代表jsp頁面編譯成的Servlet實例,一般不用。
9. exception
與exception相聯系的是Throwable類。用來捕獲jsp執(zhí)行時拋出的異常。
五. JavaBeans的使用
JavaBeans是運行于java虛擬機上的100%的純java組件,它的概念描述很類似于Microsoft的COM組件概念。
JavaBeans傳統(tǒng)的應用在于可視化領域,如AWT下的應用。其實,基于AWT的任何java程序已經是一個Bean,完全可以把它當作一個組件來使用。
現在,JavaBeans更多的應用在不可視化領域,它在服務器端應用方面表現出了越來越強的生命力。不可視化的JavaBeans在JSP程序中用來封裝事務邏輯,可以很好的實現業(yè)務邏輯和前臺程序的分離,使得系統(tǒng)具有更好的健壯性和靈活性。
JavaBeans描述了JDK1.1以前的java所沒有的東西,因此,運行JavaBeans最小的需求是JDK1.1或者以上的版本。
1. JavaBeans在JSP中的基本使用格式
l 在JSP中調用JavaBeans的格式
//加載Bean
<jsp:useBean id = “名稱” scope = “有效范圍” class = “Bean類位置”/>
//設定Bean屬性(兩種方法)
//方法一:“標簽設定”
<jsp:setProperty name = “名稱” property = “屬性” value = “值”/>
//方法二:“方法設定(用于java程序中)”
Bean對象名稱.set屬性(值)
//獲取Bean屬性(兩種方法)
//方法一:“標簽獲取”
<jsp:getProperty name = “名稱” property = “屬性”/>
//方法二:“方法獲取(用于java程序中)”
Bean對象名稱.get屬性()
l JavaBean編寫的格式
//定義Bean類所屬于的包
package 包名
//定義為公開等級的類,并且類名稱與源代碼文件名相同
public class類名
{
//Bean類的屬性,其等級定義為private
private 數據類型 屬性名
//用來初始化的構造函數
//Bean的構造函數無輸入參數
public 類名
{ }
//以setXXX函數,作為設定Bean類屬性的接口
public void set屬性名稱(數據類型 參數)
{
this.屬性 = 參數
}
//以getXXX函數,作為取得Bean類屬性的接口
public void get屬性名稱()
{
return this.屬性
}
}
² 一個簡單的使用JavaBeans的例子
Bean文件LoginData.java的源代碼如下:
package j2ee.jsp;
//定義Bean所屬的包
public class LoginData
{
//Bean屬性
private String Name = "";
private String Pwd = "";
public LoginData() //構造函數
{
}
//以下為設定Bean屬性的方法
public void setLoginName(String name)
{ this.Name = name; }
public void setPassword(String pwd)
{ this.Pwd = pwd; }
//以下為取得Bean屬性的方法
public String getLoginName()
{ return this.Name; }
public String getPassword()
{ return this.Pwd; }
}
調用Bean的jsp文件UseBean.jsp源程序如下:
<%@ page contentType="text/html; charset=GB2312" %>
<HTML>
<HEAD>
<TITLE>使用Beans</TITLE>
</HEAD>
<BODY>
<CENTER>
<FONT SIZE = 5 COLOR = blue>使用Beans</FONT>
</CENTER>
<HR>
<P></P>
<H2>
<jsp:useBean id="login" scope="application"
class="j2ee.jsp.LoginData"/>
<jsp:setProperty name="login"
property="loginName" value="最后的決定"/>
<%
login.setPassword("123456"); //調用Bean對象的方法, 設定屬性
%>
<Font color = red>LoginName</Font>屬性值為
<Font color = blue>
<jsp:getProperty name="login" property="loginName"/>
</Font><BR>
<Font color = red>Password</Font>屬性值為
<Font color = blue>
<%--以調用Bean對象方法的方式取得屬性--%>
<%= login.getPassword() %></Font>
</BODY>
</HTML>
運行結果如下:
在前面的使用中,有兩點值得注意:
(1) Bean中各個方法名的“命名規(guī)則及大小寫”與調用Bean時的“方法名規(guī)則及大小寫”之間的對應關系需要注意。
(2) Beans的存放目錄將隨選用服務器的不同而不同。以resin服務器而言,Beans默認定義存放在application-programme\WEB-INF\classes子目錄中。
2. scope范圍的具體設定
JavaBeans可以定義四種生命周期?D?Dpage、request、session與application,將分別運用pageContext、request、session、application四種對象的setAttribute方法,將JavaBeans對象保存在該對象中。下面分別說明:
l Page的有效范圍僅僅涵蓋使用JavaBeans的頁面,一旦你離開此頁面,JavaBeans對象的實體也將隨之消失。
l Request的有效范圍僅及于使用JavaBeans的請求而已,一旦你結束該頁面的請求,JavaBeans對象的實體也將隨之消失。
l Session的有效范圍涵蓋了整個用戶會話時期。在用戶會話期間,JavaBeans對象的實體均不會消失。當用戶會話結束時,JavaBeans對象的實體才會消失。
l Application的有效范圍則涵蓋了整個應用程序時期。在應用程序期間,JavaBeans對象的實體均不會消失。只有當應用程序結束時,JavaBeans對象的實體才會消失。
下面,舉一個簡單的例子,對Request與Session兩種生命周期做具體的演示。
Bean文件counter.java的源代碼如下:
package j2ee.jsp;
public class counter
{
private int count = 0;
public void setCount(int c)
{
this.count = c;
}
public int getCount()
{
this.count++;
return this.count;
}
}
Request實例
兩個jsp文件b1.jsp與b2.jsp代碼分別如下:
b1.jsp
<jsp:useBean id="counter" scope="request" class="j2ee.jsp.counter"/>
<%
counter.setCount(100);
%>
<jsp:forward page="b2.jsp"/>
b2.jsp
<jsp:useBean id="counter" scope="request" class="j2ee.jsp.counter"/>
<%
out.println(counter.getCount());
%>
運行結果如下:
Session實例
兩個jsp文件c1.jsp與c2.jsp代碼分別如下:
c1.jsp
<jsp:useBean id="counter" scope="session" class="j2ee.jsp.counter"/>
<%
out.println(counter.getCount());
%>
<a href="c2.jsp" target="_blank">c2.jsp</a>
c2.jsp
<jsp:useBean id="counter" scope="session" class="j2ee.jsp.counter"/>
<%
out.println(counter.getCount());
%>
運行結果如下:
3. session事件的運用
在jsp頁面中,將Bean對象保存至session對象時,可以定義Bean響應HttpSessionBindingEvent事件。當Bean對象加入session、Bean從session中刪除以及session對象終止時,將會觸發(fā)此事件。因此,我們可以利用這兩個事件,執(zhí)行數據起始、善后的工作。
由此,我們可以想到,把jsp頁面中最耗費服務器資源的數據庫連接工作放入HttpSessionBindingEvent事件中。當一個會話開始時,建立一個“數據庫連機”,隨后的整個會話過程中,所有與數據庫相關的操作均使用這一個“連機”,這樣,就避免了每執(zhí)行一次數據庫操作就產生一個數據庫連機的巨大消耗。當此會話結束時,再關閉釋放這個“數據庫連機”。
如果要Bean對象響應HttpSessionBindingEvent事件,則該Bean對象必須實現HttpSessionBindingListener接口,并且定義響應會話開始的valueBound方法以及響應會話結束的valueUnbound方法。
現在,我們來實做一個例子,首先,建立一個“用來建立會話級別數據庫聯機”的Bean文件DBCon.java,它的源代碼如下所示:
/*
* 文件名:DBCon.java
*
* 類名:DBCon
*
* 所屬包:j2ee.jsp
*
* 導入包:java.sql.*;javax.servlet.http.*;
*
* 作者:楊??
*
* 創(chuàng)建時間:2003.12.9
*
* 用途描述:在此JavaBean中建立會話級別的數據庫聯機,供會話過程中的各個jsp頁面使用
*
* 版本號:1.0
*
*/
package j2ee.jsp;
import javax.servlet.http.*;
import java.sql.*;
//定義DBCon類別實做HttpSessionBindingListener介面
public class DBCon implements HttpSessionBindingListener
{
//與數據庫連結有關的Bean屬性
private Connection con = null;
/**
* 方法名:BulidConnection
* 級別:private
* @param (無)
* @return (無)
* @throws (無)
* 作用:建立一個數據庫聯機
*/
private void BulidConnection()
{
try
{
System.out.println("BulidConnection()方法被調用");
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//載入驅動程式類別
con = DriverManager.getConnection("jdbc:odbc:test");
//建立數據庫連線
}
catch(Exception ex)
{
System.out.println(ex.toString());
}
}
/**
* 方法名:close
* 級別:private
* @param (無)
* @return (無)
* @throws (無)
* 作用:關閉數據庫聯機
*/
private void close()
{
try
{
con.close(); //關閉Connection對象
con = null;
}
catch(SQLException sex)
{
System.out.println(sex.toString());
}
}
/**
* 方法名:getConnection
* 級別:public
* @param (無)
* @return Connection 數據庫聯機
* @throws (無)
* 作用:返回一個數據庫聯機
*/
public Connection getConnection()
{
//若con為null時, 重新建立數據庫連結
if(con == null)
BulidConnection();
return this.con;
}
/**
* 方法名:valueBound
* 級別:public
* @param HttpSessionBindingEvent 事件
* @return (無)
* @throws (無)
* 作用:建立一個數據庫聯機,并輸出相關信息
*/
public void valueBound(HttpSessionBindingEvent event)
{
BulidConnection();
System.out.println("會話級別的數據庫連接已經建立!??!");
}
/**
* 方法名:valueUnbound
* 級別:public
* @param HttpSessionBindingEvent 事件
* @return (無)
* @throws (無)
* 作用:關閉一個數據庫聯機,并輸出相關信息
*/
public void valueUnbound(HttpSessionBindingEvent event)
{
if(con != null)
close(); //呼叫close方法
System.out.println("會話級別的數據庫連接已經關閉?。。?);
}
}
編譯這個Bean源文件。注意,編譯前要設定好classpath的路徑,使得它所包含的類庫中有javax.servlet.http.*包。
然后,建立兩個用來測試此Bean的jsp頁面文件DBBean1.jsp與DBBean2.jsp,它們的程序代碼差不多,都是用來顯示數據庫內容的,現在就只列出DBBean1.jsp的源文件,如下:
<%@ page contentType="text/html; charset=GB2312"
import="java.sql.*"%>
<HTML>
<HEAD>
<TITLE>利用Bean對象建立數據庫鏈接</TITLE>
</HEAD>
<BODY>
<CENTER>
<FONT SIZE = 5 COLOR = blue>
利用Bean對象建立數據庫鏈接
</FONT>
</CENTER>
<HR>
<P></P>
<CENTER>
<%--起始建立數據庫鏈接的Bean對象--%>
<jsp:useBean id="ConBean" scope="session"
class="j2ee.jsp.DBCon"/>
<%
Connection con = ConBean.getConnection();
//從Bean對象取得已完成建立的數據庫鏈接
Statement stmt = con.createStatement();
//建立Statement對象
ResultSet rs = stmt.executeQuery("SELECT product_name, price FROM products");
//建立ResultSet(結果集)對象,并執(zhí)行SQL敘述
%>
<TABLE bgcolor=DodgerBlue>
<TR bgcolor=SkyBlue>
<TD><B>書 名</B></TD><TD><B>價 格</B></TD>
</TR>
<%
//利用while循環(huán)將數據表中的記錄列出
while (rs.next())
{
%>
<TR bgcolor=LightGoldenrodYellow>
<TD><B><%= rs.getString("product_name") %></B></TD>
<TD><B><%= rs.getString("price") %></B></TD>
</TR>
<%
}
rs.close(); //關閉記錄集
stmt.close(); //關閉Statement對象
%>
</TABLE>
</CENTER>
<a href="DBBean2.jsp">DBBean2.jsp</a>
</BODY>
</HTML>
功能:設定整個JSP網頁的屬性和相關功能。
語法:<%@
page指令元素的屬性
language="language"
import="importList"
contentType="ctinfo"
session="true|false"
buffer="none|size
authflush="true|false":
isThreadSafe="true|false"
info="text"
errorPage="error_url"
isErrorPage="true|false"
pageEncoding="ctinfo"
isELIgnored="true|false"
If(usingExcel) {%>
<%@page contentType=”application/vnd.ms-excel”%>
我們可以使用scriptlet和常規(guī)的servlet方式——response.setContentType,如下面的片段所示:
<%String format=request.getParameter(“format”);
Response.setContentType(“application/vnd.ms-excel”);
include指令
功能:在JSP編譯時插入包含一個文件。包含的過程是靜態(tài)的,包含的文件可以是JSP、HTML、文本或是Java程序。
語法:<%@
include指令是對文件的靜態(tài)包含,所以如果兩個文件中均設置了page指令的contentType屬性將會出錯。
taglib指令
功能:使用標簽庫定義新的自定義標簽,在JSP頁面中啟用定制行為。
語法:<%@
標簽元素:<jsp:directive.taglib
uri="tagLibraryURI"
prefix="tagPrefix"
一、include動作指令
<jsp:include>標簽表示包含一個靜態(tài)的或者動態(tài)的文件。
語法:
注:
1、flush="true" 必須使用flush為true,它默認值是false。
2、<jsp:param>子句能讓你傳遞一個或多個參數給動態(tài)文件,也可在一個頁面中使用多個<jsp:param>來傳遞多個參數給動態(tài)文件。
二、forward動作指令
<jsp:forward>標簽從一個JSP文件向另一個文件傳遞包含用戶請求的request對象。
語法:
三、useBean動作指令
<jsp:useBean>標簽表示用來在JSP頁面中創(chuàng)建一個BEAN實例并指定它的名字以及作用范圍。
語法:
<jsp:useBean id="name" scope="page | request | session | application" typeSpec />
其中typeSpec有以下幾種可能的情況:
class="包名.類名" | class="包名.類名" type="typeName" | beanName="包名.類名" type="typeName"
在JSP中使用bean,class屬性必須使用完全限定類名——包括包名的類名。不管你是否使用<%@ page import ...%>輸入包,都要滿足這個要求。
<jsp:useBean id=”book” class=”core.Book”/> 等價于 <%core.Book book=new core.Book();%>
僅當找不到相同id和scope的bean時,jsp:useBean元素才會實例化新的bean。如果存在相同id和scope的bean,則只是將已有的bean綁定到相關的變量(由id指定)。
我們可以不使用
轉而使用
使用第二種形式的意義在于,jsp:useBean的起始標簽和結束標簽之間的語句只是在創(chuàng)建新的bean時執(zhí)行,如果使用已有的bean,則不執(zhí)行。
四、getProperty動作指令
<jsp:getProperty>標簽表示獲取BEAN的屬性的值并將之轉化為一個字符串,然后將其插入到輸出的頁面中。
語法:
<jsp:getProperty name="bean的名稱" property="屬性名稱" />
注:
1、在使用<jsp:getProperty>之前,必須用<jsp:useBean>來創(chuàng)建它。
2、不能使用<jsp:getProperty>來檢索一個已經被索引了的屬性。
3、能夠和JavaBeans組件一起使用<jsp:getProperty>,但是不能與Enterprise Java Bean一起使用。
五、setProperty動作指令
<jsp:setProperty>標簽表示用來設置Bean中的屬性值。
四種語法格式:
<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中的屬性來接收客戶輸入的數據,系統(tǒng)會根據名稱來自動匹配。
第二種語法格式則指設置其中匹配的一個bean的屬性。
第三種語法格式根據制定的request對象中的參數與屬性匹配。
第四種語法格式用來給bean的屬性賦值,屬性值的數據類型要與屬性的數據類型一致,否則會出錯。字符串轉換為其他數據類型的函數分別為:
轉換為boolean
轉換為byte
轉換為char
轉換為double
轉換為float
轉換為int
轉換為long
注:使用 jsp:setProperty 來為一個Bean的屬性賦值;可以使用兩種方式來實現。
在同一個setProperty動作指令中不能同時存在param和value參數。
六、plugin動作指令
這個動作指令用來在JSP中加載Java applet小程序。用<applet></applet>也可以是客戶端下載并運行Java applet小程序,但有的瀏覽器不支持,如果Java applet小程序使用了這樣的類,將無法執(zhí)行。用plugin動作指令可以較好的解決這個問題。
語法:
<jsp:plugin
</jsp:plugin>
注:
code參數是指小程序經過編譯后的字節(jié)碼文件,擴展名為.class。
codebase參數值出這個字解碼文件所在的位置,可以是相對路徑也可以是絕對路徑,但在這個參數中不需要文件名,只需要目錄路徑就可以了,如果自己嗎文件與調用的jsp文件在同一目錄下,則此參數可以省略。
Servlet是一種可以在Servlet容器中運行的組件,那么理所當然就應該有一個從創(chuàng)建到銷毀的過程,這個過程我們可以稱之為Servlet生命周期。Servlet的生命周期可以分為加載、實例化、初始化、處理客戶請求和卸載五個階段,體現在方法上主要是init()、service()和destroy()三個方法。生命周期的具體說明如下:
加載并初始化Servlet
在前面已經說過Servlet容器完成加載和實例化Servlet的工作,該工作既可以在容器啟動時完成,也可以在容器收到請求時完成,或者是兩者之間的某個時間啟動。之后需要初始化Servlet,即讀取配置信息、讀取初始化參數等,這些基本上在整個生命周期中只需要執(zhí)行一次。關于init()方法已經在積累GenericServlet中提供缺省實現,如果不需特殊處理則沒有必要再進行定義,否則要重寫。
處理客戶端請求
當容器接收到客戶端請求時,Servlet引擎將創(chuàng)建一個ServletRequest請求對象和一個ServletResponse響應對象,然后把這兩個對象作為參數傳遞給對應Servlet對象的service方法。
該方法是一個重點實現的方法,ServletRequest對象可以獲得客戶端發(fā)出請求的相關信息,如請求參數等,ServletResponse對象可以使得Servlet建立響應頭和狀態(tài)代碼,并可以寫入響應內容返回給客戶端。
在此說明一點,當Servlet中有doGet()或者doPost()方法時,那么service方法就可以省略,默認為調用這兩個方法。
卸載Servlet
Servlet的卸載是由容器本身定義和實現,在卸載Servlet之前需要調用destroy()方法,以讓Servlet自行釋放占用的系統(tǒng)資源。雖然Java虛擬機提供了垃圾自動回收處理機制,但是有一部分資源卻是該機制不能處理或延遲很久才能處理的,如關閉文件,釋放數據庫連接等。
Servlet生命周期的五個階段是相互關聯的,后面幾個階段建立在前面階段的基礎之上,在使用Servlet的時候可以根據自己的需要靈活處理。