jsp和EL表示式
一、Jsp
1、Jsp (Java Server Pages),它和 Servlet 技術一樣,都是 SUN 公司定義的一種用於開發動態 Web 資源的技術。
Jsp 技術允許在頁面中巢狀 Java 程式碼,並且允許開發人員在頁面中獲取 request、response 等 Web 常用物件。實現伺服器與瀏覽器之間的互動,所以 Jsp 也是一種動態 Web 資源的開發技術。
2、Jsp 的執行過程。當用戶第一次訪問一個 Jsp 頁面時,伺服器會將 Jsp 的內容翻譯為一個 Servlet,然後將位元組碼和原始檔存放在伺服器 work 目錄的主機目錄下。伺服器通過 Servlet 將 Jsp 頁面的內容通過 out 物件輸出到客戶機的瀏覽器中。當 Jsp 內嵌了 Java 程式碼時,伺服器會原封不動的將 Java 程式碼交給 Servlet 執行。如果伺服器中已經存在了編譯好的 Servlet 位元組碼,那麼使用者再訪問 Jsp 的時候,其實不是訪問的 Jsp 而是直接訪問 Servlet。
3、Jsp 的九大隱式物件:
(1) request:封裝了使用者提交資訊 ---(使用者請求期 Request)
(2) pageContext:封裝了其它所有物件。--- (頁面執行期 Page)
(3) session:在使用者首次訪問時獲得。是一個 Jsp 的內建域物件。--- (整個會話期 Session)
(4) application:伺服器啟動時建立的 ServletContext 物件。也就是一個 Web 應用。--- (整個應用執行期 Application)
(5) out:向客戶機輸出資料的流物件。用於各種資料的輸出。內部是一個 JspWriter,預設快取大小為 8kb。--- (頁面執行期 Page)
(6) config:配置 Servlet ,該物件用於存取servlet例項的初始化引數。。--- (頁面執行期 Page)
(7) page:指當前 Jsp 頁面,等同於 Servlet 中的 this 關鍵字,表示從該頁面產生的一個servlet例項。。--- (頁面執行期 Page)
(8) response:對客戶的請求做出動態響應,向客戶傳送資料。 --- (頁面執行期 Page)
(9) exception:異常。。--- (頁面執行期 Page)
4、Jsp 最佳實踐
Servlet 只負責響應請求產生資料,並把資料通過轉發技術帶給 Jsp,Jsp 只用作資料的顯示。
二、Jsp 語法
1、Jsp 模版元素。Jsp 頁面中的 HTML 內容稱為 Jsp 模版元素。Jsp 模版元素定義了網頁的基本骨架,即定義了頁面的結構和外觀。
2、Jsp 指令碼表示式。<%= 表示式%>。當前時間:<%= new Date().toLocalString()%>。
3、Jsp 指令碼片段。用於在頁面內加入多行 Java 程式碼。 <% Java 程式碼 %>
4、Jsp 宣告。Jsp 頁面中所編寫的程式碼會預設的翻譯到 Servlet 中的 service 中,而 Jsp 宣告中的 Java 程式碼被翻譯到 _jspService 方法的外面。即定義了 Servlet 的全域性變數、方法、靜態程式碼塊。由於 Jsp 的隱式物件是在 service 方法中生命的,所以在 Jsp 宣告中定義的成員不能訪問。
5、Jsp 指令。Jsp 指令是為伺服器而設計的,它們並不直接產生任何可見輸出,而是告訴伺服器如何處理 Jsp 頁面中的其餘部分。
<%@ 指令 屬性名="值" %> 例如:<%@ contextType="text/html charset=gb2312" %>
(1) page 指令。page 指令用於定義 Jsp 頁面的各種屬性,無論 page 指令出現在 Jsp 頁面中的什麼位置,它作用的都是 Jsp 頁面。
<%@ page
[language="java"] //用於指定當前頁面內嵌的是 Java 程式碼。
[extends="package.class"] //用於指定翻譯後的 Servlet 繼承哪個類。
[import="java.io.*"] //用於匯入 Java 程式碼所需要的包,所個之間用" , "號分割,也可以分開寫。
[session="true | false"] //指定翻譯後的 Servlet 是否自動建立 Session 物件,預設值為 true。我們常常要置為 false。因為 Session 有效期較長,所以我們不需要 Session 物件的時候就不要建立,以減輕伺服器壓力。
[buffer="none | 8kb | sizekb"] //用於指定 out 物件的傳衝區大小,也就是 JspWriter 的緩衝區大小,預設為 8kb。
[autoFlush="true | false"] //指定上面 buffer 緩衝區是否自動重新整理,預設為 true。
[isThreadSage="true | false"] //預設值為 true,採用繼承 SingleThreadModel 標記介面的方式實現。
[info="text"] //指定當前頁面資訊為文字。
[errorPage="error.index"] //指定錯誤資訊頁面,其中指定 URL 的目錄必須使用相對路徑,如果以 "/" 開頭,那麼表示相對於當前 Web 應用程式的根目錄,不是站點的根目錄。設定錯誤頁面的另一種方式:在 web.xml 配置檔案中,<web-app> 元素下加入子元素:
<exception-type>異常型別全限定名</excetion-type> 或者 <error-code>錯誤號</error-code>
<location>錯誤資訊顯示頁面</location> 注意,錯誤頁面的大小必須超過 1kb 才能正常顯示。如果在 web.xml 檔案中配置了錯誤資訊頁面,那麼在 Jsp 中設定的 errorPage 指令將不起作用。傳遞錯誤資訊就是用到了 exception 隱式物件。
[isErrorPage="true | false"] //指定這個頁面是否為錯裡處理頁面,如果是的話最好改為 true。
[contentType] //指定頁面的 MIME 型別,說明頁面是什麼頁面,頁面採用什麼編碼方式。其中 charset 用於說明 Jsp 原始檔字元編碼集。是指傳送給客戶機的時候採用什麼編碼方式。
[pageEncoding="characterset | ISO-8859-1"] // 用於指定當前 Jsp 檔案的編碼方式,是檔案本身的編碼方式。
[isELIgnored="true | false"] // 指定頁面是否忽略 EL 表示式,預設值為 false。
(2) include 指令:用於引入其它 Jsp 頁面,如果使用 include 指令引入了其它 Jsp 頁面,那麼 Jsp 伺服器將把這兩個 Jsp 翻譯成一個 Servlet,所以 include 指令引入通常稱為靜態引入。
<%@ include file="url" %> 其中如果 URL 的路徑以 "/" 開頭則表示當前的 Web 應用。Jsp 的規範中建議被引入的頁面字尾名是 .jspf。由於靜態引入是將兩個 Jsp 編譯成一個 Servlet 來打給客戶機的,所以兩個被引入的 Jsp 頁面指令不能衝突。並且被引入的 Jsp 頁面不要出現 Jsp 模版元素,也就是 HTML 的標籤,否則 HTML 的標籤內容會被打給客戶機,造成程式碼不優雅。
動態引入:利用 request 物件的 getRequestDispatcher("URL").include(request,response); 方法。原理:是在 Servlet 執行時動態的將其它的 Servlet 加入到頁面中,要多次向伺服器請求,所以效率要低。我們在開發中要儘量使用靜態引入的方法。靜態引入是將多個 Servlet 集合成一個 Servlet 後再打給客戶機。
三、Jsp 亂碼問題分析
Jsp 亂碼出現的原因:我們在編輯 Jsp 的時候,由於編輯器不同,所儲存的 Jsp 原始檔指定的編碼方式也不同,如果我們用記事本編輯 Jsp ,那麼 Jsp 的原始檔編碼方式為 gb2312 儲存到了我們硬碟上。當用戶訪問伺服器的時候,伺服器通過硬碟上編輯好的 Jsp 檔案翻譯為 Servlet ,由於伺服器不是中國人設計的,所以經常採用 ISO-8859-1 的編碼方式,由於 ISO-8859-1 碼錶中沒有對應的中文字元,所以不能正常編譯資料,然後編譯成的 .class 檔案也是亂碼,也就導致了發給客戶機的資料也不能正常顯示。
解決方案:既然我們找到了亂碼的原因,那麼我們應當控制伺服器將 Jsp 原始檔編譯成 Servlet 時採用可以編譯中文的碼錶。所以編輯原始檔的編碼方式應該與伺服器編譯 Jsp 的編碼方式相一致。那麼我們可以在 page 指令中增加 pageEncoding="utf-8" ,告訴伺服器以 utf-8 的碼錶編碼。由於最新的伺服器會自動的將設定好的編碼方式以響應頭的形式寫給客戶機,所以就沒有必要再加入 contentType="text/html;charset=utf-8" 這個 page 指令,但是為了相容老的伺服器,謹慎起見加入也可以。
四、Out 隱式物件
1、out 隱式物件用於向客戶端傳送文字資料。out 物件是通過呼叫 pageContext 物件的 getOut() 方法返回的,其作用和用法與 ServletResponse.getWriter() 方法返回的 PrintWriter 物件非常相似。
2、Jsp 頁面中的 out 隱式物件的型別為 JspWriter,JspWriter 相當於一種帶快取功能的 PriterWriter,設定 Jsp 頁面的 page 指令的 buffer 屬性可以調整它的快取大小,甚至關閉快取。
3、當向 out 中寫入了資料,那麼該資料什麼時候才會寫給客戶機的瀏覽器?
(1) 設定 page 指令的 buffer 屬性關閉了 out 物件的快取功能,那麼一旦寫入到了 out 物件中,out 就直接送給 printWriter 物件的緩衝區中。
(2) out 物件的緩衝區已滿。
(3) 整個 Jsp 頁面結束。
4、out 緩衝區工作原理:
將資料寫入 out 中,並不是直接寫給客戶機,先寫在了 out 的緩衝區中。同樣,在 Servlet 的 PrintWriter 中寫資料是寫在 PrintWriter 的緩衝區中,當 out 的緩衝區滿了,或者 Jsp 頁面執行完畢時,伺服器會將 out 緩衝區中的資料寫到 PrintWriter 的緩衝區中,然後在寫給客戶機。所以如果既在 PrintWriter 中寫資料,又在 out 中寫資料,那麼無論寫入的先後順序,最後打給客戶機時,總是 PrintWriter 的資料先送給客戶機。out 物件就是對 PrintWriter 的再一次緩衝。我們在寫 Jsp 頁面的時候儘量使用 out 物件輸出資料。
五、Jsp 實現檔案下載
[java] view plaincopyprint?- <%@ page language="java"import="java.util.*" pageEncoding="utf-8"%><%@pageimport="java.io.FileInputStream"%><%@pageimport="java.io.OutputStream"%>
- <%@pageimport="java.net.URLEncoder"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%
- String path = application.getRealPath("download/圖片.jpg");
- String filename = path.substring(path.lastIndexOf("\\") + 1);
- FileInputStream in = new FileInputStream(path);
- int len = 0;
- byte[] b = newbyte[1024];
- OutputStream os = response.getOutputStream();
- response.setHeader("content-disposition","attachment;filename=" + URLEncoder.encode(filename,"utf-8"));
- while((len = in.read(b)) != -1){
- os.write(b, 0 ,len);
- }
- in.close();
- %>
六、pageContext 物件
pageContext 物件是 Jsp 技術中最重要的一個物件,它代表 Jsp 頁面的執行環境。pageContext 不僅封裝了其它 8 大隱式物件,它自身還是一個域物件,可以用來儲存資料。並且這個物件還封裝了 Web 開發中經常設計到的一些常用操作,例如引入和跳轉其它資源,檢索其它域物件中的屬性等。
1、pageContext 封裝其它8大物件的意義。用於自定義標籤,在真實的軟體工程專案裡面,Jsp 頁面是嚴禁出現一行 Java 程式碼的,如果要使用 Java 程式碼,我們必須使用自定義標籤把它封裝掉,然後用一個 Java 類對邏輯資料進行處理,那麼其它 Java 類是沒有該請求的資料的,我們必須傳 request 過去,這樣是很麻煩的。我們可以使用 pageContext 域來獲取其它物件,也就是傳遞 pageContext 一個物件過去就可以了。
2、pageContext 物件的生命週期和作用範圍。pageContext 的生命週期與頁面是相應的,頁面被建立後 pageContext 也就被建立,頁面關閉,pageContext 也就隨之摧毀。它的作用範圍也是在當前的頁面範圍之內。
3、pageContext 操作其他域。getAttribuate(String name) 方法有一個過載,第一個形式是預設從當前的 pageContext 中檢索資料,第二個 getAttribuate(String name,int SCOPE ) 是從指定的域裡面獲取資料。
pageContext 域提供了統一操作四個域的入口,以前如果要取出資料,必須指定從哪裡取,現在可以統一的從 pageContext 中取出資料。其中 PAGE_SCOPE 常量表示的是 pageContext 域,而不是當前頁面 page。
* pageContext.findAttribuate(""); 首先從 pageContext 域中查詢,如果找不到,就從 request 域中找,找不到,就從 session 域中找,找不到就從 application 中找,如果還是找不到就返回 null。page域--->request--->session--->application。
pageContext 還可以做轉發、包含等操作。(forward、include)
七、Jsp 簡單標籤
Jsp 標籤也稱為 Jas Action(Jsp 動作元素),它用於在 Jsp 頁面中提供業務邏輯功能,避免在 Jsp 頁面中直接編寫 Java 程式碼,造成 Jsp 頁面難以維護。
1、SUN 公司提供的 Jsp 常用標籤
<jsp:include>
<jsp:forward>
<jsp:param>
2、對映 Jsp。因為 Jsp 本身就是一個 Servlet,所以我們可以使用對映 Servlet 的方式把 Jsp 對映到另外一個地址上去。
<servlet>
<servlet-name>servletDemo</servlet-name>
<jsp-file>/index.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo</servlet-name>
<url-pattern>/xxx.jsp</url-pattern>
<serlvet-mapping>
八、Jsp 操作 JavaBean 標籤
Jsp 技術提供了三個關於 JavaBean 標籤元素
1、<jsp:useBean>:用於在 Jsp 頁面中查詢或例項化一個 JavaBean 元件。
2、<jsp:setProperty>:用於在 Jsp 頁面中設定一個 JavaBean 元件的屬性。
3、<jsp:getProperty>:用於在 Jsp 頁面中獲取一個 JavaBean 元件的屬性。
<jsp:useBean>:在指定的域範圍內查詢制定名稱的 JavaBean 物件,如果存在則直接返回該物件的引用,如果不存在則例項化一個新的 JavaBean 物件並將它以指定的名稱儲存到指定的域範圍中。
注意:在用 setProperty 為 JavaBean 賦值的時候,JavaBean 標籤只支援8種基本資料型別的自動型別轉換,其它型別不能自動轉換。
九、Jsp 開發模式
Jsp 有兩種開發模式,一種是 Jsp + JavaBean 模式,一種是 Jsp + Servlet +JavaBean 模式。Jsp + JavaBean 適合開發業務邏輯不復雜的 Web 應用程式,這種模式下,JavaBean 用於封裝業務資料,Jsp 負責處理使用者請求又顯示資料。Jsp + Servlet +JavaBean (MVC Model/View/Control)模式適合開發複雜的 Web 應用,在這種模式下, Servlet 負責處理使用者請求,Jsp 負責資料顯示,JavaBean 負責封裝資料。
簡單的 Jsp + JavaBean 模式案例
[java] view plaincopyprint?- <%@ page language="java"import="java.util.*" pageEncoding="utf-8"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>計算器</title>
- </head>
- <jsp:useBean id="calc"class="bean.Calculator" scope="session"/>
- <jsp:setProperty property="*" name="calc" />
- <%
- calc.operate();
- %>
- <body>
- <hr width="30%">
- <div align="center">
- 計算結果是:<jsp:getProperty property="firstNum" name="calc"/>
- <jsp:getProperty property="operator" name="calc"/>
- <jsp:getProperty property="secondNum" name="calc"/>=
- <jsp:getProperty property="result" name="calc"/>
- </div>
- <hr width="30%"><br><br>
- <form action="/Day_07_Jsp_EL/calculator.jsp" method="post">
- <table width="30%" border="1" align="center">
- <tr>
- <td colspan="2">簡單的計算器</td>
- </tr>
- <tr>
- <td>第一個引數:</td>
- <td><input type="text" name="firstNum"/></td>
- </tr>
- <tr>
- <td>運算子:</td>
- <td>
- <select name="operator">
- <option value="+">+</option>
- <option value="-">-</option>
- <option value="*">*</option>
- <option value="/">/</option>
- </select>
- </td>
- </tr>
- <tr>
- <td>第二個引數:</td>
- <td><input type="text" name="secondNum"/></td>
- </tr>
- <tr>
- <td colspan="2">
- <input type="submit" value="提交"/>