java web学习笔记-jsp篇
轉(zhuǎn)載自:http://www.cnblogs.com/happyfans/archive/2015/03/17/4343571.html
1.java web簡介
1.1靜態(tài)頁面與動態(tài)頁面
| ? | 表現(xiàn)形式 | 所需技術(shù) |
| 靜態(tài)網(wǎng)頁 | 網(wǎng)頁內(nèi)容固定,不會更新 | html,css |
| 動態(tài)網(wǎng)頁 | 網(wǎng)頁內(nèi)容由程序動態(tài)顯示,自動更新 | html,css,DB,java/c#/php,javascript,xml,主流的動態(tài)網(wǎng)頁腳本(jsp,asp.net,php) |
?
1.2搭建java web開發(fā)環(huán)境
jdk1.7+tomcat7.0+MyEclipse10。關(guān)于MyEclipse的安裝和配置請參見http://blog.sina.com.cn/s/blog_907043b301016jtp.html。Tomcat服務器是Apache Jakarta的開源項目,是Jsp/Servlet容器。安裝Tomcat只需要解壓zip包到指定目錄即可。新建一個環(huán)境變量CATALINA_HOME,變量的值是Tomcat的根目錄D:\Program Files (x86)\apache-tomcat-7.0.57。全部的環(huán)境變量如下:
| 變量名 | 變量值 |
| JAVA_HOME | D:\Program Files (x86)\Java\jdk1.7.0_40 |
| Path | C:\Program Files\Microsoft SQL Server\100\DTS\Binn\;%JAVA_HOME%\bin;D:\Program Files\Sublime Text 3;D:\Program Files\MySQL\MySQL Utilities 1.3.6\ |
| classpath | .;%JAVA_HOME%\lib\rt.jar;%JAVA_HOME%\lib\tools.jar; |
| CATALINA_HOME | D:\Program Files (x86)\apache-tomcat-7.0.57 |
之后我們測試一下Tomcat的首頁:
進入Tomcat服務器根目錄下面的bin目錄,以管理員方式運行startup.bat,如果運行結(jié)果如下就表示Tomcat服務器啟動成功。
注意:不要關(guān)閉這個窗口(關(guān)閉窗口就意味著關(guān)閉了Tomcat服務器,將其最小化)。
在瀏覽器地址欄輸入http://localhost:8080/回車得到如下頁面:
1.3Tomcat目錄結(jié)構(gòu)
1.4手工編寫第一個web應用程序
在項目文件夾中創(chuàng)建一個index.jsp:
1 <!DOCTYPE html>2 <html lang="en">3 <head>4 <meta charset="UTF-8">5 <title>手工編寫的第一個java web項目</title>6 </head>7 <body>8 <h1>這是手工編寫的第一個java web項目——jsp</h1>9 <hr /> 10 </body> 11 </html>在項目目錄中創(chuàng)建一個WEB-INF目錄拷貝/webapps/examples/WEB-INFO/web.xm到自己項目的/myJspProject/WEB-INFO中,在/myJspProject/WEB-INFO中創(chuàng)建兩個文件夾:classes和lib。最后的項目目錄應該是這樣:
測試:瀏覽器輸入:http://localhost:8080/myJspProject/index.jsp回車,運行結(jié)果如下:
?解決方法:更改瀏覽器編碼為指定編碼:
1.5WEB-INF目錄詳解
該目錄是java web應用的安全目錄。所謂安全目錄就是客戶端無法訪問只有服務端可以訪問的目錄。其中web.xml是項目部署文件,classes目錄:存放*.class文件,lib目錄存放需要的jar包。例如:我們在WEB-INF中創(chuàng)建一個test.html,下面我們通過瀏覽器訪問:
web.xml配置文件可以配置歡迎頁面默認的歡迎頁面是項目下面的index.jsp,加入我們需要將項目下的haha.jsp,在/WEB-INF/web.xml的web-app標記中添加以下代碼:
1 <welcome-file-list> 2 <welcome-file>/haha.jsp</welcome-file> 3</welcome-file-list>運行結(jié)果:
1.6實用Eclipse編寫第一個web應用程序
注意:如果要使用Eclipse編寫java web應用應該使用Eclipse的J2EE版本。并在Eclipse中配置Tomcat服務器Window-Preference-Server-Runtime Environment-Add,然后在WebContent目錄下新建jsp文件,按下Ctrl+F11(或者在項目中右鍵-Run On Server)就可以使用內(nèi)置瀏覽器訪問建立的網(wǎng)站。
1.7用MyEclipse編寫第一個web應用程序
在新建項目之前首先在MyEclipse中配置jre和tomcat。步驟Window-Preference-Java-Install JREs-Add;Window-MyEclipse-Servers-Tomcat(注意設置tomcat的jre并將服務器設置為Enabled)。
接下來在MyEclipse中啟動Tomcat服務器:
測試首頁http://localhost:8080/證明Tomcat正常啟動,我們就可以在MyEclipse中啟動和發(fā)布Web應用程序了。
New一個WebProject會生成以下的目錄結(jié)構(gòu)(默認在WebRoot目錄下有一個index.jsp)。
發(fā)布該WebApp。
1.8理解項目的虛擬路徑
該虛擬路徑是可以修改的項目上右鍵屬性-MyEclipse-Web。
?
重新部署,瀏覽器需要使用使用http://localhost:8080/hello/index.jsp訪問了。
1.7修改Tomcat默認端口
修改conf目錄下的server.xml的以下標記:
<Connector connectionTimeout="20000" port="8888" protocol="HTTP/1.1" redirectPort="8443"/>2.jsp語法基礎
2.1jsp簡介
jsp的全名是Java Server Page,是一個簡化的Servlet設計,它實現(xiàn)了在java當中使用html標記。jsp是一種動態(tài)網(wǎng)頁技術(shù),符合J2EE標準。jsp和Servlet一樣也是在服務器端執(zhí)行的。
2.2常見動態(tài)網(wǎng)站開發(fā)技術(shù)對比
| 平臺 | 特點 |
| jsp | 跨平臺,安全性高,適合開發(fā)大型的、企業(yè)級的Web應用、分布式應用(Hadoop)。例如:12306、10086.cn、網(wǎng)上銀行 |
| asp.net | 簡單易學,安全性和跨平臺性差 |
| php | 簡單、高效、成本低、開發(fā)周期短,適合中小型企業(yè)的Web應用開發(fā)(LAMP) |
?
2.3jsp頁面元素簡介以及page指令
page指令語法:
<%@ page 屬性1="屬性值" 屬性2="屬性值1,屬性值2" 屬性n="屬性值n"%>| 屬性 | 描述 | 默認值 |
| language | jsp頁面所使用的腳本語言 | java |
| import | 引用腳本語言中所要使用的類文件 | 無 |
| contentType | 指定jsp頁面的編碼 | text/html,ISO-8859-1 |
新建一個java web工程默認的jsp頁面開頭有一個page指令:
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>默認的編碼是ISO-8859-1,不支持中文,這里建議使用另一個屬性contentType。將第一行改為如下:
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>這樣就支持中文了。
page指令的全部屬性如下:
1 <%@page2 [language="Java"]3 [extends="package.class"] // 指定JSP頁面編譯所產(chǎn)生的Java類所繼承的父類,或所實現(xiàn)的接口。4 [import="package.class│package.*,…"]5 [session="true│false"]6 [buffer="none│8kb│size kb"]7 [autoFlush="true│false"]8 [isThreadSafe="true│false"]9 [info="text"] 10 [errorPage="relativeURL"] // 指定錯誤處理頁面。因為JSP內(nèi)建了異常機制支持,所以JSP可以不處理異常。 11 [contentType="mimeType[;charset=characterSet]"│"text/html;charSet=ISO8859-1"] 12 [isErrorPage="true│false"] // 設置本JSP頁面是否為錯誤處理程序。 13 %>注意:除page指令中的import屬性之外,其他屬性均只能設置一次。
2.4jsp注釋
分為3種:html注釋,jsp注釋,jsp腳本注釋。語法:
1 <!-- html注釋 --> 2 <%-- jsp注釋 --%> 3 <% 4 /*這里是jsp腳本注釋 有兩種*/ 5 6 //單行注釋 7 8 /*多行注釋*/ 9 %>例如:
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <%3 String path = request.getContextPath();4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>6 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">8 <html>9 <head> 10 <base href="<%=basePath%>"> 11 12 <title>My JSP 'index.jsp' starting page</title> 13 <meta http-equiv="pragma" content="no-cache"> 14 <meta http-equiv="cache-control" content="no-cache"> 15 <meta http-equiv="expires" content="0"> 16 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 17 <meta http-equiv="description" content="This is my page"> 18 <!-- 19 <link rel="stylesheet" type="text/css" href="styles.css"> 20 --> 21 </head> 22 23 <body> 24 <h1>歡迎你</h1> 25 <!-- 這是html注釋,客戶端可可見 --> 26 <%-- 這是jsp注釋,客戶端不可見 --%> 27 <% 28 /*這里是jsp腳本注釋 29 有兩種*/ 30 //單行注釋 31 /*多行注釋*/ 32 %> 33 </body> 34 </html>將項目部署到Tomcat,客戶端用瀏覽器查看源代碼:
2.5jsp腳本
在jsp頁面中執(zhí)行的java代碼。語法:
<% java代碼 %> 1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <%3 String path = request.getContextPath();4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>6 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">8 <html>9 <head> 10 <base href="<%=basePath%>"> 11 12 <title>My JSP 'index.jsp' starting page</title> 13 <meta http-equiv="pragma" content="no-cache"> 14 <meta http-equiv="cache-control" content="no-cache"> 15 <meta http-equiv="expires" content="0"> 16 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 17 <meta http-equiv="description" content="This is my page"> 18 <!-- 19 <link rel="stylesheet" type="text/css" href="styles.css"> 20 --> 21 </head> 22 23 <body> 24 <h1>歡迎你</h1> 25 <hr> 26 <% 27 out.println("通過jsp內(nèi)置對象out對象打印輸出"); 28 %> 29 </body> 30 </html>2.6jsp聲明
jsp頁面中定義變量或者方法。語法:
<%! java代碼 %>例如:
1 <%! 2 String s = "張三"; //聲明一個String類型的變量 3 int add(int x,int y){ //聲明一個返回值為int類型的方法 4 return x+y; 5 } 6 %>2.7jsp表達式
jsp頁面中執(zhí)行的表達式。語法(注意=緊挨著百分號,表達式末尾沒有分號):
<%=表達式 %> 1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <%3 String path = request.getContextPath();4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>6 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">8 <html>9 <head> 10 <base href="<%=basePath%>"> 11 12 <title>My JSP 'index.jsp' starting page</title> 13 <meta http-equiv="pragma" content="no-cache"> 14 <meta http-equiv="cache-control" content="no-cache"> 15 <meta http-equiv="expires" content="0"> 16 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 17 <meta http-equiv="description" content="This is my page"> 18 <!-- 19 <link rel="stylesheet" type="text/css" href="styles.css"> 20 --> 21 </head> 22 23 <body> 24 <h1>歡迎你</h1> 25 <hr> 26 <!-- 這是html注釋,客戶端可可見 --> 27 <%! 28 String s = "張三"; //聲明一個String類型的變量 29 int add(int x,int y){ //聲明一個返回值為int類型的方法 30 return x+y; 31 } 32 %> 33 你好:<%=s %><br> 34 令x=10,y=5,則x+y = <%=add(10, 5) %> 35 </body> 36 </html>運行結(jié)果:
2.8jsp頁面生命周期
jspService()方法被調(diào)用來處理客戶端的請求。對每一個請求,JSP引擎創(chuàng)建一個新的線程來處理該請求。如果有多個客戶端同時請求你該jsp文件,則jsp引擎會創(chuàng)建多個線程(每一個客戶端請求對應一個線程)。以多線程的方式執(zhí)行可以大大降低對系統(tǒng)的資源需求,提高系統(tǒng)的并發(fā)量以及縮短服務器的響應時間——但是同時要注意多線程的同步問題。由于該Servlet常駐內(nèi)存,所以響應是非常快的。
當頁面沒有被訪問的時候work目錄下沒有相關(guān)的Servlet。如果頁面被訪問之后就會在work目錄的對應目錄生成響應的Servlet。如圖:
打開index_jsp.java會看到以下的初始化方法:
然后該Servlet常駐內(nèi)存,創(chuàng)建線程處理每一個客戶端的請求。由每一個線程調(diào)用_jspService()方法來處理請求。
如果jsp頁面內(nèi)容發(fā)生了改變,jsp引擎就需要重新編譯jsp頁面。我們修改index.jsp,用瀏覽器重新訪問,則:
2.9階段項目(九九乘法表)
1 <%@page import="java.io.IOException"%>2 <%@ page language="java" import="java.util.*"3 contentType="text/html; charset=utf-8"%>4 <%5 String path = request.getContextPath();6 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";7 %>8 9 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 10 <html> 11 <head> 12 <base href="<%=basePath%>"> 13 14 <title>My JSP 'multiplicationTable.jsp' starting page</title> 15 16 <meta http-equiv="pragma" content="no-cache"> 17 <meta http-equiv="cache-control" content="no-cache"> 18 <meta http-equiv="expires" content="0"> 19 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 20 <meta http-equiv="description" content="This is my page"> 21 22 23 </head> 24 25 <body> 26 <h1>九九乘法表</h1> 27 <h2>表達式的方式打印乘法表</h2> 28 <%! 29 //聲明表達式 30 String printMultiTable(){ 31 StringBuilder s = new StringBuilder(); 32 for(int i=1;i<=9;i++){ 33 for(int j=1;j<=i;j++){ 34 s.append(i+" * "+j+" = "+i*j+"\t"); 35 } 36 s.append("<br />");//追加換行標記,注意不能使用\n 37 } 38 return s.toString(); 39 } 40 %> 41 <%=printMultiTable() //調(diào)用表達式 42 %> 43 44 <h2>使用腳本的方式打印九九乘法表</h2> 45 <%! 46 //jsp小腳本 47 void printMultiTable2(JspWriter out) throws IOException{ 48 StringBuilder s = new StringBuilder(); 49 for(int i=1;i<=9;i++){ 50 for(int j =1;j<=i;j++){ 51 s.append(i+" * "+j+" = "+i*j+"\t"); 52 } 53 s.append("<br />"); 54 } 55 out.println(s.toString()); 56 } 57 %> 58 59 <% 60 //調(diào)用腳本 61 printMultiTable2(out); 62 %> 63 </body> 64 </html>運行結(jié)果:
3.jsp內(nèi)置對象
3.1jsp內(nèi)置對象簡介
JSP內(nèi)置對象是Web容器創(chuàng)建的一組對象,不需要使用new關(guān)鍵字,JSP規(guī)范將它們完成了默認初始化(由JSP頁面對應Servlet的_jspService()方法來創(chuàng)建這些實例)。例如打印九九乘法表的jsp小腳本中使用的out對象就是jsp內(nèi)置對象。
1 <%!2 //jsp小腳本3 void printMultiTable2(JspWriter out) throws IOException{4 StringBuilder s = new StringBuilder();5 for(int i=1;i<=9;i++){6 for(int j =1;j<=i;j++){7 s.append(i+" * "+j+" = "+i*j+"\t");8 }9 s.append("<br />"); 10 } 11 out.println(s.toString());//這里的out就是jsp內(nèi)置對象 12 } 13 %>JSP一共有9個內(nèi)置對象,其中常用的內(nèi)置對象有5個,如圖所示:
3.3out對象
緩沖區(qū)(Buffer)就是內(nèi)存中用來保存臨時數(shù)據(jù)的一塊區(qū)域。關(guān)于緩沖區(qū)有一個很形象的例子:比如我們煮好了飯放在鍋里,如果我們一粒一粒地來吃米飯就不知道吃到猴年馬月,拿來一個碗來一碗一碗吃,豈不快哉!這里的碗就充當了緩沖區(qū)的概念。其實IO的本質(zhì)就是直接操作字節(jié),但是效率太慢所以引入了緩沖區(qū)。
out對象是JspWriter類的一個實例——是向客戶端輸出內(nèi)容的常用對象,該對象的常用方法:
1 void println(String message); // 向客戶端打印字符串 2 void clear(); // 清除緩沖區(qū)內(nèi)容,如果在flush之后調(diào)用會拋出異常 3 void clearBuffer(); // 清除緩沖區(qū)內(nèi)容,如果在flush之后調(diào)用不會拋出異常 4 void flush(); // 將緩沖區(qū)的內(nèi)容輸出到客戶端 5 int getBufferSize(); // 返回緩沖區(qū)的大小(字節(jié)),默認是0 6 int getRemaining(); // 返回緩沖區(qū)可用容量 7 boolean isAutoFlush(); // 返回緩沖區(qū)滿的時候是自動清空還是拋出異常 8 void close(); // 關(guān)閉輸出流下面是一個簡單的示例:
1 <h1>JSP的out內(nèi)置對象</h1>2 <%3 //jsp腳本4 out.println("<h2>靜夜思</h2>");5 out.println("李白<br /><br />");6 out.println("窗前明月光,<br />");7 out.println("疑是地上霜。<br />");8 out.println("舉頭望明月,<br />");9 out.println("低頭思故鄉(xiāng)。<hr />"); 10 %> 11 <!-- JSP表達式 --> 12 緩沖區(qū)大小:<%=out.getBufferSize() %>字節(jié)。<br /> 13 剩余緩沖區(qū)(可用緩沖區(qū)):<%=out.getRemaining() %>字節(jié)。<br /> 14 是否自動清空緩沖區(qū):<%=out.isAutoFlush() %><br />運行結(jié)果:
1 <h1>JSP的out內(nèi)置對象</h1>2 <%3 //jsp腳本4 out.println("<h2>靜夜思</h2>");5 out.println("李白<br /><br />");6 out.println("窗前明月光,<br />");7 out.flush();//將緩沖區(qū)中的內(nèi)容輸出到客戶端
8 out.println("疑是地上霜。<br />");9 out.println("舉頭望明月,<br />"); 10 out.println("低頭思故鄉(xiāng)。<hr />"); 11 %> 12 <!-- JSP表達式 --> 13 緩沖區(qū)大小:<%=out.getBufferSize() %>字節(jié)。<br /> 14 剩余緩沖區(qū)(可用緩沖區(qū)):<%=out.getRemaining() %>字節(jié)。<br /> 15 是否自動清空緩沖區(qū):<%=out.isAutoFlush() %><br />
如果在第7行強制刷新緩沖區(qū),則輸出的頁面不會有任何變化,僅僅是可用緩沖區(qū)的數(shù)量變多了而已【因為flush清空了緩沖區(qū)】
1 <%2 //jsp腳本3 out.println("<h2>靜夜思</h2>");4 out.println("李白<br /><br />");5 out.println("窗前明月光,<br />");6 7 out.flush();//將緩沖區(qū)中的內(nèi)容輸出到客戶端8 out.clear();//在flush之后調(diào)用clear,將會拋出異常9 10 out.println("疑是地上霜。<br />"); 11 out.println("舉頭望明月,<br />"); 12 out.println("低頭思故鄉(xiāng)。<hr />"); 13 %>運行結(jié)果:
1 <%2 //jsp腳本3 out.println("<h2>靜夜思</h2>");4 out.println("李白<br /><br />");5 out.println("窗前明月光,<br />");6 7 out.flush();//將緩沖區(qū)中的內(nèi)容輸出到客戶端8 out.clearBuffer();//在flush之后調(diào)用clearBuffer不會拋出異常9 10 out.println("疑是地上霜。<br />"); 11 out.println("舉頭望明月,<br />"); 12 out.println("低頭思故鄉(xiāng)。<hr />"); 13 %>運行結(jié)果:
3.4post和get提交方式的區(qū)別
<form name="regForm" action="處理腳本" method="提交方式[post|get]"></form>- get:以明文的方式通過URL提交數(shù)據(jù),提交的數(shù)據(jù)最大不超過2K。適合提交數(shù)據(jù)量小,安全性不高的數(shù)據(jù)【例如:搜索和查詢】
- post:將用戶提交的數(shù)據(jù)封裝在URL HEADER內(nèi)。適合提交數(shù)據(jù)量大,安全性高的數(shù)據(jù)【例如:注冊、修改、上傳】 下面以用戶登錄的例子比較兩者的區(qū)別:
- login.jsp頁面
處理登錄的動作腳本dologin.jsp僅僅是顯示一句話"登錄成功"。
運行結(jié)果:
將用戶登錄表單的get方式改為post。
3.5request對象
客戶端的請求被封裝在request對象中,通過它才能了解到客戶端的需求,然后做出響應。它是HttpServletRequest對象的實例。request對象具有請求域,即:完成客戶端的請求之前,該對象一直有效。常用方法如下:
/* 兩個比較常用的方法 */1 String getParameter(String name); // 返回name指定參數(shù)的參數(shù)值2 String[] getParameterValues(String name); // 返回包含name的所有值的數(shù)組
3 void setAttribute(String,Object); // 存儲此請求中的屬性4 String getContentType(); // 返回請求體的MIME類型5 Stirng getProtocol(); // 返回請求所用的協(xié)議和版本號6 String getServerName(); // 返回接受請求的服務器的主機名7 int getServerPort(); // 返回服務器接受此請求所用的端口號8 String getCharacterEncoding(); // 返回字符編碼方式【只能解決post方式的亂碼問題】9 void setCharacterEncoding(); // 設置請求的字符編碼方式 10 int getContentLength(); // 返回請求體的長度(字節(jié)) 11 String getRemoteAddr(); // 返回發(fā)送此請求的客戶端IP 12 String getRealPath(String path); // 返回虛擬路徑的真實路徑 13 String request.getContextPath(); // 返回上下文路徑
以用戶注冊頁面為例(用戶在注冊頁reg.jsp完善信息后提交給request.jsp來處理):
用戶注冊頁reg.jsp
1 請輸入相關(guān)信息完成注冊<br />2 <form action="request.jsp" name="regForm" method="post">3 用戶名:<input type="text" name = "username" /><br />4 密碼:<input type="password" name = "password" /><br />5 愛好:6 <input type="checkbox" name = "favorite" value="read"/>讀書7 <input type="checkbox" name = "favorite" value="music"/>音樂8 <input type="checkbox" name = "favorite" value="movie"/>電影9 <input type="checkbox" name = "favorite" value="internet"/>上網(wǎng)<br /> 10 <input type="submit" value="提交" /> 11 </form>處理用戶注冊頁的request.jsp
1 <h1>request內(nèi)置對象</h1><br />2 3 用戶名:<%=request.getParameter("username") %><br />4 密碼:<%=request.getParameter("password") %><hr />5 愛好:<br />6 <%7 String[]favorites = request.getParameterValues("favorite");8 for(String str:favorites){9 out.print(str+" "); 10 } 11 %>運行結(jié)果:
但是以上頁面存在一個問題:假如我們在用戶名中輸入中文:
這時只要再request.jsp中設置字符集和reg.jsp一樣即可:
1 <h1>request內(nèi)置對象</h1><br />2 <!-- 設置字符集,防止出現(xiàn)中文亂碼 -->3 <% request.setCharacterEncoding("utf-8"); %>4 用戶名:<%=request.getParameter("username") %><br />5 密碼:<%=request.getParameter("password") %><hr />6 愛好:<br />7 <%8 String[]favorites = request.getParameterValues("favorite");9 for(String str:favorites){ 10 out.print(str+" "); 11 } 12 %>
除了可以使用表單的方式傳遞數(shù)據(jù)給request對象,也可以使用URL傳參的方式傳遞數(shù)據(jù)給request對象:
reg.jsp
<a href="request.jsp?username=root&password=toor&favorite=read&favorite=internet">測試URL傳參</a>request.jsp(不變)
1 <h1>request內(nèi)置對象</h1><br />2 <!-- 設置字符集,防止出現(xiàn)中文亂碼 -->3 <% request.setCharacterEncoding("utf-8"); %>4 用戶名:<%=request.getParameter("username") %><br />5 密碼:<%=request.getParameter("password") %><hr />6 愛好:<br />7 <%8 String[]favorites;9 if((favorites=request.getParameterValues("favorite"))!=null){ 10 for(String str:favorites){ 11 out.print(str+" "); 12 } 13 } 14 %>運行結(jié)果:
如果我們在URL傳參中傳入了中文數(shù)據(jù),同樣會出現(xiàn)亂碼問題:
<a href="request.jsp?username=你好&password=toor&favorite=read&favorite=internet">測試URL傳參</a>此時通過request.setCharacterEncoding()方法就無法解決亂碼問題了【一個良好的解決方案是修改tomcat的配置文件server.xml】
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="utf-8"/>向request對象中添加鍵值對:
reg.jsp:
1 請輸入相關(guān)信息完成注冊<br />2 <form action="request.jsp" name="regForm" method="post">3 用戶名:<input type="text" name = "username" /><br />4 密碼:<input type="password" name = "password" /><br />5 愛好:6 <input type="checkbox" name = "favorite" value="read"/>讀書7 <input type="checkbox" name = "favorite" value="music"/>音樂8 <input type="checkbox" name = "favorite" value="movie"/>電影9 <input type="checkbox" name = "favorite" value="internet"/>上網(wǎng)<br /> 10 <input type="submit" value="提交" /> 11 </form>request.jsp
1 <h1>request內(nèi)置對象</h1><br />2 <!-- 設置字符集,防止出現(xiàn)中文亂碼 -->3 <% request.setCharacterEncoding("utf-8"); %>4 <%5 //在request對象中保存一個email屬性6 request.setAttribute("email","io@gmail.com");7 8 %>9 用戶名:<%=request.getParameter("username") %><br /> 10 密碼:<%=request.getParameter("password") %><hr /> 11 愛好:<br /> 12 <% 13 String[]favorites; 14 if((favorites=request.getParameterValues("favorite"))!=null){ 15 for(String str:favorites){ 16 out.print(str+" "); 17 } 18 } 19 %> 20 <br />郵箱:<%=request.getAttribute("email") %>運行結(jié)果:
1 <h1>request內(nèi)置對象</h1><br />2 <!-- 設置字符集,防止出現(xiàn)中文亂碼 -->3 <% request.setCharacterEncoding("utf-8"); %>4 <%5 //在request對象中保存一個email屬性6 request.setAttribute("email","io@gmail.com");7 8 %>9 用戶名:<%=request.getParameter("username") %><br /> 10 密碼:<%=request.getParameter("password") %><hr /> 11 愛好:<br /> 12 <% 13 String[]favorites; 14 if((favorites=request.getParameterValues("favorite"))!=null){ 15 for(String str:favorites){ 16 out.print(str+" "); 17 } 18 } 19 %> 20 <br />郵箱:<%=request.getAttribute("email") %> <hr /> 21 請求體的MIME類型:<%=request.getContentType() %><br /> 22 請求體的協(xié)議及版本號:<%=request.getProtocol() %><br /> 23 服務器主機名:<%=request.getServerName() %><br /> 24 服務器端口號:<%=request.getServerPort() %><br /> 25 請求的字符編碼:<%=request.getCharacterEncoding() %><br /> 26 請求的文件長度:<%=request.getContentLength() %>字節(jié)<br /> 27 請求的客戶端的IP:<%=request.getRemoteAddr() %><br /> 28 請求的真實路徑:<%=request.getRealPath("request.jsp") %><br /> 29 請求的上下文路徑:<%=request.getContextPath() %>運行結(jié)果:
3.6response對象
response對象包含了響應客戶請求的相關(guān)信息,但是在JSP中很少直接使用到它。它是HttpServletResponse類的實例。response對象具有頁面作用域——即:訪問一個頁面時,該頁面的response只對本次訪問有效,其他頁面的response對象對當前頁面無效。常用方法如下:
1 String getCharacterEncoding(); // 返回響應所用的編碼 2 void setContentType(); // 設置響應的MIME類型 3 PrintWriter getPrintWriter(); // 返回一個可以向客戶端輸出字符的對象【注意區(qū)別于out內(nèi)置對象】 4 sendRedirect(String location); // 重定向客戶端的請求response.jsp
1 <%@page import="java.io.PrintWriter"%>2 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>3 <%4 response.setContentType("text/html;charset=utf-8");//設置響應的MIME類型5 6 out.println("<h1>response內(nèi)置對象</h1><hr />");7 8 PrintWriter outer = response.getWriter();//獲得輸出流對象9 outer.println("我是response對象生成的outter對象,在頁面中總是在前面輸出"); 10 %>運行結(jié)果:
運行結(jié)果很是奇怪:明明out對象的輸出在代碼中位于前面。但是結(jié)果卻是PrintWriter的打印結(jié)果在前面,根本原因就是:PrintWriter的對象的輸出總是在最前面。如果我們需要讓標題先輸出,可以使用內(nèi)置對象out的flush()方法強制刷新緩沖,向頁面輸出——保證標題出現(xiàn)在最前面。
請求重定向——當用戶請求response.jsp的時候馬上跳轉(zhuǎn)到login.jsp
3.7請求重定向與請求轉(zhuǎn)發(fā)的區(qū)別
- 請求重定向:客戶端行為response.sendResponse(),從本質(zhì)上講相當于兩次請求,前一次的請求對象不會保存,瀏覽器的URL欄會改變。
- 請求轉(zhuǎn)發(fā):服務器行為request.getRequestDipatcher().forword(req,resp);是一次請求,轉(zhuǎn)發(fā)后請求對象會被保存,瀏覽器的URL不會改變。 例如還是用原來的例子:我們在reg.jsp中指定處理頁面的腳本是response.jsp而在response.jsp中我們重定向到request.jsp。觀察request.jsp的輸出:
如果我們在response.jsp中使用請求轉(zhuǎn)發(fā):
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%> 2 <% 3 //請求轉(zhuǎn)發(fā) 4 request.getRequestDispatcher("request.jsp").forward(request, response); 5 %>運行結(jié)果:
3.8session對象
Session客戶端與服務器的一次會話。Web中的Session表示用戶在瀏覽某個網(wǎng)站時,從進入網(wǎng)站到瀏覽器關(guān)閉所經(jīng)過的這段時間——也就是用戶瀏覽這個網(wǎng)站所花費的時間。在服務器的內(nèi)存中保存著不同用戶的Session。
session對象的常用方法:
1 long getCreationTime(); // 返回session的創(chuàng)建時間 2 String getId(); // 返回session創(chuàng)建時JSP引擎為它設定的唯一ID號 3 Object setAttribute(String name,Object value); // 使用指定名稱將對象綁定到此會話 4 Object getAttribute(String name); // 返回此會話中的指定名稱綁定在一起的對象,如果沒有對象綁定在該名稱下則返回null 5 String[] getValueNames(); // 返回一個包含此Session所有可用屬性的數(shù)組 6 int getMaxInactiveInterval(); // 返回兩次請求間隔多長時間此session被取消【單位:秒】sesseion_page1.jsp
1 <h1>session內(nèi)置對象</h1>2 <h2>session_page1.jsp</h2>3 <%4 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");5 String date = sdf.format(new Date(session.getCreationTime()));6 out.print("session的創(chuàng)建時間:" + date);7 session.setAttribute("username", "admin"); // 向session中設置屬性8 %>9 <br />Session的ID號:<%=session.getId() %><br /> 10 從session中獲取用戶名:<%=session.getAttribute("username") %> 11 12 <a href="session_page2.jsp" target="_blank">以新窗口的方式打開session_page2.jsp</a>session_page2.jsp
1 <h2>session_page2.jsp</h2> 2 <% 3 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 4 String date = sdf.format(new Date(session.getCreationTime())); 5 out.print("session的創(chuàng)建時間:" + date); 6 %> 7 <br />Session的ID號:<%=session.getId() %><br /> 8 從session中獲取用戶名:<%=session.getAttribute("username") %>運行結(jié)果:
可以獲取session中保存的屬性集合以及設置session的有效期:
1 <% 2 session.setMaxInactiveInterval(5);//設置session的有效期為5s3 4 session.setAttribute("username", "admin"); // 向session中設置屬性5 session.setAttribute("password", "123456");6 session.setAttribute("age", 16);7 %>8 9 <% 10 //獲取session中保存的屬性 11 String[]names=session.getValueNames(); 12 if(names!=null){ 13 for(String str:names){ 14 out.print(str+"\t"); 15 } 16 } 17 %>Session的生命周期:
- 創(chuàng)建:當客戶端第一次訪問某個jsp頁面或者Servlet的時候,服務器會為當前會話創(chuàng)建一個SessionId。每次客戶端向服務器發(fā)送請求的時候都會攜帶此SessionId,服務端會對此SessionId進行檢驗——判斷是否屬于同一次會話。
- 活動階段:某次會話中通過超鏈接打開新的頁面;只要當前頁面沒有全部關(guān)閉,打開新的瀏覽器窗口訪問同一項目資源也屬于同一會話。注意:原有的會話仍然存在,只不過再也沒有客戶端會攜帶此sessionId交給服務器檢驗。——創(chuàng)建一個新的會話并不意味著原有會話消失,除非超時。
- 銷毀。
Tomcat如何進入后臺管理系統(tǒng)?
修改/conf/tomcat-user.xml為以下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <tomcat-users> 3 <role rolename="admin-gui"/> 4 <role rolename="manager-gui"/> 5 <user username="admin" password="admin" roles="admin-gui,manager-gui"></user> 6 </tomcat-users>在瀏覽器中打開session_page1.jsp然后通過session_page1.jsp的超鏈接打開session_page2.jsp在后臺管理系統(tǒng)中查看:
?
如果我們在session創(chuàng)建之后調(diào)用session.invalidate()方法,例如:我們在session_page1.jsp中這樣寫:
1 <h1>session內(nèi)置對象</h1>2 <h2>session_page1.jsp</h2>3 <%4 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");5 String date = sdf.format(new Date(session.getCreationTime()));6 out.print("session的創(chuàng)建時間:" + date);7 10 session.setAttribute("username", "admin"); // 向session中設置屬性 11 session.setAttribute("password", "123456"); 12 session.setAttribute("age", 16); 13 %> 14 <br />Session的ID號:<%=session.getId() %><hr /> 15 session中保存的屬性有:<br /> 16 <% 17 //獲取session中保存的屬性 18 String[]names=session.getValueNames(); 19 if(names!=null){ 20 for(String str:names){ 21 out.print(str+"\t"); 22 } 23 } 24 session.invalidate();//銷毀session 25 %> 26 <a href = "session_page2.jsp" target = "_blank">點擊在新標簽頁中打開session_page2.jsp</a>運行結(jié)果(不斷刷新瀏覽器):
Session默認session超時是30min設置session對象的超時有兩種方式:
- session.setMaxInactiveInterval(5);單位是秒
- 在web.xml中配置(單位是分鐘):
- <session-config><session-timeout>30</session-timeout> </session-config>
? 3.9application對象
- application對象實現(xiàn)了用戶間數(shù)據(jù)的共享,可以存放全局變量。
- application對象開始于服務器的啟動,結(jié)束于服務器的關(guān)閉。
- 在用戶的前后連接或者不同用戶之間,可以對統(tǒng)一個application對象的屬性進行操作。
- 在任何地方對application對象屬性的操作將會影響到其他用戶對此的訪問。
- application對象是ServletContext類的實例。 該對象的常用方法如下:
1 <h1>application對象</h1>2 <%3 //在application中保存3個鍵值對4 application.setAttribute("city", "北京");5 application.setAttribute("zipcode", "10000");6 application.setAttribute("email", "io@gmail.com");7 %>8 所在城市:<%=application.getAttribute("city") %><hr>9 application中存放的屬性有:<br> 10 <% 11 Enumeration attrs = application.getAttributeNames(); 12 while(attrs.hasMoreElements()){ 13 out.print(attrs.nextElement()+"<br>"); 14 } 15 %> 16 <hr> 17 jsp(Servlet)引擎:<%=application.getServerInfo() %><br>
運行效果:
3.10page對象
page對象就是指向當前jsp頁面本身(就好像類中的this),是java.lang.Object類的實例,常用方法和Object類的方法一致。例如它的toString()方法:
1 <h1>page內(nèi)置對象</h1> 2 當前頁面的page對象的字符串描述:<br /> 3 <%=page.toString() %>運行結(jié)果:
我們打開tomcat的work目錄(編譯生成的Servlet目錄)看到它的包結(jié)構(gòu)是org.apache.jsp,在該目錄下有一系列的*_jsp.java和*_jsp.class文件。我們打開page_jsp.java發(fā)現(xiàn)類名就是page_jsp。
3.11pageContext對象
- 提供了對JSP頁面內(nèi)所有的對象及名字空間的訪問。
- 可以訪問到本頁所在的session,也可以取本頁面所在的application的某一屬性值
- 相當于頁面中所有功能的集大成者。
- pageContext對象的本類名也叫pageContext。 常用方法:
我們在session_page1.jsp中向session中設置了用戶名:
<%session.setAttribute("username", "admin"); %>現(xiàn)在我們在pageContext.jsp中取出session中存儲的用戶名(注意要先打開session_page1.jsp):
<h1>pageContext內(nèi)置對象</h1>用戶名:<%=pageContext.getSession().getAttribute("username") %>運行結(jié)果:
用pageContext實現(xiàn)頁面跳轉(zhuǎn):
<%pageContext.forward("reg.jsp");%>運行結(jié)果:
新建一個include.jsp(頁面用于向頁面輸出當前的日期):
1 <%@page import="java.text.SimpleDateFormat"%> 2 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%> 3 <% 4 out.print(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())); 5 %>下面我們在pageContext.jsp頁面中包含include.jsp:
1 <h1>pageContext內(nèi)置對象</h1> 2 用戶名:<%=pageContext.getSession().getAttribute("username") %><hr> 3 4 <!-- 包含其他頁面 --> 5 <%pageContext.include("include.jsp"); %>3.12config對象
該對象是一個在servlet初始化時,jsp引擎向它傳遞信息時使用的,此信息包含Servlet初始化時所用到的參數(shù)(鍵-值對)以及服務器的相關(guān)信息(通過傳遞一個ServletContext對象),常用方法:
1 ServletContext getServletContext(); // 返回服務器相關(guān)信息的ServletContext對象 2 String getInitParameter(String name);// 返回初始化參數(shù)的值 3 Enumeration getInitParameterNames(); // 返回Servlet初始化時所有需要參數(shù)的枚舉3.13exception對象
該對象是一個異常對象,如果一個頁面在運行過程中出現(xiàn)了異常就會產(chǎn)生這個對象。如果一個JSP頁面需要應用此對象,就必須把isErrorPage設為true——否則無法編譯。它實際上是java.lang.Throwable的對象,常用方法:
1 String getMessage(); // 返回異常的描述信息 2 String toString(); // 返回關(guān)于異常的簡短描述信息 3 void printStackTrace(); // 顯示異常及其棧軌跡 4 Throwable FillInStackTrace(); // 重寫異常的執(zhí)行棧軌跡首先建立一個會出現(xiàn)異常的頁面exception_text.jsp(并指定處理異常的頁面):
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8" errorPage="exception.jsp"%>2 <!-- 在errorPage中指定處理異常的頁面 -->3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">4 <html>5 <head>6 <title>這個頁面肯定會出現(xiàn)異常</title>7 </head>8 9 <body> 10 <h1>測試異常對象</h1><hr /> 11 <% 12 out.println(100/0);//肯定會拋出運行時異常【算術(shù)異常】 13 %> 14 </body> 15 </html>然后建立處理異常的頁面exception.jsp:
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8" isErrorPage="true"%> <!-- isErrorPage設為true表示這是一個異常處理頁面 --> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><title>My JSP 'exception.jsp' starting page</title></head><body><h1>Exception內(nèi)置對象</h1>異常消息是:<%=exception.getMessage() %><br>異常的字符串描述:<%=exception.toString() %></body> </html>運行結(jié)果:
3.14階段案例——實現(xiàn)用戶登錄
這個案例比較簡單:用戶名和密碼都是admin(沒有使用數(shù)據(jù)庫),如果用戶名和密碼相符,則頁面跳轉(zhuǎn)到login_success.jsp【服務器內(nèi)部轉(zhuǎn)發(fā)】,提示用戶登錄成功;如果用戶登錄失敗,則頁面跳轉(zhuǎn)到login_failure.jsp【請求重定向】,提示用戶登錄失敗。
整個項目的截圖:
項目地址:https://git.oschina.net/gaopengfei/JSPLogin.git
4.java beans
JavaBean是使用Java語言開發(fā)的一個可重用的組件,在JSP的開發(fā)中可以使用JavaBean減少重復的代碼,使整個JSP代碼的開發(fā)更加簡潔。JSP配置JavaBean使用有以下優(yōu)點:
?1. 將html和java大媽分離,為日后的維護提供了方便。
?2. 可以利用JavaBean的優(yōu)點將常用到的程序?qū)懗蒍avaBean組件,節(jié)省開發(fā)時間。
?
簡單JavaBean有以下幾個名詞:
VO:值對象,存放所有的傳遞數(shù)據(jù)的操作上
POJO:簡單java對象
TO:傳輸對象,必須實現(xiàn)Serializable接口
WEB開發(fā)的標準目錄結(jié)構(gòu)
?
實際上在WEB-INF中的lib和classes目錄就相當于一個默認的classpath(類執(zhí)行時所需要的一個重要的環(huán)境屬性)。當Tomcat啟動之后,WEB-INF/lib和WEB-INF/classes都會自動配置到classpath中。
4.1java bean簡介與設計原則
Javabeans就是符合某種特定規(guī)范的的Java類。它的好處有:
一個Javabean要滿足4個規(guī)范:
例如以下的學生類就是一個Javabean:
1 /**2 * 這是一個典型的JavaBean3 */4 5 // 1.這是一個共有的類6 public class Student {7 // 2.屬性私有8 private String name;9 private int age; 10 11 // 3.有共有的無參構(gòu)造 12 public Student() { 13 } 14 15 // 4.getter和setter 16 public String getName() { 17 return name; 18 } 19 20 public void setName(String name) { 21 this.name = name; 22 } 23 24 public int getAge() { 25 return age; 26 } 27 28 public void setAge(int age) { 29 this.age = age; 30 } 31 32 }JavaBean有2種應用方式:
4.2jsp動作元素【運行時】
?JSP動作元素(action elements),動作元素為請求處理階段提供信息。動作元素遵循XML元素的語法——有一個元素名的開始標簽,可以有屬性、可選的內(nèi)容、與開始標簽匹配的結(jié)束標簽。
4.3普通方式應用java bean
像使用普通java類一樣,創(chuàng)建javabean實例。在MyEclipse項目的src目錄下新建類Users:
1 package org.po;2 3 /**4 * 用戶類-符合Javabean的實際原則5 */6 public class Users {7 private String username;8 private String password;9 10 public Users() { 11 12 } 13 14 public String getUsername() { 15 return username; 16 } 17 18 public void setUsername(String username) { 19 this.username = username; 20 } 21 22 public String getPassword() { 23 return password; 24 } 25 26 public void setPassword(String password) { 27 this.password = password; 28 } 29 30 }下面我們在javabean_page1.jsp中使用以上的Javabean:
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <!-- 使用import指令導入Javabean -->3 <%@ page import="org.po.Users" %>4 5 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">6 <html>7 <head>8 <title>JavaBeans范例</title>9 </head> 10 11 <body> 12 <h1>使用普通方式創(chuàng)建Javabean的實例</h1> 13 <% 14 //使用普通方式創(chuàng)建JavaBean 15 Users user = new Users(); 16 user.setUsername("admin"); 17 user.setPassword("admin"); 18 %> 19 用戶名:<%=user.getUsername() %><br /> 20 密碼:<%=user.getPassword() %> 21 </body> 22 </html>運行結(jié)果:
4.4useBean動作元素
<jsp:useBean>用于在jsp頁面中實例化或者在指定范圍內(nèi)使用JavaBean。基本操作是首先使用id和作用域查找一個現(xiàn)有的對象,如果在指定的作用域中沒有找到具有指定id的對象,那么它會試圖使用其他屬性創(chuàng)建一個新實例。語法如下:
<jsp:useBean id="標示符" class="java類名" scope="作用域" /> 1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <!-- 這里不需要page指令來導入User類了 -->3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">4 <html>5 <head>6 <title>使用useBean動作指令來使用JavaBean</title>7 </head>8 9 <body> 10 <h1>使用<jsp:useBean>動作指令來使用JavaBean</h1> 11 <!-- useBean指令 --> 12 <jsp:useBean id="myUsers" class="org.po.Users" scope="page"></jsp:useBean> 13 用戶名:<%=myUsers.getUsername() %><br/> 14 密碼:<%=myUsers.getPassword() %> 15 </body> 16 </html>運行結(jié)果:
4.5setProperty
上一個jsp頁面中取得的用戶名和密碼都為null,原因就是我們使用僅僅是實例化了Users對象,并沒有為其成員變量執(zhí)行屬性。當然你也可以使用setXXX來給已經(jīng)實例化的JavaBean設置屬性,不過我更推薦使用setProperty指令。
<jsp:setProperty>的主要作用就是給已經(jīng)實例化的JavaBean的屬性賦值,一共有4種形式:
1 <jsp:setProperty name="JavaBean實例名" property="*" /> <!-- 和表單關(guān)聯(lián),全部屬性 --> 2 <jsp:setProperty name="JavaBean實例名" property="JavaBean屬性名" /> <!-- 和表單關(guān)聯(lián),指定屬性 --> 3 <jsp:setProperty name="JavaBean實例名" property="JavaBean屬性名" value = "BeanValue" /> <!-- 手工設置 --> 4 <jsp:setProperty name="JavaBean實例名" property="propertyName" param="request對象中的參數(shù)名"/> <!-- 和request參數(shù)關(guān)聯(lián),URL傳參 -->方式一:【表單內(nèi)容的自動全部匹配】
新建一個用戶登錄表單login.jsp:
1 <form action="dologin.jsp" method="post" name="loginForm"> 2 用戶名:<input type="text" name="username"/><br /> 3 密碼:<input type="password" name="password" /> 4 <input type="submit" value="提交" /> 5 </form>處理用戶登錄的頁面dologin.jsp
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <%3 String path = request.getContextPath();4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>6 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">8 <html>9 <head> 10 <base href="<%=basePath%>"> 11 <title>用戶登錄處理頁面</title> 12 </head> 13 14 <body> 15 16 <!-- 實例化javaBean對象 --> 17 <jsp:useBean id="myUsers" class="org.po.Users"></jsp:useBean> 18 19 <h1>setPerpority動作元素</h1><hr /> 20 21 <!-- 根據(jù)表單自動匹配所有的屬性并設置 --> 22 <jsp:setProperty property="*" name="myUsers"/> 23 用戶名:<%=myUsers.getUsername() %><br> 24 密碼:<%=myUsers.getPassword() %> 25 26 </body> 27 </html>運行結(jié)果:
這實際上以依靠表單中的name屬性來匹配javabean中的成員變量。例如:在用戶登錄表單中input標記的屬性有一個name="username",那么使用這種自動匹配的方式就會把這個username與javabean中的屬性挨個查找,如果找到了就為這個字段設定相應的值——換言之:表單中的name屬性要和要和javabean中的屬性對應相同。
方式二:部分匹配表單的屬性(dologin.jsp):
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <%3 String path = request.getContextPath();4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>6 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">8 <html>9 <head> 10 <base href="<%=basePath%>"> 11 <title>用戶登錄處理頁面</title> 12 </head> 13 14 <body> 15 16 <!-- 實例化javaBean對象 --> 17 <jsp:useBean id="myUsers" class="org.po.Users"></jsp:useBean> 18 19 <h1>setPerpority動作元素</h1><hr /> 20 21 <!-- 根據(jù)表單匹配部分屬性 --> 22 <jsp:setProperty property="username" name="myUsers"/> 23 用戶名:<%=myUsers.getUsername() %><br> 24 密碼:<%=myUsers.getPassword() %> 25 26 </body> 27 </html>運行結(jié)果:
僅僅匹配了用戶名屬性,由于密碼屬性沒有匹配,所以為null。這種方式也要注意表單的name屬性要和javabean的屬性相同。
方式三:手工給javabean的屬性賦值——與表單無關(guān)(dologin.jsp):
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <%3 String path = request.getContextPath();4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>6 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">8 <html>9 <head> 10 <base href="<%=basePath%>"> 11 <title>用戶登錄處理頁面</title> 12 </head> 13 14 <body> 15 16 <!-- 實例化javaBean對象 --> 17 <jsp:useBean id="myUsers" class="org.po.Users"></jsp:useBean> 18 19 <h1>setPerpority動作元素</h1><hr /> 20 21 <!-- 與表單無關(guān),通過手工給javabean的屬性賦值 --> 22 <jsp:setProperty property="username" name="myUsers" value="root"/> 23 <jsp:setProperty property="password" name="myUsers" value="123456"/> 24 用戶名:<%=myUsers.getUsername() %><br> 25 密碼:<%=myUsers.getPassword() %> 26 27 </body> 28 </html>
方式四(通過URL傳參的方式給javabean賦值):
login.jsp:
<a href="dologin.jsp?id=root&sn=123456">通過url傳參的方式給javabean的屬性賦值</a>dologin.jsp:
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <%3 String path = request.getContextPath();4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>6 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">8 <html>9 <head> 10 <base href="<%=basePath%>"> 11 <title>用戶登錄處理頁面</title> 12 </head> 13 14 <body> 15 16 <!-- 實例化javaBean對象 --> 17 <jsp:useBean id="myUsers" class="org.po.Users"></jsp:useBean> 18 19 <h1>setPerpority動作元素</h1><hr /> 20 21 <!-- 通過URL傳參的方式給javabean屬性賦值--> 22 <jsp:setProperty property="username" name="myUsers" param="id"/> 23 <jsp:setProperty property="password" name="myUsers" param="sn"/> 24 用戶名:<%=myUsers.getUsername() %><br> 25 密碼:<%=myUsers.getPassword() %> 26 27 </body> 28 </html>運行結(jié)果:
4.6getProperty
<jsp:getProperty>獲取指定JavaBean對象的屬性值【String類型】。語法:
<jsp:getProperty name="JavaBean實例名" property="屬性名" />前面的例子已經(jīng)通過URL傳遞參數(shù)的方式指定了javabean的屬性值,現(xiàn)在通過getProperty的方式獲得javabean的屬性值:
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <%3 String path = request.getContextPath();4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>6 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">8 <html>9 <head> 10 <base href="<%=basePath%>"> 11 <title>用戶登錄處理頁面</title> 12 </head> 13 14 <body> 15 16 <!-- 實例化javaBean對象 --> 17 <jsp:useBean id="myUsers" class="org.po.Users"></jsp:useBean> 18 19 <h1>setPerpority動作元素</h1><hr /> 20 21 <!-- 通過URL傳參的方式給javabean屬性賦值--> 22 <jsp:setProperty property="username" name="myUsers" param="id"/> 23 <jsp:setProperty property="password" name="myUsers" param="sn"/> 24 25 <!-- 通過getter獲得javabean的屬性值 --> 26 <%-- 27 用戶名:<%=myUsers.getUsername() %><br> 28 密碼:<%=myUsers.getPassword() %> 29 --%> 30 31 <!-- 通過getProperty獲得javabean的屬性值 --> 32 用戶名:<jsp:getProperty property="username" name="myUsers"/><br /> 33 密碼:<jsp:getProperty property="password" name="myUsers"/> 34 </body> 35 </html>運行結(jié)果:
4.7java bean的4個作用域范圍
使用useBean的scope屬性可以指定javabean的作用域。
1 page // 當前頁面有效,可以通過PageContext.getAttribute()獲得JavaBean對象。 2 request // 同一個請求有效,可通過HttpRequest.getAttibute()方法獲得JavaBean對象。 3 session // 同一個session有效,可通過HttpSession.getAttribute()方法獲得JavaBean對象。 4 application // 同一個application有效,可通過application.getAttribute()方法獲得JavaBean對象。下面是一個簡單的測試4個作用范圍的示例:
dolog.jsp以URL傳參的方式為javabean指定屬性值:
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">3 <html>4 <head>5 <title>用戶登錄處理頁面</title>6 </head>7 8 <body>9 10 <!-- 實例化javaBean對象,并制定作用域為application --> 11 <jsp:useBean id="myUsers" class="org.po.Users" scope="application"></jsp:useBean> 12 13 <h1>setPerpority動作元素</h1><hr /> 14 15 <!-- 通過URL傳參的方式給javabean的屬性賦值--> 16 <jsp:setProperty property="username" name="myUsers" param="id"/> 17 <jsp:setProperty property="password" name="myUsers" param="sn"/> 18 19 <a href="test_scope.jsp">測試javabean的4個作用域范圍</a> 20 21 </body> 22 </html>dologin.jsp中有一個跳轉(zhuǎn)鏈接test_scope.jsp用于跳轉(zhuǎn)頁面,下面是test_scope.jsp。
1 <%@page import="org.po.Users"%>2 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>3 4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">5 <html>6 <head>7 <title>檢驗useBean的4個作用域</title>8 </head>9 10 <body> 11 <h1>檢驗useBean的4個作用域</h1><hr> 12 13 <jsp:useBean id="myUsers" class="org.po.Users" scope="application"></jsp:useBean> 14 <!-- 通過getProperty獲取javabean屬性值 --> 15 <h2>用jsp動作元素獲取javabean的屬性值</h2> 16 用戶名:<jsp:getProperty property="username" name="myUsers"/><br /> 17 密碼:<jsp:getProperty property="password" name="myUsers"/><hr> 18 19 <!-- 通過內(nèi)置對象獲取javabean的屬性值 --> 20 <h2>通過內(nèi)置對象獲取javabean的屬性值</h2> 21 用戶名:<%=((Users)application.getAttribute("myUsers")).getUsername() %><br> 22 密碼:<%=((Users)application.getAttribute("myUsers")).getPassword() %> 23 </body> 24 </html>按照上面的例子分別將scope換成session、request和page得到如下如下結(jié)果:javabean的作用域范圍從大到小依次是:application、session、request、page。
4.8JavaBean的刪除
JavaBean雖然使用了<jsp:useBean>標簽進行創(chuàng)建,但是其操作仍然依靠的是4種屬性范圍。如果一個JavaBean不再使用的話,則可以使用對應的removeAttribute()方法進行刪除。
1 pageContext.removeAttribute(JavaBean名稱) // 刪除page范圍內(nèi)的JavaBean 2 request.removeAttribute(JavaBean名稱) // 刪除request范圍內(nèi)的JavaBean 3 session.removeAttribute(JavaBean名稱) // 刪除session范圍內(nèi)的JavaBean 4 application.removeAttribute(JavaBean名稱) // 刪除application范圍內(nèi)的JavaBean 1 package org.gpf;2 3 public class Count {4 5 private int count = 0;6 7 public Count() {8 System.out.println("======== 一個新的Count實例產(chǎn)生了 ========");9 } 10 11 public int getCount() { 12 return ++count; 13 } 14 15 } 1 <%@ page language="java" contentType="text/html; charset=utf-8"%> 2 <!-- 創(chuàng)建JavaBean,指定作用域為session --> 3 <jsp:useBean id="c" class="org.gpf.Count" scope="session"></jsp:useBean> 4 count = <jsp:getProperty property="count" name="c"/> 5 <% 6 session.removeAttribute("c"); // 刪除javaBean 7 %>我們本來設置的是session范圍內(nèi)的JavaBean,刷新頁面不應該有新的JavaBean產(chǎn)生,但是我們在最后使用了session.removeAttribute()方法將創(chuàng)建的JavaBean刪除了,因而每次請求都會產(chǎn)生新的JavaBean。
4.9model 1(JSP+JavaBean)簡介
Model 1模型出現(xiàn)以前,整個Web應用幾乎全部由JSP頁面組成,JSP頁面接收處理客戶端請求,對請求處理后直接響應。這樣做的一個弊端就是:在界面層(JSP頁面)中充斥著大量的業(yè)務邏輯代碼和數(shù)據(jù)訪問層的代碼,Web程序的可擴展性和可維護性非常差。
JavaBean的出現(xiàn)可以使得可以在JSP頁面中調(diào)用JavaBean封裝的數(shù)據(jù)或者業(yè)務邏輯代碼,大大提升了程序的可維護性。下面的這張圖簡單描述了Model 1.
模型一體現(xiàn)了一種Web應用的分層架構(gòu)。
4.9階段項目(使用Model 1完成用戶登錄)
首先建立一個用戶類Users(javabean):
1 package org.po;2 3 /**4 * 用戶類-javabean5 */6 public class Users {7 private String username;8 private String passwordString;9 10 public Users() { 11 } 12 13 public String getUsername() { 14 return username; 15 } 16 17 public void setUsername(String username) { 18 this.username = username; 19 } 20 21 public String getPasswordString() { 22 return passwordString; 23 } 24 25 public void setPasswordString(String passwordString) { 26 this.passwordString = passwordString; 27 } 28 29 }下面編寫一個用戶業(yè)務邏輯類:
1 package org.dao;2 3 import org.po.Users;4 5 /**6 * 用戶的業(yè)務邏輯類7 */8 public class UsersDAO {9 public boolean isUserLogin(Users users) { 10 return "admin".equals(users.getUsername()) 11 && "admin".equals(users.getPassword()); 12 } 13 }業(yè)務邏輯處理的頁面dologin.jsp:
1 <%@ page language="java" import="java.util.*"2 contentType="text/html; charset=utf-8"%>3 <!-- 引入實體類Users --> 4 <jsp:useBean id="loginUser" class="org.po.Users"></jsp:useBean>5 <!-- 引入業(yè)務邏輯類UsersDAO -->6 <jsp:useBean id="userDAO" class="org.dao.UsersDAO"></jsp:useBean>7 8 <!-- 為javaBean loginUser設置屬性,使用表單自動設置全部的值 -->9 <jsp:setProperty property="*" name="loginUser"/> 10 11 <!-- 調(diào)用業(yè)務邏輯代碼 --> 12 <% 13 request.setCharacterEncoding("utf-8");//防止中文亂碼 14 if(userDAO.isUserLogin(loginUser)){ 15 //如果用戶登錄成功則向session中設置用戶名和密碼 16 session.setAttribute("username", loginUser.getUsername()); 17 session.setAttribute("password", loginUser.getPassword()); 18 //請求轉(zhuǎn)發(fā) 19 request.getRequestDispatcher("login_success.jsp").forward(request, response); 20 }else{ 21 //重定向 22 response.sendRedirect("login_failure.jsp"); 23 } 24 %>項目地址:https://git.oschina.net/gaopengfei/loginDemoByModel1.git
該項目中主要的修改的dologin.jsp在該頁面中沒有使用request對象直接從表單中讀出數(shù)據(jù),而是從javabean中取出屬性,并且用戶合法性的判斷也放在了javabean中很好的體現(xiàn)了Web的分層思想(邏輯與頁面分離)。
5.jsp狀態(tài)管理
5.1http協(xié)議的無狀態(tài)性
http的無狀態(tài)性是指:當瀏覽器發(fā)送請求給服務器的時候,服務器響應客戶端的請求。但是當瀏覽器再次發(fā)送請求給服務器的時候,服務器并不知道它就是剛剛的那個瀏覽器。——服務器不會記住你。為了保存用戶的狀態(tài)有兩種機制:
5.2Cookie
Cookie是Web服務器保存在客戶端的一系列文本信息。
- Cookie的典型應用一:判斷注冊用戶是否已經(jīng)登錄網(wǎng)站。保存用戶的登錄狀態(tài),簡化登錄的手續(xù)(記住密碼)。
- Cookie的典型應用二:“購物車”的處理。
- Cookie的典型應用三:視頻網(wǎng)站播放記錄的存儲。
在JSP頁面中創(chuàng)建和使用Cookie
1 Cookie newCookie = new Cookie(String key,Object value); // 創(chuàng)建Cookie對象 2 response.add(newCookie); // 寫入Cookie對象 3 Cookie[] cookies = request.getCookies(); // 讀取Cookie對象Cooike對象的常用方法:
1 void setMaxAge(int expiry); // 設置cookie的有效期【秒】 2 void setValue(String value);// 對已經(jīng)實例化的cookie對象賦值 3 String getName(); // 獲得cookie的名稱 4 String getValue(); // 獲得cookie的值 5 int getMaxAge(); // 獲得cookie的有效時間【秒】注意:以上方法中的setValue(String value)和String getValue()方法的返回值都是字符串類型——因為Cookie本質(zhì)上就是一個字符串存儲在客戶端,無論對它存值還是取值都應該是字符串類型。
5.3案例:Cookie在登錄中的應用:
實現(xiàn)記憶用戶名和密碼的功能。
用戶登陸頁login.jsp
1 <%@ page language="java" import="java.util.*"2 contentType="text/html; charset=utf-8"%>3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">4 <html>5 <head>6 <title>用戶登錄</title>7 </head>8 9 <body> 10 <% 11 /*獲得Cookie中保存的用戶名和密碼*/ 12 String username = ""; 13 String password = ""; 14 15 Cookie[]cookies = request.getCookies(); 16 if(cookies!=null&&cookies.length>0){ 17 for(Cookie c:cookies){ 18 if(c.getName().equals("username")){ 19 username = c.getValue(); 20 } 21 if(c.getName().equals("password")){ 22 password = c.getValue(); 23 } 24 } 25 } 26 %> 27 28 請輸入用戶名和密碼: 29 <br /> 30 <form action="dologin.jsp" name="loginForm" method="post"> 31 用戶名:<input type="text" name="username" value="<%= username%>" /><br /> 32 密碼:<input type="password" name="password" value="<%= password%>"><br /> 33 <input type="checkbox" checked="checked" name="isUseCookie"> 34 十天內(nèi)記住我<br /> <input type="submit" value="登錄" /> 35 </form> 36 37 </body> 38 </html>處理用戶登錄的頁面dologin.jsp
1 <%@ page language="java" import="java.util.*"2 contentType="text/html; charset=utf-8"%>3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">4 <html>5 <head>6 <title>處理用戶登錄</title>7 </head>8 9 <body> 10 <h1>登錄成功!</h1> 11 <hr /> 12 <% 13 //判斷用戶是否選擇了記住密碼 14 String[] isUseCookie = request.getParameterValues("isUseCookie"); 15 if(isUseCookie!=null&&isUseCookie.length>0){ 16 /*把用戶名和密碼保存在Cookie對象中*/ 17 String username = request.getParameter("username"); 18 String password = request.getParameter("password"); 19 //創(chuàng)建2個Cookie對象 20 Cookie usernameCookie = new Cookie("username",username); 21 Cookie passwordCookie = new Cookie("password",password); 22 usernameCookie.setMaxAge(3600*24*10);//設置cookie生存期10天 23 passwordCookie.setMaxAge(3600*24*10); 24 25 //在客戶端保存Cookie對象,需要依賴response對象的addCookie方法 26 response.addCookie(usernameCookie); 27 response.addCookie(passwordCookie); 28 }else{ 29 /*使已經(jīng)保存的cookie對象失效*/ 30 Cookie[]cookies = request.getCookies();//得到客戶端保存的cookie 31 if(cookies!=null&&cookies.length>0){ 32 //遍歷Cookie數(shù)組 33 for(Cookie c:cookies){ 34 if(c.getName().equals("username")||c.getName().equals("password")){ 35 c.setMaxAge(0);//設置Cookie的有效期是0,讓其馬上失效 36 response.addCookie(c);//重新向客戶端保存Cookie 37 } 38 } 39 } 40 } 41 %> 42 <a href="users.jsp">點擊查看用戶信息</a> 43 </body> 44 </html>用戶信息顯示頁users.jsp
1 <%@ page language="java" import="java.util.*"2 contentType="text/html; charset=utf-8"%>3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">4 <html>5 <head>6 <title>用戶信息顯示</title>7 </head>8 9 <body> 10 <h1>用戶信息</h1> 11 <hr /> 12 <% 13 /*獲得Cookie中保存的用戶名和密碼*/ 14 String username = ""; 15 String password = ""; 16 17 Cookie[]cookies = request.getCookies(); 18 if(cookies!=null&&cookies.length>0){ 19 for(Cookie c:cookies){ 20 if(c.getName().equals("username")){ 21 username = c.getValue(); 22 } 23 if(c.getName().equals("password")){ 24 password = c.getValue(); 25 } 26 } 27 } 28 %> 29 用戶名:<%=username %><br /> 密碼:<%=password %> 30 </body> 31 </html>該項目一般情況下能夠正常運行,但是當我們輸入中文用戶名的時候,服務器會拋出一個500的錯誤。要解決這個問題就需要依靠java網(wǎng)絡包中的URLEncoder和URLDecoder,除此之外不要忘記了在每次使用request對象之前首先要設置request對象的編碼方式。完整的代碼如下:
login.jsp
1 <%@ page language="java" import="java.util.*"2 contentType="text/html; charset=utf-8"%>3 <%@page import="java.net.URLDecoder"%>4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">5 <html>6 <head>7 <title>用戶登錄</title>8 </head>9 10 <body> 11 <% 12 /*獲得Cookie中保存的用戶名和密碼*/ 13 String username = ""; 14 String password = ""; 15 16 request.setCharacterEncoding("utf-8"); 17 Cookie[]cookies = request.getCookies(); 18 if(cookies!=null&&cookies.length>0){ 19 for(Cookie c:cookies){ 20 if (c.getName().equals("username")) { 21 username = URLDecoder.decode(c.getValue(), "utf-8"); 22 } 23 if (c.getName().equals("password")) { 24 password = URLDecoder.decode(c.getValue(), "utf-8"); 25 } 26 } 27 } 28 %> 29 30 請輸入用戶名和密碼: 31 <br /> 32 <form action="dologin.jsp" name="loginForm" method="post"> 33 用戶名:<input type="text" name="username" value="<%= username%>" /><br /> 34 密碼:<input type="password" name="password" value="<%= password%>"><br /> 35 <input type="checkbox" checked="checked" name="isUseCookie"> 36 十天內(nèi)記住我<br /> <input type="submit" value="登錄" /> 37 </form> 38 39 </body> 40 </html>dologin.jsp
1 <%@page import="java.net.URLEncoder"%>2 <%@ page language="java" import="java.util.*"3 contentType="text/html; charset=utf-8"%>4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">5 <html>6 <head>7 <title>處理用戶登錄</title>8 </head>9 10 <body> 11 <h1>登錄成功!</h1> 12 <hr /> 13 <% 14 //判斷用戶是否選擇了記住密碼 15 request.setCharacterEncoding("utf-8"); 16 String[] isUseCookie = request.getParameterValues("isUseCookie"); 17 if (isUseCookie != null && isUseCookie.length > 0) { 18 /*把用戶名和密碼保存在Cookie對象中*/ 19 //得到登錄表單中的內(nèi)容并編碼 20 String username = URLEncoder.encode( 21 request.getParameter("username"), "utf-8"); 22 String password = URLEncoder.encode( 23 request.getParameter("password"), "utf-8"); 24 //創(chuàng)建2個Cookie對象 25 Cookie usernameCookie = new Cookie("username", username); 26 Cookie passwordCookie = new Cookie("password", password); 27 usernameCookie.setMaxAge(3600 * 24 * 10);//設置cookie生存期10天 28 passwordCookie.setMaxAge(3600 * 24 * 10); 29 30 //在客戶端保存Cookie對象,需要依賴response對象的addCookie方法 31 response.addCookie(usernameCookie); 32 response.addCookie(passwordCookie); 33 } else { 34 /*使已經(jīng)保存的cookie對象失效*/ 35 Cookie[] cookies = request.getCookies();//得到客戶端保存的cookie 36 if (cookies != null && cookies.length > 0) { 37 //遍歷Cookie數(shù)組 38 for (Cookie c : cookies) { 39 if (c.getName().equals("username") 40 || c.getName().equals("password")) { 41 c.setMaxAge(0);//設置Cookie的有效期是0,讓其馬上失效 42 response.addCookie(c);//重新向客戶端保存Cookie 43 } 44 } 45 } 46 } 47 %> 48 <a href="users.jsp">點擊查看用戶信息</a> 49 </body> 50 </html>users.jsp
1 <%@page import="java.net.URLDecoder"%>2 <%@ page language="java" import="java.util.*"3 contentType="text/html; charset=utf-8"%>4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">5 <html>6 <head>7 <title>用戶信息顯示</title>8 </head>9 10 <body> 11 <h1>用戶信息</h1> 12 <hr /> 13 <% 14 /*獲得Cookie中保存的用戶名和密碼*/ 15 String username = ""; 16 String password = ""; 17 18 request.setCharacterEncoding("utf-8"); 19 Cookie[] cookies = request.getCookies(); 20 if (cookies != null && cookies.length > 0) { 21 for (Cookie c : cookies) { 22 if (c.getName().equals("username")) { 23 username = URLDecoder.decode(c.getValue(), "utf-8"); 24 } 25 if (c.getName().equals("password")) { 26 password = URLDecoder.decode(c.getValue(), "utf-8"); 27 } 28 } 29 } 30 %> 31 用戶名:<%=username%><br /> 密碼:<%=password%> 32 </body> 33 </html>修正后的項目就支持中文用戶名了。Cookie與Session的區(qū)別是Cookie存放于瀏覽器中,瀏覽器關(guān)閉后再打開,已經(jīng)保存的cookie還是存在。
5.4Session與Cookie對比
| ? | Session | Cookie |
| 保存位置 | 服務端保存用戶信息 | 客戶端保存用戶信息 |
| 保存類型 | Session中保存的是Object類型 | Cookie中保存的是String類型 |
| 生命周期 | 會話結(jié)束,則存儲的數(shù)據(jù)銷毀 | Cookie可長期保存在客戶端 |
| 重要性 | 保存重要信息 | 保存不重要信息 |
?
6.jsp指令【編譯時】與動作【運行時】元素
6.1include指令(可以包含其他頁面)
語法:
<%@ include file="URL"%>例如我們要在include_command.jsp中包含date.jsp的頁面——即:在include_command中顯示date.jsp的內(nèi)容:
date.jsp
1 <%@page import="java.text.SimpleDateFormat"%> 2 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%> 3 <% 4 out.print(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())); 5 %>include_command.jsp
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">3 <html>4 <head>5 <title>在該頁面中使用include指令將剛剛寫的date.jsp包含進來</title>6 </head>7 8 <body>9 <h1>在該頁面中使用include指令將剛剛寫的date.jsp包含進來</h1><hr /> 10 <%@include file="date.jsp" %> 11 </body> 12 </html>運行結(jié)果:
6.2include動作
include動作實際上是JSP動作標簽,語法:
<jsp:include page="URL" flush="true|false" />其中page屬性是需要包含的頁面的URL,而flush屬性制定了被包含的頁面是否從緩沖區(qū)中讀取。
demo:使用include動作在include_action.jsp中包含date.jsp
include_action.jsp
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">3 <html>4 <head>5 <title>include動作</title>6 </head>7 8 <body>9 <h1>在該頁面中使用include動作將剛剛寫的date.jsp包含進來</h1><hr /> 10 <jsp:include page="date.jsp" flush="false"></jsp:include> 11 </body> 12 </html>使用include動作和include指令在jsp頁面的執(zhí)行效果上沒有任何區(qū)別。
6.3include指令與include動作的區(qū)別
在Tomcat服務器的work目錄中刪除剛剛發(fā)布的工程:
先訪問include_command.jsp
work目錄生成以下內(nèi)容:
打開include_005fcommand_jsp.java發(fā)現(xiàn)在它的源代碼中有date.jsp的源代碼:
out.print(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));include指令主頁面和被包含的頁面轉(zhuǎn)換成了同一個Servlet。
在Tomcat的work目錄中刪除編譯生成的Servlet,訪問include_action.jsp生成以下文件:
打開include_005faction_jsp.java發(fā)現(xiàn)源代碼中并沒有包含date.jsp的源代碼,而是由下面的一條代碼將date.jsp的輸出結(jié)果包含到該jsp頁面:
// 該語句相當于調(diào)用date.jsp,并將date.jsp的輸出結(jié)果返回給該頁面 org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "date.jsp", out, false);6.4forward動作
服務器內(nèi)部轉(zhuǎn)發(fā)指令,語法:
1 <jsp:forward page="URL" /> 2 3 // 相當于 4 request.getRequestDispatcher("url").forward(request,response);例如:在登陸頁中將用戶的表單處理交給forward_action.jsp頁面處理,forward_action.jsp將該請求通過forward動作轉(zhuǎn)發(fā)給users.jsp,users.jsp從request對象中取得用戶名和密碼給予顯示:
login.jsp
1 <%@ page language="java" import="java.util.*"2 contentType="text/html; charset=utf-8"%>3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">4 <html>5 <head>6 <title>用戶登錄</title>7 </head>8 9 <body> 10 請輸入用戶名和密碼: 11 <br /> 12 <form action="forward_action.jsp" name="loginForm" method="post"> 13 用戶名:<input type="text" name="username" /><br /> 14 密碼:<input type="password" name="password" /><br /> 15 <input type="submit" value="登錄" /> 16 </form> 17 </body> 18 </html>forward_action.jsp
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">3 <html>4 <head>5 <title>forward動作</title>6 </head>7 8 <body>9 <h1>該頁面處理用戶提交的表單信息</h1> 10 <h2>forward動作</h2> 11 <jsp:forward page="users.jsp"></jsp:forward> 12 <!-- 上面這條語句和下面的這條語句相當 --> 13 <%-- 14 request.getRequestDispatcher("users.jsp").forward(request, response); 15 --%> 16 </body> 17 </html>users.jsp
1 <%@ page language="java" import="java.util.*"2 contentType="text/html; charset=utf-8"%>3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">4 <html>5 <head>6 <title>用戶信息顯示</title>7 </head>8 9 <body> 10 <h1>用戶信息</h1> 11 <hr /> 12 <% 13 request.setCharacterEncoding("utf-8"); 14 15 String username = ""; 16 String password = ""; 17 if(request.getParameter("username")!=null){ 18 username = request.getParameter("username"); 19 } 20 if(request.getParameter("password")!=null){ 21 password = request.getParameter("password"); 22 } 23 %> 24 用戶名:<%=username %><br /> 密碼:<%=password %> 25 </body> 26 </html>運行結(jié)果:
6.5param動作
語法:
1 <jsp:param name="參數(shù)名" value="參數(shù)名" /> 2 <!-- 該動作常常作為<jsp:forward>的子標簽,和它一起使用 -->用戶將提交的表單交給dologin.jsp處理,dologin.jsp通過forward動作把請求轉(zhuǎn)發(fā)給users.jsp(并人為添加表單中沒有的內(nèi)容:郵箱,修改表單中提交的用戶名為root),users.jsp通過request.getParamer()方法獲得用戶名、密碼、郵箱并予以顯示:
login.jsp
1 <%@ page language="java" import="java.util.*"2 contentType="text/html; charset=utf-8"%>3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">4 <html>5 <head>6 <title>用戶登錄</title>7 </head>8 9 <body> 10 請輸入用戶名和密碼: 11 <br /> 12 <form action="dologin.jsp" name="loginForm" method="post"> 13 用戶名:<input type="text" name="username" /><br /> 14 密碼:<input type="password" name="password" /><br /> 15 <input type="submit" value="登錄" /> 16 </form> 17 </body> 18 </html>dologin.jsp
1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%> 2 <jsp:forward page="users.jsp"> 3 <jsp:param value="io@gmail.com" name="email"/> 4 <jsp:param value="root" name="username"/> 5 </jsp:forward>users.jsp
1 <%@ page language="java" import="java.util.*"2 contentType="text/html; charset=utf-8"%>3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">4 <html>5 <head>6 <title>用戶信息顯示</title>7 </head>8 9 <body> 10 <h1>用戶信息</h1> 11 <hr /> 12 <% 13 request.setCharacterEncoding("utf-8"); 14 15 String username = ""; 16 String password = ""; 17 String email = ""; 18 if(request.getParameter("username")!=null){ 19 username = request.getParameter("username"); 20 } 21 if(request.getParameter("password")!=null){ 22 password = request.getParameter("password"); 23 } 24 if(request.getParameter("email")!=null){ 25 email = request.getParameter("email"); 26 } 27 %> 28 用戶名:<%=username %><br /> 密碼:<%=password %><br>郵箱:<%=email %> 29 </body> 30 </html>效果圖:
7.jsp案例項目——商品瀏覽記錄的實現(xiàn)
該項目使用Model1(JSP+JavaBean)使用Cookie機制實現(xiàn)。該項目使用到了數(shù)據(jù)庫(數(shù)據(jù)庫中存放了商品表)。實現(xiàn)步驟如下:
DB-->JavaBean-->JSP。項目的目錄結(jié)構(gòu):
一、實現(xiàn)DBHelper類:
該類的主要作用是取得數(shù)據(jù)庫的連接并關(guān)閉相關(guān)資源。
1 package util;2 3 import java.sql.Connection;4 import java.sql.DriverManager;5 import java.sql.PreparedStatement;6 import java.sql.ResultSet;7 import java.sql.SQLException;8 9 public class DBHelper { 10 private static final String DRIVER = "com.mysql.jdbc.Driver"; 11 private static final String URL = "jdbc:mysql://localhost:3306/shopping?useUnicode=true&characterEncoding=UTF-8"; 12 private static final String USER = "root"; 13 private static final String PASSWORD = "mysqladmin"; 14 15 private static Connection coon = null;// DB連接對象 16 17 /** 靜態(tài)代碼塊加載DB驅(qū)動 */ 18 static { 19 try { 20 Class.forName(DRIVER); 21 } catch (ClassNotFoundException e) { 22 e.printStackTrace(); 23 } 24 } 25 26 /** Singleton設計模式返回DB連接對象 */ 27 public static Connection getConnection() throws SQLException { 28 if (coon == null) { 29 coon = DriverManager.getConnection(URL, USER, PASSWORD); 30 return coon; 31 } 32 return coon; 33 } 34 35 /** 清理資源-關(guān)閉DB結(jié)果集、釋放語句對象 */ 36 public static void relsaseResource(ResultSet rs,PreparedStatement pstmt){ 37 // 釋放結(jié)果集 38 if (rs != null) { 39 try { 40 rs.close(); 41 rs = null; 42 } catch (SQLException e) { 43 e.printStackTrace(); 44 } 45 } 46 // 釋放語句對象 47 if (pstmt != null) { 48 try { 49 pstmt.close(); 50 pstmt = null; 51 } catch (SQLException e) { 52 e.printStackTrace(); 53 } 54 } 55 } 56 57 /** 測試DB連接 */ 58 public static void main(String[] args) { 59 try { 60 Connection connection = DBHelper.getConnection(); 61 if(connection!=null){ 62 System.out.println("數(shù)據(jù)庫連接成功!"); 63 }else { 64 System.out.println("數(shù)據(jù)庫連接異常!"); 65 } 66 } catch (SQLException e) { 67 e.printStackTrace(); 68 } 69 } 70 } 如果shopping數(shù)據(jù)庫沒有創(chuàng)建可能會拋出異常只需要執(zhí)行: create database shopping;二、商品實體類的設計:
在創(chuàng)建實體類之前先建立好數(shù)據(jù)庫表:
數(shù)據(jù)庫腳本:items.sql
1 /*2 Navicat MySQL Data Transfer3 4 Source Server : MySQL505 Source Server Version : 500676 Source Host : localhost:33067 Source Database : shopping8 9 Target Server Type : MYSQL 10 Target Server Version : 50067 11 File Encoding : 65001 12 13 Date: 2014-08-27 12:12:31 14 */ 15 16 SET FOREIGN_KEY_CHECKS=0; 17 18 -- ---------------------------- 19 -- Table structure for items 20 -- ---------------------------- 21 DROP TABLE IF EXISTS `items`; 22 CREATE TABLE `items` ( 23 `id` int(11) NOT NULL auto_increment, 24 `name` varchar(50) default NULL, 25 `city` varchar(50) default NULL, 26 `price` int(11) default NULL, 27 `number` int(11) default NULL, 28 `picture` varchar(500) default NULL, 29 PRIMARY KEY (`id`) 30 ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; 31 32 -- ---------------------------- 33 -- Records of items 34 -- ---------------------------- 35 INSERT INTO `items` VALUES ('1', '沃特籃球鞋', '佛山', '180', '500', '001.jpg'); 36 INSERT INTO `items` VALUES ('2', '安踏運動鞋', '福州', '120', '800', '002.jpg'); 37 INSERT INTO `items` VALUES ('3', '耐克運動鞋', '廣州', '500', '1000', '003.jpg'); 38 INSERT INTO `items` VALUES ('4', '阿迪達斯T血衫', '上海', '388', '600', '004.jpg'); 39 INSERT INTO `items` VALUES ('5', '李寧文化衫', '廣州', '180', '900', '005.jpg'); 40 INSERT INTO `items` VALUES ('6', '小米3', '北京', '1999', '3000', '006.jpg'); 41 INSERT INTO `items` VALUES ('7', '小米2S', '北京', '1299', '1000', '007.jpg'); 42 INSERT INTO `items` VALUES ('8', 'thinkpad筆記本', '北京', '6999', '500', '008.jpg'); 43 INSERT INTO `items` VALUES ('9', 'dell筆記本', '北京', '3999', '500', '009.jpg'); 44 INSERT INTO `items` VALUES ('10', 'ipad5', '北京', '5999', '500', '010.jpg');在MySQL中查詢:
建立實體類(Items):也就是javabean其屬性與DB中的各個字段一一對應。
1 package entity;2 3 /**4 * 商品類(與DB中的表名一致)-javabean 屬性和DB中表的字段完全一致5 */6 public class Items {7 private int id;8 private String name;9 private String city; 10 private int price; 11 private int number; 12 private String picture; 13 14 public Items() { 15 } 16 17 public int getId() { 18 return id; 19 } 20 21 public void setId(int id) { 22 this.id = id; 23 } 24 25 public String getName() { 26 return name; 27 } 28 29 public void setName(String name) { 30 this.name = name; 31 } 32 33 public String getCity() { 34 return city; 35 } 36 37 public void setCity(String city) { 38 this.city = city; 39 } 40 41 public int getPrice() { 42 return price; 43 } 44 45 public void setPrice(int price) { 46 this.price = price; 47 } 48 49 public int getNumber() { 50 return number; 51 } 52 53 public void setNumber(int number) { 54 this.number = number; 55 } 56 57 public String getPicture() { 58 return picture; 59 } 60 61 public void setPicture(String picture) { 62 this.picture = picture; 63 } 64 65 }三、實現(xiàn)業(yè)務邏輯類(數(shù)據(jù)訪問層DAO)
該類需要完成的功能:
分析:
1.在index.jsp中我們需要展示所有的商品信息。——獲得所有商品
2.當用戶點擊任意一種商品后會將id通過URL傳遞給details.jsp,而在details.jsp中我們需要——根據(jù)id獲得對應商品。
3.根據(jù)Cookie傳入的字符串獲得最近瀏覽的5條記錄。
思考:如何將瀏覽記錄保存在Cookie中?
?
?
?
回答:只需要保存商品的ID即可,因為每個商品的ID是唯一的。
?
?
?
實現(xiàn):把每次瀏覽的商品ID保存一個字符串中,將這個字符串保存在Cookie中,ID和ID之間用分隔符分隔,每次取出前5條記錄。
?
?
?
顯示所有商品的主頁index.jsp
?
?
1 <%@page import="entity.Items"%>2 <%@page import="dao.ItemsDAO"%>3 <%@ page language="java" import="java.util.*"4 contentType="text/html; charset=utf-8"%>5 <!-- 顯示所有的商品信息 -->6 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">7 <html>8 <head>9 <title>歡迎光臨網(wǎng)上商城</title> 10 <style type="text/css"> 11 div { 12 float: left; 13 margin: 10px; 14 } 15 16 div dd { 17 margin: 0px; 18 font-size: 10pt; 19 } 20 21 div dd.dd_name { 22 color: blue; 23 } 24 25 div dd.dd_city { 26 color: #000; 27 } 28 </style> 29 </head> 30 31 <body> 32 <h1>商品展示</h1> 33 <hr> 34 <center> 35 <table width="750" height="60" cellpadding="0" cellspacing="0" 36 border="0"> 37 <tr> 38 <td> 39 <!-- 商品循環(huán)開始 --> 40 <% 41 ItemsDAO itemsDAO = new ItemsDAO(); 42 ArrayList<Items>list = itemsDAO.getAllItems(); 43 if(list!=null&&list.size()>0){ 44 //遍歷所有的商品 45 for(Items item:list){ 46 %> 47 <div> 48 <dl> 49 <dt> 50 <a href="details.jsp?id=<%=item.getId() %>"> 51 <img src="images/<%=item.getPicture() %>" width="120" height="90" border="1"/> 52 </a> 53 </dt> 54 <dd class="dd_name"><%=item.getName() %></dd> 55 <dd class="dd_city">產(chǎn)地:<%=item.getCity() %> 價格:¥<%=item.getPrice() %></dd> 56 </dl> 57 </div> 58 <% 59 } 60 } 61 %> 62 <!-- 商品循環(huán)結(jié)束 --> 63 </td> 64 </tr> 65 </table> 66 </center> 67 </body> 68 </html>顯示商品詳細信息的details.jsp
1 <%@page import="entity.Items"%>2 <%@page import="dao.ItemsDAO"%>3 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>4 <!-- 顯示商品詳情,并在右側(cè)顯示商品的瀏覽記錄(最近5條記錄) -->5 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">6 <html>7 <head>8 <title>歡迎光臨網(wǎng)上商城</title>9 <style type="text/css">10 div{11 float:left;12 margin-left: 30px;13 margin-right:30px;14 margin-top: 5px;15 margin-bottom: 5px;16 }17 div dd{18 margin:0px;19 font-size:10pt;20 }21 div dd.dd_name22 {23 color:blue;24 }25 div dd.dd_city26 {27 color:#000;28 }29 </style>30 </head>31 32 <body> 33 <h1>商品詳情</h1><hr>34 <center>35 <table width="750" height="60" cellpadding="0" cellspacing="0" border="0">36 <tr>37 <!-- 商品詳細信息 -->38 <%39 Items item = new ItemsDAO().getItemsById(Integer.parseInt(request.getParameter("id")));40 if(item!=null){41 %>42 <td width="70%" valign="top">43 <table>44 <tr>45 <td rowspan="4"><img src="images/<%=item.getPicture()%>" width="200" height="160"/></td>46 </tr>47 <tr>48 <td><b><%=item.getName() %></b></td>49 </tr>50 <tr>51 <td>產(chǎn)地:<%=item.getCity() %></td>52 </tr>53 <tr>54 <td>價格:¥<font color="red"><b><%=item.getPrice() %></b></font></td>55 </tr>56 </table>57 </td>58 <%59 } 60 %>61 <!-- 取得Cookie -->62 <%63 String list = "";64 // 從客戶端獲得Cookie集合65 Cookie[]cookies = request.getCookies();66 if(cookies!=null&&cookies.length>0){67 for(Cookie c:cookies){68 if(c.getName().equals("ListViewCookie")){69 list = c.getValue();70 }71 72 String[] arr = list.split(",");73 // 相同商品只在瀏覽記錄中存放一次74 if(Arrays.binarySearch(arr, request.getParameter("id"))<0){75 list += request.getParameter("id") + ",";76 }77 // 如果瀏覽記錄超過1000條,則清空Cookie78 if(arr!=null&&arr.length>1000){79 list = "";// 清零-置空串80 }81 Cookie cookie = new Cookie("ListViewCookie",list);82 response.addCookie(cookie);83 }84 }85 %>86 87 <!-- 瀏覽過的商品 -->88 <td width="30%" bgcolor="#EEE" align="center">89 <br /><b>您瀏覽過的商品</b><br />90 <!-- 循環(huán)開始 -->91 <%92 ArrayList<Items>itemsList = new ItemsDAO().getViewList(list);93 if(itemsList!=null&&itemsList.size()>0){94 for(Items i:itemsList){95 %>96 <div>97 <dl>98 <dt><img src="images/<%=i.getPicture() %>" width="120" height="90" border="1" /></dt>99 <dd class="dd_name"><%=i.getName() %></dd> 100 <dd class="dd_city">產(chǎn)地:<%=i.getCity() %> 價格:¥<%=i.getPrice() %></dd> 101 </dl> 102 </div> 103 <% 104 } 105 } 106 %> 107 <!-- 循環(huán)結(jié)束 --> 108 </td> 109 </tr> 110 </table> 111 </center> 112 </body> 113 </html>主業(yè)務邏輯類ItemsDAO
?View Code項目展示:(項目地址:https://git.oschina.net/gaopengfei/JSPLogin.git)
Tips:
解決中文亂碼:
1)在執(zhí)行獲取請求參數(shù)前設置編碼:
request.setCharacterEncoding(“漢字編碼”);2)轉(zhuǎn)換字符編碼:
1 //獲取原始的請求參數(shù)值 2 String rawName = request.getParameter("name"); 3 //將請求參數(shù)值使用ISO-8859-1字符串分解成字節(jié)數(shù)組 4 byte[] rawBytes = rawName.getBytes("ISO-8859-1"); 5 //將字節(jié)數(shù)組重新編碼成字符串 6 String name = new String(rawBytes , "gb2312");3)獲取請求參數(shù)同時轉(zhuǎn)換編碼:
request.getParameter(“name”).getBytes ("ISO-8859-1");?
轉(zhuǎn)載于:https://www.cnblogs.com/IvySue/p/7507238.html
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的java web学习笔记-jsp篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 给定地址段为0001H,仅通过变化偏移地
- 下一篇: 【KEIL·单片机·扫盲贴】关于ARM单