java web學習筆記-jsp篇

轉載自:http://www.cnblogs.com/happyfans/archive/2015/03/17/4343571.htmljavascript

1.java web簡介

  1.1靜態頁面與動態頁面

  表現形式 所需技術
靜態網頁 網頁內容固定,不會更新 html,css
動態網頁 網頁內容由程序動態顯示,自動更新 html,css,DB,java/c#/php,javascript,xml,主流的動態網頁腳本(jsp,asp.net,php)

 

  1.2搭建java web開發環境

    jdk1.7+tomcat7.0+MyEclipse10。關於MyEclipse的安裝和配置請參見http://blog.sina.com.cn/s/blog_907043b301016jtp.html。Tomcat服務器是Apache Jakarta的開源項目,是Jsp/Servlet容器。安裝Tomcat只須要解壓zip包到指定目錄便可。新建一個環境變量CATALINA_HOME,變量的值是Tomcat的根目錄D:\Program Files (x86)\apache-tomcat-7.0.57。所有的環境變量以下:php

變量名 變量值
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的首頁:css

  進入Tomcat服務器根目錄下面的bin目錄,以管理員方式運行startup.bat,若是運行結果以下就表示Tomcat服務器啓動成功。html

  注意:不要關閉這個窗口(關閉窗口就意味着關閉了Tomcat服務器,將其最小化)。java

在瀏覽器地址欄輸入http://localhost:8080/回車獲得以下頁面:
mysql

  

1.3Tomcat目錄結構

  1.4手工編寫第一個web應用程序

  在項目文件夾中建立一個index.jsp:git

複製代碼
 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>
複製代碼

  在項目目錄中建立一個WEB-INF目錄拷貝/webapps/examples/WEB-INFO/web.xm到本身項目的/myJspProject/WEB-INFO中,在/myJspProject/WEB-INFO中建立兩個文件夾:classes和lib。最後的項目目錄應該是這樣:web

  測試:瀏覽器輸入:http://localhost:8080/myJspProject/index.jsp回車,運行結果以下:sql

 解決方法:更改瀏覽器編碼爲指定編碼:數據庫

  1.5WEB-INF目錄詳解

      該目錄是java web應用的安全目錄。所謂安全目錄就是客戶端沒法訪問只有服務端能夠訪問的目錄。其中web.xml是項目部署文件,classes目錄:存放*.class文件,lib目錄存放須要的jar包。例如:咱們在WEB-INF中建立一個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>    

  運行結果:

  1.6實用Eclipse編寫第一個web應用程序

      注意:若是要使用Eclipse編寫java web應用應該使用Eclipse的J2EE版本。並在Eclipse中配置Tomcat服務器Window-Preference-Server-Runtime Environment-Add,而後在WebContent目錄下新建jsp文件,按下Ctrl+F11(或者在項目中右鍵-Run On Server)就可使用內置瀏覽器訪問創建的網站。

  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中啓動和發佈Web應用程序了。

  New一個WebProject會生成如下的目錄結構(默認在WebRoot目錄下有一個index.jsp)。

  發佈該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設計,它實現了在java當中使用html標記。jsp是一種動態網頁技術,符合J2EE標準。jsp和Servlet同樣也是在服務器端執行的。

  2.2常見動態網站開發技術對比

平臺 特色
jsp 跨平臺,安全性高,適合開發大型的、企業級的Web應用、分佈式應用(Hadoop)。例如:1230六、10086.cn、網上銀行
asp.net 簡單易學,安全性和跨平臺性差
php 簡單、高效、成本低、開發週期短,適合中小型企業的Web應用開發(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 <%@page
 2     [language="Java"]
 3     [extends="package.class"] // 指定JSP頁面編譯所產生的Java類所繼承的父類,或所實現的接口。
 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內建了異常機制支持,因此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頁面中執行的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內置對象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頁面中執行的表達式。語法(注意=緊挨着百分號,表達式末尾沒有分號):

<%=表達式 %>
複製代碼
 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>
複製代碼

  運行結果:

  2.8jsp頁面生命週期

    

    jspService()方法被調用來處理客戶端的請求。對每個請求,JSP引擎建立一個新的線程來處理該請求。若是有多個客戶端同時請求你該jsp文件,則jsp引擎會建立多個線程(每個客戶端請求對應一個線程)。以多線程的方式執行能夠大大下降對系統的資源需求,提升系統的併發量以及縮短服務器的響應時間——可是同時要注意多線程的同步問題。因爲該Servlet常駐內存,因此響應是很是快的。

    當頁面沒有被訪問的時候work目錄下沒有相關的Servlet。若是頁面被訪問以後就會在work目錄的對應目錄生成響應的Servlet。如圖:

  打開index_jsp.java會看到如下的初始化方法:

  而後該Servlet常駐內存,建立線程處理每個客戶端的請求。由每個線程調用_jspService()方法來處理請求。

  若是jsp頁面內容發生了改變,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() //調用表達式
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          //調用腳本
61      printMultiTable2(out);
62       %>
63 </body>
64 </html>
複製代碼

  運行結果:

3.jsp內置對象

  3.1jsp內置對象簡介

      JSP內置對象是Web容器建立的一組對象,不須要使用new關鍵字,JSP規範將它們完成了默認初始化(由JSP頁面對應Servlet的_jspService()方法來建立這些實例)。例如打印九九乘法表的jsp小腳本中使用的out對象就是jsp內置對象。

複製代碼
 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內置對象
12         }
13 %>
複製代碼

    JSP一共有9個內置對象,其中經常使用的內置對象有5個,如圖所示:

  3.3out對象

    緩衝區(Buffer)就是內存中用來保存臨時數據的一塊區域。關於緩衝區有一個很形象的例子:好比咱們煮好了飯放在鍋裏,若是咱們一粒一粒地來吃米飯就不知道吃到猴年馬月,拿來一個碗來一碗一碗吃,豈不快哉!這裏的碗就充當了緩衝區的概念。其實IO的本質就是直接操做字節,可是效率太慢因此引入了緩衝區。

    out對象是JspWriter類的一個實例——是向客戶端輸出內容的經常使用對象,該對象的經常使用方法:

複製代碼
1 void println(String message);   // 向客戶端打印字符串
2 void clear();                   // 清除緩衝區內容,若是在flush以後調用會拋出異常
3 void clearBuffer();             // 清除緩衝區內容,若是在flush以後調用不會拋出異常
4 void flush();                   // 將緩衝區的內容輸出到客戶端
5 int getBufferSize();            // 返回緩衝區的大小(字節),默認是0
6 int getRemaining();             // 返回緩衝區可用容量
7 boolean isAutoFlush();          // 返回緩衝區滿的時候是自動清空仍是拋出異常
8 void close();                   // 關閉輸出流
複製代碼

    下面是一個簡單的示例:

複製代碼
 1 <h1>JSP的out內置對象</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("低頭思故鄉。<hr />");
10      %>
11      <!-- JSP表達式 -->
12      緩衝區大小:<%=out.getBufferSize() %>字節。<br />
13     剩餘緩衝區(可用緩衝區):<%=out.getRemaining() %>字節。<br /> 
14     是否自動清空緩衝區:<%=out.isAutoFlush() %><br />
複製代碼

  運行結果:

複製代碼
 1 <h1>JSP的out內置對象</h1>
 2     <%
 3         //jsp腳本
 4         out.println("<h2>靜夜思</h2>");
 5         out.println("李白<br /><br />");
 6         out.println("窗前明月光,<br />");
7 out.flush();//將緩衝區中的內容輸出到客戶端
8 out.println("疑是地上霜。<br />"); 9 out.println("舉頭望明月,<br />"); 10 out.println("低頭思故鄉。<hr />"); 11 %> 12 <!-- JSP表達式 --> 13 緩衝區大小:<%=out.getBufferSize() %>字節。<br /> 14 剩餘緩衝區(可用緩衝區):<%=out.getRemaining() %>字節。<br /> 15 是否自動清空緩衝區:<%=out.isAutoFlush() %><br />
複製代碼

  若是在第7行強制刷新緩衝區,則輸出的頁面不會有任何變化,僅僅是可用緩衝區的數量變多了而已【由於flush清空了緩衝區】

複製代碼
 1 <%
 2         //jsp腳本
 3         out.println("<h2>靜夜思</h2>");
 4         out.println("李白<br /><br />");
 5         out.println("窗前明月光,<br />");
 6         
 7     out.flush();//將緩衝區中的內容輸出到客戶端
 8     out.clear();//在flush以後調用clear,將會拋出異常
 9     
10         out.println("疑是地上霜。<br />");
11         out.println("舉頭望明月,<br />");
12         out.println("低頭思故鄉。<hr />");
13 %>
複製代碼

  運行結果:

複製代碼
 1  <%
 2         //jsp腳本
 3         out.println("<h2>靜夜思</h2>");
 4         out.println("李白<br /><br />");
 5         out.println("窗前明月光,<br />");
 6         
 7     out.flush();//將緩衝區中的內容輸出到客戶端
 8     out.clearBuffer();//在flush以後調用clearBuffer不會拋出異常
 9     
10         out.println("疑是地上霜。<br />");
11         out.println("舉頭望明月,<br />");
12         out.println("低頭思故鄉。<hr />");
13 %>
複製代碼

  運行結果:

  3.4post和get提交方式的區別

<form name="regForm" action="處理腳本"  method="提交方式[post|get]"></form>
  • get:以明文的方式經過URL提交數據,提交的數據最大不超過2K。適合提交數據量小,安全性不高的數據【例如:搜索和查詢】
  • post:將用戶提交的數據封裝在URL HEADER內。適合提交數據量大,安全性高的數據【例如:註冊、修改、上傳】 
  • 下面以用戶登陸的例子比較二者的區別:
    login.jsp頁面
1    請輸入用戶名和密碼:
2     <form  name = "loginForm" action = "dologin.jsp" method = "get">
3     用戶名:<input type="text" name="username" value="" maxlength = "15" /><br />
4     密碼:<input type="password" name="password" maxlength="16" value="" /><br />
5     <input type="submit" value="提交" />
6     </form>

  處理登陸的動做腳本dologin.jsp僅僅是顯示一句話"登陸成功"。

  運行結果:

  將用戶登陸表單的get方式改成post。

  3.5request對象

    客戶端的請求被封裝在request對象中,經過它才能瞭解到客戶端的需求,而後作出響應。它是HttpServletRequest對象的實例。request對象具備請求域,即:完成客戶端的請求以前,該對象一直有效。經常使用方法以下:

複製代碼
/* 兩個比較經常使用的方法 */
1 String getParameter(String name); // 返回name指定參數的參數值 2 String[] getParameterValues(String name); // 返回包含name的全部值的數組

3 void setAttribute(String,Object); // 存儲此請求中的屬性 4 String getContentType(); // 返回請求體的MIME類型 5 Stirng getProtocol(); // 返回請求所用的協議和版本號 6 String getServerName(); // 返回接受請求的服務器的主機名 7 int getServerPort(); // 返回服務器接受此請求所用的端口號 8 String getCharacterEncoding(); // 返回字符編碼方式【只能解決post方式的亂碼問題】 9 void setCharacterEncoding(); // 設置請求的字符編碼方式 10 int getContentLength(); // 返回請求體的長度(字節) 11 String getRemoteAddr(); // 返回發送此請求的客戶端IP 12 String getRealPath(String path); // 返回虛擬路徑的真實路徑 13 String request.getContextPath(); // 返回上下文路徑
複製代碼

  以用戶註冊頁面爲例(用戶在註冊頁reg.jsp完善信息後提交給request.jsp來處理):

  用戶註冊頁reg.jsp

複製代碼
 1    請輸入相關信息完成註冊<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"/>上網<br />
10         <input type="submit" value="提交" />  
11     </form>
複製代碼

   處理用戶註冊頁的request.jsp

複製代碼
 1  <h1>request內置對象</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+"&nbsp;&nbsp;");
10         }
11     %>
複製代碼

    運行結果:

  可是以上頁面存在一個問題:假如咱們在用戶名中輸入中文:

  這時只要再request.jsp中設置字符集和reg.jsp同樣便可:

複製代碼
 1 <h1>request內置對象</h1><br  />
 2     <!-- 設置字符集,防止出現中文亂碼 -->
 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+"&nbsp;&nbsp;"); 11 } 12 %>
複製代碼

  除了可使用表單的方式傳遞數據給request對象,也可使用URL傳參的方式傳遞數據給request對象:

  reg.jsp

<a href="request.jsp?username=root&password=toor&favorite=read&favorite=internet">測試URL傳參</a>

  request.jsp(不變)

複製代碼
 1 <h1>request內置對象</h1><br  />
 2     <!-- 設置字符集,防止出現中文亂碼 -->
 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+"&nbsp;&nbsp;");
12         }
13     }
14    %>
複製代碼

  運行結果:

  若是咱們在URL傳參中傳入了中文數據,一樣會出現亂碼問題:

<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   請輸入相關信息完成註冊<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"/>上網<br />
10         <input type="submit" value="提交" />  
11     </form>
複製代碼

  request.jsp

複製代碼
 1 <h1>request內置對象</h1><br  />
 2     <!-- 設置字符集,防止出現中文亂碼 -->
 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+"&nbsp;&nbsp;");
17         }
18     }
19      %>
20   <br />郵箱:<%=request.getAttribute("email") %>  
複製代碼

  運行結果:

複製代碼
 1  <h1>request內置對象</h1><br  />
 2     <!-- 設置字符集,防止出現中文亂碼 -->
 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+"&nbsp;&nbsp;");
17         }
18     }
19      %>
20   <br />郵箱:<%=request.getAttribute("email") %>  <hr />
21   請求體的MIME類型:<%=request.getContentType() %><br />
22   請求體的協議及版本號:<%=request.getProtocol() %><br />
23   服務器主機名:<%=request.getServerName() %><br />
24   服務器端口號:<%=request.getServerPort() %><br />
25   請求的字符編碼:<%=request.getCharacterEncoding() %><br />
26   請求的文件長度:<%=request.getContentLength() %>字節<br />
27   請求的客戶端的IP:<%=request.getRemoteAddr() %><br />
28   請求的真實路徑:<%=request.getRealPath("request.jsp") %><br />
29   請求的上下文路徑:<%=request.getContextPath() %>
複製代碼

  運行結果:

  3.6response對象

    response對象包含了響應客戶請求的相關信息,可是在JSP中不多直接使用到它。它是HttpServletResponse類的實例。response對象具備頁面做用域——即:訪問一個頁面時,該頁面的response只對本次訪問有效,其餘頁面的response對象對當前頁面無效。經常使用方法以下:

1 String getCharacterEncoding();     // 返回響應所用的編碼
2 void setContentType();             // 設置響應的MIME類型
3 PrintWriter getPrintWriter();      // 返回一個能夠向客戶端輸出字符的對象【注意區別於out內置對象】
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內置對象</h1><hr />");
 7     
 8     PrintWriter outer = response.getWriter();//得到輸出流對象
 9     outer.println("我是response對象生成的outter對象,在頁面中老是在前面輸出");
10 %>
複製代碼

  運行結果:

  運行結果非常奇怪:明明out對象的輸出在代碼中位於前面。可是結果倒是PrintWriter的打印結果在前面,根本緣由就是:PrintWriter的對象的輸出老是在最前面。若是咱們須要讓標題先輸出,可使用內置對象out的flush()方法強制刷新緩衝,向頁面輸出——保證標題出如今最前面。

  請求重定向——當用戶請求response.jsp的時候立刻跳轉到login.jsp

<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
<%
    response.sendRedirect("login.jsp"); // 請求重定向
%>

  3.7請求重定向與請求轉發的區別

  • 請求重定向:客戶端行爲response.sendResponse(),從本質上講至關於兩次請求,前一次的請求對象不會保存,瀏覽器的URL欄會改變。
  • 請求轉發:服務器行爲request.getRequestDipatcher().forword(req,resp);是一次請求,轉發後請求對象會被保存,瀏覽器的URL不會改變。
  • 例如仍是用原來的例子:咱們在reg.jsp中指定處理頁面的腳本是response.jsp而在response.jsp中咱們重定向到request.jsp。觀察request.jsp的輸出:

  若是咱們在response.jsp中使用請求轉發:

1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
2 <%
3     //請求轉發
4     request.getRequestDispatcher("request.jsp").forward(request, response);
5 %>

  運行結果:

  3.8session對象

    Session客戶端與服務器的一次會話。Web中的Session表示用戶在瀏覽某個網站時,從進入網站到瀏覽器關閉所通過的這段時間——也就是用戶瀏覽這個網站所花費的時間。在服務器的內存中保存着不一樣用戶的Session。

  session對象的經常使用方法:

複製代碼
1 long getCreationTime();                          // 返回session的建立時間
2 String getId();                                  // 返回session建立時JSP引擎爲它設定的惟一ID號
3 Object setAttribute(String name,Object value);   // 使用指定名稱將對象綁定到此會話
4 Object getAttribute(String name);                // 返回此會話中的指定名稱綁定在一塊兒的對象,若是沒有對象綁定在該名稱下則返回null
5 String[] getValueNames();                        // 返回一個包含此Session全部可用屬性的數組
6 int getMaxInactiveInterval();                    // 返回兩次請求間隔多長時間此session被取消【單位:秒】
複製代碼

  sesseion_page1.jsp

複製代碼
 1    <h1>session內置對象</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的建立時間:" + 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的建立時間:" + date); 
6      %>
7    <br />Session的ID號:<%=session.getId() %><br />
8    從session中獲取用戶名:<%=session.getAttribute("username") %>
複製代碼

  運行結果:

  能夠獲取session中保存的屬性集合以及設置session的有效期:

複製代碼
 1  <%      
 2         session.setMaxInactiveInterval(5);//設置session的有效期爲5s
 3         
 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的生命週期:

  • 建立:當客戶端第一次訪問某個jsp頁面或者Servlet的時候,服務器會爲當前會話建立一個SessionId。每次客戶端向服務器發送請求的時候都會攜帶此SessionId,服務端會對此SessionId進行檢驗——判斷是否屬於同一次會話。
  • 活動階段:某次會話中經過超連接打開新的頁面;只要當前頁面沒有所有關閉,打開新的瀏覽器窗口訪問同一項目資源也屬於同一會話。注意:原有的會話仍然存在,只不過再也沒有客戶端會攜帶此sessionId交給服務器檢驗。——建立一個新的會話並不意味着原有會話消失,除非超時。
  • 銷燬。

  Tomcat如何進入後臺管理系統?

   修改/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在後臺管理系統中查看:

 

  若是咱們在session建立以後調用session.invalidate()方法,例如:咱們在session_page1.jsp中這樣寫:

複製代碼
 1  <h1>session內置對象</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的建立時間:" + 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>
複製代碼

  運行結果(不斷刷新瀏覽器):

  Session默認session超時是30min設置session對象的超時有兩種方式:

  • session.setMaxInactiveInterval(5);單位是秒
  • 在web.xml中配置(單位是分鐘):
  • <session-config>
            <session-timeout>30</session-timeout>
    </session-config>

    3.9application對象

  • application對象實現了用戶間數據的共享,能夠存放全局變量。
  • application對象開始於服務器的啓動,結束於服務器的關閉。
  • 在用戶的先後鏈接或者不一樣用戶之間,能夠對統一個application對象的屬性進行操做。
  • 在任何地方對application對象屬性的操做將會影響到其餘用戶對此的訪問。
  • application對象是ServletContext類的實例。
  • 該對象的經常使用方法以下:
1 void setAttribute(String name,Object value); // 指定名稱將對象綁定到此會話
2 Object getAttribute(String name);            // 返回此會話中和指定名稱綁定在一塊兒的對象,若是沒有對象綁定在該名稱下則返回null
3 Enumeration getAttributeNames();             // 返回全部可用屬性名的枚舉
4 String getServerInfo();                      // 返回JSP(Servlet)引擎名和版本號

  

複製代碼
 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內置對象</h1>
2     當前頁面的page對象的字符串描述:<br />
3     <%=page.toString() %>

  運行結果:

  咱們打開tomcat的work目錄(編譯生成的Servlet目錄)看到它的包結構是org.apache.jsp,在該目錄下有一系列的*_jsp.java和*_jsp.class文件。咱們打開page_jsp.java發現類名就是page_jsp。

  3.11pageContext對象

  • 提供了對JSP頁面內全部的對象及名字空間的訪問。
  • 能夠訪問到本頁所在的session,也能夠取本頁面所在的application的某一屬性值
  • 至關於頁面中全部功能的集大成者。
  • pageContext對象的本類名也叫pageContext。
  • 經常使用方法:
複製代碼
1 JspWriter getOut();                           // 返回當前客戶端響應被使用的JspWriter流(out)
2 HttpSession getSession();                     // 返回當前頁中的HttpSession對象(session)
3 Object getPage();                             // 返回當前頁面的Object對象(page)
4 ServletRequest getRequest();                  // 返回當前頁面的ServletRequest對象(request)
5 ServletResponse getResponse();                // 返回當前頁面的ServletResponse對象(response)
6 void setAttribute(String name,Object value);  // 設置屬性鍵值對
7 Object getAttribute(String name,int scope);   // 在指定範圍內取屬性值
8 void forward(String relativeUrlPath);         // 將當前頁面重定向到另外一頁面
9 void include(String relativeUrlPath);         //  在當前頁面包含另外一文件
複製代碼

  咱們在session_page1.jsp中向session中設置了用戶名:

<%
    session.setAttribute("username", "admin");
%>

  如今咱們在pageContext.jsp中取出session中存儲的用戶名(注意要先打開session_page1.jsp):

<h1>pageContext內置對象</h1>
    用戶名:<%=pageContext.getSession().getAttribute("username") %>

  運行結果:

  用pageContext實現頁面跳轉:

  <%
        pageContext.forward("reg.jsp");
  %>

  運行結果:

    新建一個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內置對象</h1>
2     用戶名:<%=pageContext.getSession().getAttribute("username") %><hr>
3     
4     <!-- 包含其餘頁面 -->
5     <%pageContext.include("include.jsp"); %>

  3.12config對象

      該對象是一個在servlet初始化時,jsp引擎向它傳遞信息時使用的,此信息包含Servlet初始化時所用到的參數(鍵-值對)以及服務器的相關信息(經過傳遞一個ServletContext對象),經常使用方法:

1 ServletContext getServletContext();  // 返回服務器相關信息的ServletContext對象
2 String getInitParameter(String name);// 返回初始化參數的值
3 Enumeration getInitParameterNames(); // 返回Servlet初始化時全部須要參數的枚舉

  3.13exception對象

    該對象是一個異常對象,若是一個頁面在運行過程當中出現了異常就會產生這個對象。若是一個JSP頁面須要應用此對象,就必須把isErrorPage設爲true——不然沒法編譯。它其實是java.lang.Throwable的對象,經常使用方法:

1 String getMessage();            // 返回異常的描述信息
2 String toString();              // 返回關於異常的簡短描述信息
3 void printStackTrace();         // 顯示異常及其棧軌跡
4 Throwable FillInStackTrace();   // 重寫異常的執行棧軌跡

  首先創建一個會出現異常的頁面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>這個頁面確定會出現異常</title>
 7   </head>
 8   
 9   <body>
10     <h1>測試異常對象</h1><hr />
11     <%
12            out.println(100/0);//確定會拋出運行時異常【算術異常】
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內置對象</h1>
    異常消息是:<%=exception.getMessage() %><br>
    異常的字符串描述:<%=exception.toString() %>
  </body>
</html>
複製代碼

  運行結果:

  

  3.14階段案例——實現用戶登陸

      這個案例比較簡單:用戶名和密碼都是admin(沒有使用數據庫),若是用戶名和密碼相符,則頁面跳轉到login_success.jsp【服務器內部轉發】,提示用戶登陸成功;若是用戶登陸失敗,則頁面跳轉到login_failure.jsp【請求重定向】,提示用戶登陸失敗。

  整個項目的截圖:

  項目地址:https://git.oschina.net/gaopengfei/JSPLogin.git

4.java beans

  JavaBean是使用Java語言開發的一個可重用的組件,在JSP的開發中可使用JavaBean減小重複的代碼,使整個JSP代碼的開發更加簡潔。JSP配置JavaBean使用有如下優勢:

   1. 將html和java大媽分離,爲往後的維護提供了方便。

   2. 能夠利用JavaBean的優勢將經常使用到的程序寫成JavaBean組件,節省開發時間。

 

簡單JavaBean有如下幾個名詞:

  VO:值對象,存放全部的傳遞數據的操做上

  POJO:簡單java對象

  TO:傳輸對象,必須實現Serializable接口

WEB開發的標準目錄結構

 

  實際上在WEB-INF中的libclasses目錄就至關於一個默認的classpath(類執行時所須要的一個重要的環境屬性)。當Tomcat啓動以後,WEB-INF/lib和WEB-INF/classes都會自動配置到classpath中。

  4.1java bean簡介與設計原則  

     Javabeans就是符合某種特定規範的的Java類。它的好處有:

   一個Javabean要知足4個規範:

  例如如下的學生類就是一個Javabean:

複製代碼
 1 /**
 2  * 這是一個典型的JavaBean
 3  */
 4 
 5 // 1.這是一個共有的類
 6 public class Student {
 7     // 2.屬性私有
 8     private String name;
 9     private int age;
10 
11     // 3.有共有的無參構造
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元素的語法——有一個元素名的開始標籤,能夠有屬性、可選的內容、與開始標籤匹配的結束標籤。

  

  4.3普通方式應用java bean

  像使用普通java類同樣,建立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>使用普通方式建立Javabean的實例</h1>
13        <%
14            //使用普通方式建立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>
複製代碼

  運行結果:

     

  4.4useBean動做元素

    <jsp:useBean>用於在jsp頁面中實例化或者在指定範圍內使用JavaBean。基本操做是首先使用id和做用域查找一個現有的對象,若是在指定的做用域中沒有找到具備指定id的對象,那麼它會試圖使用其餘屬性建立一個新實例。語法以下:

<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>使用&lt;jsp:useBean&gt;動做指令來使用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>
複製代碼

  運行結果:

  4.5setProperty

    上一個jsp頁面中取得的用戶名和密碼都爲null,緣由就是咱們使用僅僅是實例化了Users對象,並無爲其成員變量執行屬性。固然你也可使用setXXX來給已經實例化的JavaBean設置屬性,不過我更推薦使用setProperty指令。

    <jsp:setProperty>的主要做用就是給已經實例化的JavaBean的屬性賦值,一共有4種形式:

複製代碼
1 <jsp:setProperty name="JavaBean實例名" property="*" />                        <!-- 和表單關聯,所有屬性 -->
2 <jsp:setProperty name="JavaBean實例名" property="JavaBean屬性名" />                 <!-- 和表單關聯,指定屬性 -->
3 <jsp:setProperty name="JavaBean實例名" property="JavaBean屬性名" value = "BeanValue" />     <!-- 手工設置 -->
4 <jsp:setProperty name="JavaBean實例名" property="propertyName" param="request對象中的參數名"/>  <!-- 和request參數關聯,URL傳參 -->
複製代碼

   方式一:【表單內容的自動所有匹配】  

   新建一個用戶登陸表單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       <!-- 根據表單自動匹配全部的屬性並設置 -->
22     <jsp:setProperty property="*" name="myUsers"/>
23     用戶名:<%=myUsers.getUsername() %><br>
24     密碼:<%=myUsers.getPassword() %>      
25     
26   </body>
27 </html>
複製代碼

    運行結果:

    這實際上以依靠表單中的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     <!-- 根據表單匹配部分屬性 -->
22     <jsp:setProperty property="username" name="myUsers"/>
23     用戶名:<%=myUsers.getUsername() %><br>
24     密碼:<%=myUsers.getPassword() %>      
25     
26   </body>
27 </html>
複製代碼

    運行結果:

  僅僅匹配了用戶名屬性,因爲密碼屬性沒有匹配,因此爲null。這種方式也要注意表單的name屬性要和javabean的屬性相同。

  方式三:手工給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      <!-- 與表單無關,經過手工給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>
複製代碼

    運行結果:

  4.6getProperty

    <jsp:getProperty>獲取指定JavaBean對象的屬性值【String類型】。語法:

<jsp:getProperty name="JavaBean實例名" property="屬性名" />

    前面的例子已經經過URL傳遞參數的方式指定了javabean的屬性值,如今經過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>
複製代碼

  運行結果:

  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中有一個跳轉連接test_scope.jsp用於跳轉頁面,下面是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         <!-- 經過內置對象獲取javabean的屬性值 -->
20         <h2>經過內置對象獲取javabean的屬性值</h2>
21         用戶名:<%=((Users)application.getAttribute("myUsers")).getUsername() %><br>
22         密碼:<%=((Users)application.getAttribute("myUsers")).getPassword() %>      
23   </body>
24 </html>
複製代碼

  按照上面的例子分別將scope換成session、request和page獲得以下以下結果:javabean的做用域範圍從大到小依次是:application、session、request、page。

  4.8JavaBean的刪除

    JavaBean雖然使用了<jsp:useBean>標籤進行建立,可是其操做仍然依靠的是4種屬性範圍。若是一個JavaBean再也不使用的話,則可使用對應的removeAttribute()方法進行刪除。

1 pageContext.removeAttribute(JavaBean名稱)    // 刪除page範圍內的JavaBean
2 request.removeAttribute(JavaBean名稱)        // 刪除request範圍內的JavaBean
3 session.removeAttribute(JavaBean名稱)        // 刪除session範圍內的JavaBean
4 application.removeAttribute(JavaBean名稱)    // 刪除application範圍內的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實例產生了 ========");
 9     }
10 
11     public int getCount() {
12         return ++count;
13     }
14     
15 }
複製代碼
複製代碼
1 <%@ page language="java" contentType="text/html; charset=utf-8"%>
2 <!-- 建立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範圍內的JavaBean,刷新頁面不該該有新的JavaBean產生,可是咱們在最後使用了session.removeAttribute()方法將建立的JavaBean刪除了,於是每次請求都會產生新的JavaBean。

  4.9model 1(JSP+JavaBean)簡介

 

  Model 1模型出現之前,整個Web應用幾乎所有由JSP頁面組成,JSP頁面接收處理客戶端請求,對請求處理後直接響應。這樣作的一個弊端就是:在界面層(JSP頁面)中充斥着大量的業務邏輯代碼和數據訪問層的代碼,Web程序的可擴展性和可維護性很是差。
  JavaBean的出現可使得能夠在JSP頁面中調用JavaBean封裝的數據或者業務邏輯代碼,大大提高了程序的可維護性。下面的這張圖簡單描述了Model 1.

  模型一體現了一種Web應用的分層架構。

  4.9階段項目(使用Model 1完成用戶登陸)

      首先創建一個用戶類Users(javabean):

複製代碼
 1 package org.po;
 2 
 3 /**
 4  * 用戶類-javabean
 5  */
 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 }
複製代碼

    下面編寫一個用戶業務邏輯類:

複製代碼
 1 package org.dao;
 2 
 3 import org.po.Users;
 4 
 5 /**
 6  * 用戶的業務邏輯類
 7  */
 8 public class UsersDAO {
 9     public boolean isUserLogin(Users users) {
10         return "admin".equals(users.getUsername())
11                 && "admin".equals(users.getPassword());
12     }
13 }
複製代碼

  業務邏輯處理的頁面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 <!-- 引入業務邏輯類UsersDAO -->
 6 <jsp:useBean id="userDAO" class="org.dao.UsersDAO"></jsp:useBean>
 7 
 8 <!-- 爲javaBean loginUser設置屬性,使用表單自動設置所有的值 -->
 9 <jsp:setProperty property="*" name="loginUser"/>
10 
11 <!-- 調用業務邏輯代碼 -->
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         //請求轉發
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對象直接從表單中讀出數據,而是從javabean中取出屬性,而且用戶合法性的判斷也放在了javabean中很好的體現了Web的分層思想(邏輯與頁面分離)。

5.jsp狀態管理

  5.1http協議的無狀態性

    http的無狀態性是指:當瀏覽器發送請求給服務器的時候,服務器響應客戶端的請求。可是當瀏覽器再次發送請求給服務器的時候,服務器並不知道它就是剛剛的那個瀏覽器。——服務器不會記住你。爲了保存用戶的狀態有兩種機制:

  5.2Cookie

    Cookie是Web服務器保存在客戶端的一系列文本信息。

  • Cookie的典型應用一:判斷註冊用戶是否已經登陸網站。保存用戶的登陸狀態,簡化登陸的手續(記住密碼)。
  • Cookie的典型應用二:「購物車」的處理。
  • Cookie的典型應用三:視頻網站播放記錄的存儲。

    在JSP頁面中建立和使用Cookie    

1 Cookie newCookie = new Cookie(String key,Object value); // 建立Cookie對象
2 response.add(newCookie);                                // 寫入Cookie對象
3 Cookie[] cookies = request.getCookies();                // 讀取Cookie對象

    Cooike對象的經常使用方法:

1 void setMaxAge(int expiry); // 設置cookie的有效期【秒】
2 void setValue(String value);// 對已經實例化的cookie對象賦值
3 String getName();           // 得到cookie的名稱
4 String getValue();          // 得到cookie的值
5 int getMaxAge();            // 得到cookie的有效時間【秒】

    注意:以上方法中的setValue(String value)和String getValue()方法的返回值都是字符串類型——由於Cookie本質上就是一個字符串存儲在客戶端,不管對它存值仍是取值都應該是字符串類型。

  5.3案例:Cookie在登陸中的應用:

      實現記憶用戶名和密碼的功能。

      用戶登錄頁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         十天內記住我<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             //建立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             /*使已經保存的cookie對象失效*/
30             Cookie[]cookies = request.getCookies();//獲得客戶端保存的cookie
31             if(cookies!=null&&cookies.length>0){
32                 //遍歷Cookie數組
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網絡包中的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         十天內記住我<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             //獲得登陸表單中的內容並編碼
20             String username = URLEncoder.encode(
21                     request.getParameter("username"), "utf-8");
22             String password = URLEncoder.encode(
23                     request.getParameter("password"), "utf-8");
24             //建立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             /*使已經保存的cookie對象失效*/
35             Cookie[] cookies = request.getCookies();//獲得客戶端保存的cookie
36             if (cookies != null && cookies.length > 0) {
37                 //遍歷Cookie數組
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的區別是Cookie存放於瀏覽器中,瀏覽器關閉後再打開,已經保存的cookie仍是存在。

  5.4Session與Cookie對比

  Session Cookie
保存位置 服務端保存用戶信息 客戶端保存用戶信息
保存類型 Session中保存的是Object類型 Cookie中保存的是String類型
生命週期 會話結束,則存儲的數據銷燬 Cookie可長期保存在客戶端
重要性 保存重要信息 保存不重要信息

 

6.jsp指令【編譯時】與動做【運行時】元素 

  6.1include指令(能夠包含其餘頁面)

    語法:

<%@ include file="URL"%>

    例如咱們要在include_command.jsp中包含date.jsp的頁面——即:在include_command中顯示date.jsp的內容:

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>
複製代碼

    運行結果:

  6.2include動做

    include動做其實是JSP動做標籤,語法:

<jsp:include page="URL" flush="true|false" />

  其中page屬性是須要包含的頁面的URL,而flush屬性制定了被包含的頁面是否從緩衝區中讀取。

  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頁面的執行效果上沒有任何區別。

  6.3include指令與include動做的區別

    在Tomcat服務器的work目錄中刪除剛剛發佈的工程:

    先訪問include_command.jsp

    work目錄生成如下內容:

  打開include_005fcommand_jsp.java發如今它的源代碼中有date.jsp的源代碼:

out.print(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));

  include指令主頁面和被包含的頁面轉換成了同一個Servlet。

  在Tomcat的work目錄中刪除編譯生成的Servlet,訪問include_action.jsp生成如下文件:

  打開include_005faction_jsp.java發現源代碼中並無包含date.jsp的源代碼,而是由下面的一條代碼將date.jsp的輸出結果包含到該jsp頁面:

// 該語句至關於調用date.jsp,並將date.jsp的輸出結果返回給該頁面
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "date.jsp", out, false);

  6.4forward動做

    服務器內部轉發指令,語法:

1 <jsp:forward page="URL" />
2 
3 // 至關於
4 request.getRequestDispatcher("url").forward(request,response);

    例如:在登錄頁中將用戶的表單處理交給forward_action.jsp頁面處理,forward_action.jsp將該請求經過forward動做轉發給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>
複製代碼

    運行結果:

  6.5param動做

   語法:

1 <jsp:param name="參數名" value="參數名" />
2 <!-- 該動做經常做爲<jsp:forward>的子標籤,和它一塊兒使用 -->

  用戶將提交的表單交給dologin.jsp處理,dologin.jsp經過forward動做把請求轉發給users.jsp(並人爲添加表單中沒有的內容:郵箱,修改表單中提交的用戶名爲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案例項目——商品瀏覽記錄的實現

    該項目使用Model1(JSP+JavaBean)使用Cookie機制實現。該項目使用到了數據庫(數據庫中存放了商品表)。實現步驟以下:

  DB-->JavaBean-->JSP。項目的目錄結構:

1、實現DBHelper類:

 該類的主要做用是取得數據庫的鏈接並關閉相關資源。

複製代碼
 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     /** 靜態代碼塊加載DB驅動 */
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     /** 清理資源-關閉DB結果集、釋放語句對象 */
36     public static void relsaseResource(ResultSet rs,PreparedStatement pstmt){
37         // 釋放結果集
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("數據庫鏈接成功!");    
63             }else {
64                 System.out.println("數據庫鏈接異常!");
65             }
66         } catch (SQLException e) {
67             e.printStackTrace();
68         }
69     }
70 }
複製代碼
若是shopping數據庫沒有建立可能會拋出異常只須要執行:
 create database shopping;

  2、商品實體類的設計:

  在建立實體類以前先創建好數據庫表:

  數據庫腳本:items.sql

複製代碼
 1 /*
 2 Navicat MySQL Data Transfer
 3 
 4 Source Server         : MySQL50
 5 Source Server Version : 50067
 6 Source Host           : localhost:3306
 7 Source Database       : shopping
 8 
 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 }
複製代碼

    3、實現業務邏輯類(數據訪問層DAO)

    該類須要完成的功能:

    分析:

    1.在index.jsp中咱們須要展現全部的商品信息。——得到全部商品

    2.當用戶點擊任意一種商品後會將id經過URL傳遞給details.jsp,而在details.jsp中咱們須要——根據id得到對應商品。 

    3.根據Cookie傳入的字符串得到最近瀏覽的5條記錄。

思考:如何將瀏覽記錄保存在Cookie中?

 

 

 

回答:只須要保存商品的ID便可,由於每一個商品的ID是惟一的。

 

 

 

實現:把每次瀏覽的商品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>歡迎光臨網上商城</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                     <!-- 商品循環開始 -->
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">產地:<%=item.getCity() %>&nbsp;&nbsp;價格:¥<%=item.getPrice() %></dd>
56                                     </dl>
57                                 </div>
58                      <%
59                             }
60                           }
61                        %>
62                        <!-- 商品循環結束 -->
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 <!-- 顯示商品詳情,並在右側顯示商品的瀏覽記錄(最近5條記錄) -->
  5 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  6 <html>
  7   <head>
  8     <title>歡迎光臨網上商城</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_name
 22        {
 23           color:blue;
 24        }
 25        div dd.dd_city
 26        {
 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>產地:<%=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條,則清空Cookie
 78                            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                     <!-- 循環開始 -->
 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">產地:<%=i.getCity() %>&nbsp;&nbsp;價格:¥<%=i.getPrice() %></dd>
101                                 </dl>
102                             </div>
103                     <%
104                             }
105                         }
106                      %>
107                     <!-- 循環結束 -->
108                 </td>
109               </tr>
110           </table>
111       </center>
112   </body>
113 </html>
複製代碼

  主業務邏輯類ItemsDAO

  View Code

  項目展現:(項目地址:https://git.oschina.net/gaopengfei/JSPLogin.git

Tips:

  解決中文亂碼:

1)在執行獲取請求參數前設置編碼:

request.setCharacterEncoding(「漢字編碼」);

2)轉換字符編碼:

1   //獲取原始的請求參數值
2     String rawName = request.getParameter("name");
3     //將請求參數值使用ISO-8859-1字符串分解成字節數組
4     byte[] rawBytes = rawName.getBytes("ISO-8859-1");
5    //將字節數組從新編碼成字符串
6    String name = new String(rawBytes , "gb2312");

3)獲取請求參數同時轉換編碼:

request.getParameter(「name」).getBytes ("ISO-8859-1");
相關文章
相關標籤/搜索