11. JSP(我的JavaEE筆記)

1.什么是JSP

(1)jsp全稱是Java Server Pages,它和Servlet技術(shù)一樣都是sun公司定義的一種用于開發(fā)動(dòng)態(tài)web資源的技術(shù)。
(2)jsp這門技術(shù)的最大的特點(diǎn)在于,寫jsp就像在寫html,但它相比html而言,html只能為用戶提供靜態(tài)數(shù)據(jù),而jsp技術(shù)允許在頁面中嵌套java代碼,為用戶提供動(dòng)態(tài)數(shù)據(jù)。

2. jsp原理

其原理就是jsp引擎將jsp文件翻譯成一個(gè)servlet,而其中的java代碼將原封不動(dòng)的復(fù)制到新的servlet中。其執(zhí)行起來也和servlet一樣。

3. jsp的最佳實(shí)踐

不管是jsp還是servlet,雖然都可以用于開發(fā)動(dòng)態(tài)web資源。但由于這兩門技術(shù)各自的特點(diǎn),在長期的軟件實(shí)踐中,人們逐漸把servlet作為web應(yīng)用中的控制組件來使用,而把jsp技術(shù)作為數(shù)據(jù)顯示模板來使用。

其原因是,程序的數(shù)據(jù)通常要美化后再輸出
(1)讓jsp即用java代碼產(chǎn)生動(dòng)態(tài)數(shù)據(jù),又做美化會(huì)導(dǎo)致頁面難以維護(hù)。
(2)讓servlet即產(chǎn)生數(shù)據(jù),又在里面嵌套html代碼美化數(shù)據(jù),同樣也會(huì)導(dǎo)致程序可讀性差,難以維護(hù)。

4. jsp語法

(1)jsp模板元素

Jsp頁面中的html內(nèi)容稱之為jsp模板元素。Jsp模板元素定義了網(wǎng)頁的基本骨架,即定義了頁面的結(jié)構(gòu)和外觀。

(2)jsp腳本表達(dá)式

Jsp腳本表達(dá)式用于將程序數(shù)據(jù)輸出到客戶端:
語法:<%=x%>
舉例:當(dāng)前時(shí)間:<%=new java.util.Date()%>

Jsp引擎在翻譯腳本表達(dá)式時(shí),會(huì)將程序數(shù)據(jù)轉(zhuǎn)成字符串,然后在相應(yīng)位置用out.print(...)將數(shù)據(jù)輸出給客戶端。

注意:jsp腳本表達(dá)式中的變量或表達(dá)式后面一定不能有分號(hào)!

(3)jsp腳本片斷

Jsp腳本片斷用于在jsp頁面中編寫多行java代碼。
語法:

<%
    多行java代碼
%>

注意:jsp腳本片斷只能出現(xiàn)java代碼,不能出現(xiàn)其它模板元素,jsp引擎在翻譯jsp頁面中,會(huì)將jsp腳本片斷中的java代碼將被原封不動(dòng)地放到servlet中的_jspServlet方法中。Jsp腳本片斷中的java代碼必須嚴(yán)格遵循java代碼,例如,每執(zhí)行語句后面必須用分號(hào)結(jié)束。

在一個(gè)jsp頁面中可以有多個(gè)腳本片斷,在兩個(gè)或多個(gè)腳本片斷之間可以嵌入文本、html標(biāo)記和其他jsp元素。多個(gè)腳本片斷的代碼可以相互訪問,就像將所有的代碼放在一對(duì)<%%>之中的情況。

單個(gè)腳本片斷中的java語句可以是不完整的,但是,多個(gè)腳本片斷組合后的結(jié)果必須是完整的java語句,例如:

<%
    for(int i = 0; i < 5; i++)
    {
%>
    <H1>www.itcast.org</H1>
<%
    }
%>

(4)jsp聲明

Jsp頁面中編寫的所有代碼,默認(rèn)會(huì)翻譯到servlet的service方法中,而jsp聲明中的java代碼會(huì)被翻譯到 _jspService 方法的外面。語法:

<%!
    Java代碼
%>

所以,jsp聲明可以用于定義jsp頁面轉(zhuǎn)換成的servlet程序的靜態(tài)代碼塊、成員變量和方法。多個(gè)靜態(tài)代碼塊、變量和函數(shù)可以定義在一個(gè)jsp聲明中,也可以分別單獨(dú)定義在多個(gè)jsp聲明中。Jsp隱式對(duì)象的作用范圍僅限于servlet的 _jspServeice 方法,所以在jsp聲明中不能使用這些隱式對(duì)象。

注意:不能在jsp中定義名字為 jspInit 或 jspDestroy 的方法,這樣在將jsp翻譯成servlet時(shí)會(huì)將原帶的相關(guān)方法覆蓋掉。

(5)jsp注釋

Jsp中使用<%--注釋信息--%>格式添加注釋,但是注意:這個(gè)和html頁面中的****不同的是,jsp中的注釋信息不會(huì)被翻譯到servlet中,這樣就不會(huì)被顯示在頁面上,但是html中的注釋是會(huì)被發(fā)送到瀏覽器中的。

5. jsp指令

(1)Jsp指令是為jsp引擎而設(shè)計(jì)的,它們并不直接產(chǎn)生任何可見輸出,而只是告訴引擎如何處理jsp頁面中的其余部分。一共有三個(gè)指令:page指令、include指令、taglib指令。這里只講前兩個(gè),最后一個(gè)是用于自定義標(biāo)簽上的,以后會(huì)講。

(2)jsp指令簡介

Jsp指令的基本語法格式:

<%@ 指令 屬性值="值"%>

例如:

<%@ page contentType="text/html;charset=gb2312"%>

如果一個(gè)指令有多個(gè)屬性,可以寫在一個(gè)指令中,也可以分開寫。如:

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.util.Date"%>

也可以寫成:

<%@ page contentType="text/html;charset=gb2312" import="java.util.Date"%>

(3)page指令

  1. page指令用于定義jsp頁面的各種屬性,無論page指令出現(xiàn)在jsp頁面中的什么地方,它作用的都是整個(gè)jsp頁面,為了保持程序的可讀性和遵循良好的編程習(xí)慣,page指令最好放在整個(gè)jsp頁面的起始位置。
2. jsp2.0規(guī)范中定義的page指令完整語法:

language="java" 指定嵌入的語言

extends="package.class" 指明編譯該jsp文件時(shí)繼承哪個(gè)類。Jsp為servlet,因此當(dāng)指明繼承普通類時(shí)需要實(shí)現(xiàn)的servlet的init、destroy等方法。

Import="java.servlet.http" 指明需要導(dǎo)入的包,可以在一條指令的import屬性中引入多個(gè)類或包,使用逗號(hào)分隔。也可以分開使用指令寫。其中java.lang包,java.servlet包不需要導(dǎo)入。

session="true|false" 指明生成(true)或不生成(false)session,默認(rèn)是生成,但是一般我們會(huì)將其置為false。

buffer="none|8kb|sizekb" 指明緩存的大小,設(shè)為none表明無緩存,默認(rèn)是8kb緩存,可以自己設(shè)置大小,比如64kb。但是必須在autoFlush設(shè)為true時(shí)有效。

autoFlush="true|false" 是否運(yùn)行緩存。默認(rèn)為true(運(yùn)行緩存)。

isThreadSafe="true|false" 指定是否線程安全。默認(rèn)是false(非線程安全)。

info="text" 指明jsp的信息。該信息可以通過Servlet.getServletInfo()方法取到。

errorPage="relative_url" 指定某個(gè)jsp頁面的相對(duì)路徑。用于指明一個(gè)錯(cuò)誤顯示頁面,然后我們?cè)诖隧撁媾龅较嚓P(guān)的異常時(shí)進(jìn)行跳轉(zhuǎn)。此屬性指定的頁面通常isErrorPage屬性為true,且內(nèi)置的exception對(duì)象為未捕捉的異常。注意:必須使用相對(duì)路徑,如果以“/”斜杠開頭,表示相對(duì)于當(dāng)前web應(yīng)用程序的根目錄(注意:不是站點(diǎn)根目錄),否則表示相對(duì)于當(dāng)前頁面。當(dāng)然有時(shí)候我們的錯(cuò)誤顯示頁面會(huì)有很多,所以我們一般在web.xml文件中使用<error-page>元素為整個(gè)web應(yīng)用程序設(shè)置錯(cuò)誤處理頁面,其中的<exception-type>子元素指定異常類的完全限定名(java.lang.NoFoundException),而<error-code>指定出現(xiàn)什么錯(cuò)誤,** <location>**元素指定以”/”開頭的錯(cuò)誤處理頁面的路徑。如果設(shè)置了某個(gè)jsp頁面的errorPage屬性,那么在web.xml文件中設(shè)置的錯(cuò)誤處理將不對(duì)該頁面起作用。例如一般我們會(huì)將所有的錯(cuò)誤頁面放在一個(gè)文件夾中,如下面的errors:

<error-page>
    <error-code>500</error-code>
    <location>/errors/500.jsp</location>
</error-page>

注意:在錯(cuò)誤顯示頁面中輸出的錯(cuò)誤信息一定要大于1kb,不然瀏覽器不會(huì)顯示出來。

isErrorPage="true|false" 指定該頁面是否為錯(cuò)誤處理頁面,如果為true,則該jsp內(nèi)置有一個(gè)Exception對(duì)象exception,可直接使用,否則沒有。默認(rèn)為false。注意:jsp中有九大隱式對(duì)象,其中有八個(gè)是默認(rèn)會(huì)生成的。但是如果我們沒有將此屬性設(shè)置為true,那么exception隱式對(duì)象將看不到,可以通過exception.getCause()方法得到此隱式對(duì)象。

contentType="text/html;charset=UTF-8" 指明有效的文檔類型。如html格式為text/html;純文本格式為text/plain;JPG圖像為image/jpeg;GIF圖像為image/gif。Jsp引擎會(huì)根據(jù)page指令的此屬性生成相應(yīng)的調(diào)用ServletResponse.setContentType方法的語句。還具有說明jsp源文件的字符編碼的作用。

pageEncoding="characterSet|ISO8859-1" 指定jsp引擎使用哪張碼表。

isELIgnored="true|false" 指明是否支持EL表達(dá)式。true為不支持。一般都需要設(shè)置為false。

注意:默認(rèn)是有緩存的,這就是jsp中的out.write()方法和Servlet中的write方法的區(qū)別,當(dāng)我們?cè)趈sp中有如下內(nèi)容:

out.write(“aaa”);
response.getWriter().write(“bbb”);

時(shí)bbb會(huì)先輸出,因?yàn)閍aa會(huì)先存在out對(duì)象的緩沖區(qū)中,當(dāng)滿足一些條件時(shí)才能將此緩沖區(qū)中的內(nèi)容寫到servlet的緩沖區(qū),這樣才能輸出。而response.getWriter().write(“bbb”);會(huì)直接將bbb存在servlet的緩沖區(qū)中,于是可以直接輸出。

使用page指令解決jsp中文亂碼問題(在tomcat5.0中存在,高版本不存在了,同時(shí)在MyEclipse中也不存在此問題)
(1)jsp程序存在有與Servlet程序完全相同的中文亂碼問題

輸出響應(yīng)正文時(shí)出現(xiàn)的中文亂碼問題
讀取瀏覽器傳遞的參數(shù)信息時(shí)出現(xiàn)中文亂碼問題。

(2)jsp引擎將jsp頁面翻譯成Servlet源文件時(shí)也可能導(dǎo)致中文亂碼問題

Jsp引擎將jsp源文件翻譯成Servlet源文件默認(rèn)采用UTF-8編碼,而jsp開發(fā)人員可以采用各種字符集編碼來編寫jsp源文件,這樣就會(huì)造成亂碼。如果jsp文件中沒有說明它采用的字符集編碼,jsp引擎將把它當(dāng)作默認(rèn)的ISO8859-1字符集編碼處理。

亂碼產(chǎn)生過程:
在tomcat5.0中,若我們使用記事本編寫jsp程序,若jsp程序中有漢字,此時(shí)在中文環(huán)境下會(huì)使用gb2312保存,但是在將其翻譯成Servlet程序時(shí)會(huì),jsp引擎會(huì)使用ISO8859-1進(jìn)行翻譯,這時(shí)就會(huì)出現(xiàn)亂碼,如果我們?cè)赟ervlet中不對(duì)編碼作任何設(shè)置,那么Response對(duì)象也將會(huì)使用ISO8859-1將亂碼顯示在瀏覽器中,而此時(shí)瀏覽器會(huì)使用ISO8859-1進(jìn)行顯示,這樣我們看到的就是亂碼,但是如果我們?cè)跒g覽器中選擇使用bg2312顯示還是可以將亂碼轉(zhuǎn)換成正確的漢字。但是如果我們?cè)赟ervlet中對(duì)編碼進(jìn)行設(shè)置,只要設(shè)置的不是ISO8859-1,那么我們?cè)跒g覽器中就不能將亂碼還原成正確的漢字了,即使我們最好使用bg2312進(jìn)行顯示。但是我們不能讓用戶每次都這樣選擇,所以我們使用pageEncoding進(jìn)行設(shè)置,比如設(shè)置為UTF-8,這樣就改變了引擎將jsp程序翻譯成Servlet時(shí)使用的碼表。但是如果是使用記事本寫的jsp程序,還是會(huì)出現(xiàn)亂碼,因?yàn)橛浭卤驹谥形沫h(huán)境下是使用gb2312保存的,這里我們需要手工改變保存時(shí)使用的碼表。但是在MyEclipse中不需要,它會(huì)根據(jù)pageEncoding設(shè)置的碼表保存相關(guān)的jsp程序。

注意:tomcat5.0中還有一個(gè)問題是,在高版本的tomcat中會(huì)將webapps中的工程自動(dòng)發(fā)布成web應(yīng)用,但是5.0不會(huì),在文件夾中必須要有一個(gè)WEB-INF的文件夾,同時(shí)還必須要有web.xml文件才行。

如何解決
通過page指令的contentType屬性說明jsp源文件的字符集編碼。
page指令的pageEncoding屬性說明jsp源文件的字符集編碼

(4) include指令

  1. include指令用于引入其他jsp頁面,如果使用include指令引入了其它jsp頁面,那么jsp引擎將把這兩個(gè)jsp翻頁成一個(gè)Servlet。所以include指令引入通常稱為靜態(tài)導(dǎo)入。

語法:

<%@ include file="relativeURL"%>

其中的file屬性用于指定被引入文件的路徑。路徑以”/”開頭,表示當(dāng)前web應(yīng)用。

細(xì)節(jié):
被引入的文件必須遵循jsp語法。被引入的文件可以使用任意的擴(kuò)展名是html,jsp引擎也會(huì)按照處理jsp頁面的方式處理它里面的內(nèi)容,為了見名知意,jsp規(guī)范建議使用.jsp作為靜態(tài)引入文件的擴(kuò)展名。

由于使用include指令將會(huì)涉及到2個(gè)頁面,并會(huì)把jsp翻譯成一個(gè)Servlet,所以這2個(gè)jsp頁面的指令不能沖突。同時(shí)多個(gè)jsp程序中最好只有一個(gè)jsp程序里面帶有html這類全局標(biāo)簽,但是不能將標(biāo)識(shí)jsp文件的頭刪掉。
例:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    這是網(wǎng)頁頭

但是有些指令可以沖突,比如pageEncoding、import。

以上是靜態(tài)包含,也可以使用動(dòng)態(tài)包含:

<%
    Request.getRequestDispatcher("/public/head.jsp").include(request,response);
%>

這就是動(dòng)態(tài)包含,但是這種包含效率較低,因?yàn)樗鼤?huì)將多個(gè)jsp翻譯成多個(gè)servlet。

6. jsp運(yùn)行原理和九大隱式對(duì)象

(1)每個(gè)jsp頁面在第一次被訪問時(shí),web容器都會(huì)把請(qǐng)求交給jsp引擎(一個(gè)java程序)去處理。Jsp引擎先將jsp翻譯成一個(gè)_jspServlet(實(shí)質(zhì)上也是一個(gè)Servlet),然后按照Servlet的調(diào)用方式進(jìn)行調(diào)用。

(2)由于jsp第一次訪問時(shí)會(huì)翻譯成Servlet,所以第一次訪問通常會(huì)比較慢,但后面的訪問時(shí),jsp引擎如果發(fā)現(xiàn)jsp沒有變化,就不再翻譯,而是直接調(diào)用,所以程序的執(zhí)行效率不會(huì)收到影響。

(3)jsp引擎在調(diào)用jsp對(duì)應(yīng)的_jspServlet時(shí),會(huì)傳遞或創(chuàng)建九個(gè)與web開發(fā)相關(guān)的對(duì)象供_jspServlet使用。Jsp技術(shù)的設(shè)計(jì)者為了便于開發(fā)人員在編寫jsp頁面時(shí)獲得這些web對(duì)象的引用,特意定義了九個(gè)相應(yīng)的變量,開發(fā)人員在jsp頁面中通過這些變量就可以快速獲得這九個(gè)對(duì)象的引用。

(4)九個(gè)隱式對(duì)象

Request、Response、session、Application(servletContext)、config(servletConfig)、page(this)、exception、out(jspWriter)、pageContext。其中只有最后一個(gè)是jsp獨(dú)有的,其余的都是在servlet中學(xué)過的。

1.out隱式對(duì)象

Out隱式對(duì)象用于向客戶端發(fā)送文本數(shù)據(jù)。Out對(duì)象是通過調(diào)用pageContext對(duì)象的getOut方法返回的,其作用和用法與servletResponse.getWriter方法返回的PrintWriter對(duì)象非常相似,但是不同。

Jsp頁面中的out隱式對(duì)象的類型為jspWriter,jspWriter相當(dāng)于一種帶緩存功能的PrintWriter,設(shè)置jsp頁面的page指令的buffer屬性可以調(diào)整它的緩存大小,甚至關(guān)閉它的緩存。

只有向out對(duì)象中寫入了內(nèi)容,且滿足如下任何一個(gè)條件時(shí),out對(duì)象才去調(diào)用servletResponse.getWriter方法,并通過該方法返回的PrintWriter對(duì)象將out對(duì)象的緩沖區(qū)中的內(nèi)容真正寫到servlet引擎提供的緩沖區(qū)中:

  1. 設(shè)置page指令的buffer屬性關(guān)閉了out對(duì)象的緩存功能;
  2. out對(duì)象的緩沖區(qū)已滿
  3. 整個(gè)jsp頁面結(jié)束
    注意:這里有兩個(gè)緩沖區(qū)。

2.用jsp實(shí)現(xiàn)文件下載

<%@page import="java.io.OutputStream"%><%@page import="java.io.FileInputStream"%><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%
    String path = application.getRealPath("1.jpg");
    String filename = path.substring(path.lastIndexOf("\\") + 1);
    response.setHeader("content-disposition", "attachment;filename="+filename);
    FileInputStream in = new FileInputStream(path);
    int len = 0;
    byte[] buffer = new byte[1024];
    OutputStream sout = response.getOutputStream();
    while((len = in.read(buffer)) > 0){
        sout.write(buffer, 0, len);
    }
    in.close();
 %>


注意:這里我們必須將所有的模板內(nèi)容都刪除干凈,因?yàn)?strong>只要有模板內(nèi)容那么就會(huì)生成out對(duì)象,但是我們可以看到j(luò)ava代碼中我們自己創(chuàng)建了一個(gè)字節(jié)流,那如果服務(wù)器又生成一個(gè)out的字符流就會(huì)產(chǎn)生異常,字符流是不能輸出圖片的。只有當(dāng)模板代碼沒有時(shí)才不會(huì)生成out隱式對(duì)象,即使生成了也不會(huì)輸出。而刪除模板代碼要將空格都刪除干凈,每個(gè)<% %>之間不能有空格,而最后的%>后面也不能有空格。我們可以看到,這和我們?cè)趕ervlet中寫是一樣的。

3. pageContext對(duì)象

(1)pageContext對(duì)象是jsp技術(shù)中最重要的一個(gè)對(duì)象,它代表jsp頁面的運(yùn)行環(huán)境,這個(gè)對(duì)象不僅封裝了對(duì)其它8大隱式對(duì)象的引用,自身還是一個(gè)域?qū)ο?,可以用來保存?shù)據(jù)。并且,這個(gè)對(duì)象還封裝了web開發(fā)中常常涉及到的一些常用操作,例如,引入和跳轉(zhuǎn)到其他資源、檢索其它域?qū)ο笾械膶傩缘取?/p>

getException方法返回exception隱式對(duì)象
getPage方法返回page隱式對(duì)象
getRequest方法返回request隱式對(duì)象
getResponse方法返回Response隱式對(duì)象
getServletConfig方法返回config隱式對(duì)象
getServletContext方法返回Application隱式對(duì)象
getSession方法返回session隱式對(duì)象
getOut方法返回out隱式對(duì)象

既然pageContext內(nèi)置其他八大對(duì)象,那么如果將此對(duì)象傳遞給一個(gè)普通的java對(duì)象,那么這個(gè)java對(duì)象就相當(dāng)于一個(gè)servlet。

(2)pageContext作為域?qū)ο?/h4>

pageContext對(duì)象的方法
public abstract void setAttribute(String name,Object value)
public abstract Object getAttribute(String name)
public abstract void removeAttribute(String name)

pageContext對(duì)象中還封裝了訪問其它域的方法
public abstract Object getAttribute(String name,int scope)
public abstract void setAttribute(String name,
Object value,int scope)
public abstract void removeAttribute(String name, int scope)

代表各個(gè)域的常量
PageContext. APPLICATION_SCOPE
PageContext. SESSION_SCOPE
PageContext. REQUEST_SCOPE
PageContext. PAGE_SCOPE

例子:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP '2.jsp' starting page</title>
  </head>
  <body>
    <%  
        //往session中存入一個(gè)數(shù)據(jù)
        pageContext.setAttribute("data", "xxx", PageContext.SESSION_SCOPE);
        //從session中取數(shù)據(jù)
        /* String data = (String)session.getAttribute("data");
        String data = (String)pageContext.getAttribute("data"); */
        
        String data = (String)pageContext.findAttribute("data");
     %>
     <%=data %>
  </body>
</html>

注意:findAttribute這個(gè)方法重點(diǎn)掌握,用于查找各個(gè)域中的屬性。

(3)引入和跳轉(zhuǎn)到其他資源

pageContext類中定義了一個(gè)forward方法和兩個(gè)include方法來分別簡化和替代RequestDispatcher.forward方法和include方法。方法接收的資源如果以“/”開頭,“/”表示當(dāng)前的web應(yīng)用。當(dāng)然這都是動(dòng)態(tài)引用。

(4)jsp標(biāo)簽

jsp標(biāo)簽也稱之為Jsp Action(jsp動(dòng)作)元素,它用于在jsp頁面中提供業(yè)務(wù)邏輯功能,避免在jsp頁面中直接編寫java代碼,造成jsp頁面難以維護(hù)。

(5)jsp常用標(biāo)簽

<jsp:include>動(dòng)態(tài)包含標(biāo)簽:

<jsp:include page="<%=url%>"/>

<jsp:forward><jsp:param>跳轉(zhuǎn)標(biāo)簽:

<jsp:forward page="1.jsp">
  <jsp:param name="xxx" value="yyy">
</jsp:forward>

相當(dāng)于:

<jsp:forward page="1.jsp?xxx=yyy"/>

語法:

<jsp:include page="1.jsp|<%=url%>" flush="true|false"/>

Page屬性用于指定被引入資源的相對(duì)路徑,它也可以通過執(zhí)行一個(gè)表達(dá)式來獲得;flush屬性指定在插入其他資源的輸出內(nèi)容時(shí),是否先將當(dāng)前jsp頁面的已輸出的內(nèi)容刷新到客戶端。

<jsp:include>與include指令的比較
(1) <jsp:include>標(biāo)簽是動(dòng)態(tài)引入,涉及到兩個(gè)jsp頁面會(huì)被翻譯成2個(gè)servlet,這兩個(gè)servlet的內(nèi)容在執(zhí)行時(shí)進(jìn)行合并。

(2) 而include指令是靜態(tài)引入,涉及到的2個(gè)jsp頁面會(huì)被翻譯成一個(gè)servlet,其內(nèi)容是在源文件級(jí)別進(jìn)行合并。

(3) 都會(huì)把兩個(gè)jsp頁面的內(nèi)容合并輸出,所以這兩個(gè)頁面不要出現(xiàn)重復(fù)非html全局架構(gòu)標(biāo)簽,否則輸出給客戶端的內(nèi)容將會(huì)是一個(gè)格式混亂的html文檔。

<jsp:forward>標(biāo)簽
page屬性用于指定請(qǐng)求轉(zhuǎn)發(fā)到的資源的相對(duì)路徑,它也可以通過執(zhí)行一個(gè)表達(dá)式來獲得。

<jsp:param>標(biāo)簽
用于傳入?yún)?shù)。可以將多個(gè)參數(shù)寫在一個(gè)標(biāo)簽中,也可以分開寫。

映射jsp

<servlet>
    <servlet-name></servlet-name>
    <jsp-file>/jsp/simple.jsp</jsp-file>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>SimpleJspServlet</servlet-name>
    <url-pattern>/xxx/yyy.html</url-pattern>
</servlet-mapping>

這是我們?nèi)绻苯釉L問yyy.html就相當(dāng)于訪問simple.jsp。

如何查找jsp頁面中的錯(cuò)誤
(1) jsp頁面中的jsp語法格式有問題,導(dǎo)致其不能被翻譯成servlet源文件,jsp引擎將提示這類錯(cuò)誤發(fā)生在jsp頁面中的位置以及相關(guān)信息。

(2) jsp頁面中的jsp語法格式?jīng)]有問題,但被翻譯成的servlet源文件中出現(xiàn)了java語法問題,導(dǎo)致jsp頁面翻譯成的servlet不能通過編譯,jsp引擎也將提示這類錯(cuò)誤發(fā)生在jsp頁面中的位置以及相關(guān)信息。

(3) jsp頁面翻譯成的servlet在運(yùn)行時(shí)出現(xiàn)異常,這與普通的java錯(cuò)誤一樣,會(huì)提示相關(guān)信息。

(4) 一個(gè)難以理解的錯(cuò)誤:有時(shí)候訪問jsp正確,之后訪問又出現(xiàn)錯(cuò)誤,也就是時(shí)好時(shí)壞。這是因?yàn)槿绻谝淮卧L問時(shí)正確,那么就有一個(gè)正確的servlet存在硬盤中了,如果這時(shí)jsp發(fā)生改動(dòng)產(chǎn)生了錯(cuò)誤,那么第二次訪問會(huì)出錯(cuò),而第三次訪問時(shí)服務(wù)器發(fā)現(xiàn)剛才編譯過,此時(shí)不會(huì)再次編譯,會(huì)直接從硬盤中取得之前正確的文件,這時(shí)就正確了。但是如果間隔時(shí)間長了,那么又會(huì)再次編譯。

(6)三個(gè)容器

request:客戶機(jī)像服務(wù)器發(fā)出請(qǐng)求,用戶看完之后就沒用了,比如新聞,這種數(shù)據(jù)一般存在此容器中。

session:客戶機(jī)像服務(wù)器發(fā)出請(qǐng)求,用戶看完之后,“過一會(huì)兒”之后還有用,比如購物,這種數(shù)據(jù)一般存在此容器中。

servletContext:客戶機(jī)像服務(wù)器發(fā)出請(qǐng)求,產(chǎn)生的數(shù)據(jù)用戶看完之后還要給其它用戶使用,比如聊天數(shù)據(jù)。這類數(shù)據(jù)一般存在此容器中。
最后,如果使用較小的容器能完成的任務(wù)就不要使用較大的容器。

補(bǔ):九大隱式對(duì)象和四大作用域總結(jié)

名稱 描述 作用域
request 請(qǐng)求對(duì)象 request
response 響應(yīng)對(duì)象 Page
pageContext 頁面上下文對(duì)象 Page
session 會(huì)話對(duì)象 Session
application(servletContext) 應(yīng)用程序?qū)ο?/td> Application
out(jspWriter) 輸出對(duì)象 Page
config(servletConfig) 配置對(duì)象 Page
page(this) 頁面對(duì)象 Page
exception 異常對(duì)象 Page

詳細(xì)說明:

  • 1.request 對(duì)象代表的是來自客戶端的請(qǐng)求,例如我們?cè)贔ORM表單中填寫的信息等,是最常用的對(duì)象;

  • 2.response 對(duì)象代表的是對(duì)客戶端的響應(yīng),也就是說可以通過response 對(duì)象來組織發(fā)送到客戶端的數(shù)據(jù)。但是由于組織方式比較底層,所以不建議普通讀者使用;

  • 3.pageContext 對(duì)象直譯時(shí)可以稱作“頁面上下文”對(duì)象,代表的是當(dāng)前頁面運(yùn)行的一些屬性;

  • 4.session 對(duì)象代表服務(wù)器與客戶端所建立的會(huì)話,當(dāng)需要在不同的JSP頁面中保留客戶信息的情況下使用,比如在線購物、客戶軌跡跟蹤等?!皊ession” 對(duì)象建立在cookie的基礎(chǔ)上,所以使用時(shí)應(yīng)注意判斷一下客戶端是否打開了cookie;

  • 5.application 對(duì)象負(fù)責(zé)提供應(yīng)用程序在服務(wù)器中運(yùn)行時(shí)的一些全局信息;

  • 6.out 對(duì)象代表了向客戶端發(fā)送數(shù)據(jù)的對(duì)象,與“response” 對(duì)象不同,通過“out” 對(duì)象發(fā)送的內(nèi)容將是瀏覽器需要顯示的內(nèi)容,是文本一級(jí)的,可以通過“out” 對(duì)象直接向客戶端寫一個(gè)由程序動(dòng)態(tài)生成HTML文件;

  • 7.config對(duì)象提供一些配置信息,常用的方法有g(shù)etInitParameter和getInitParameterNames,以獲得Servlet初始化時(shí)的參數(shù);

  • 8.page 對(duì)象代表了正在運(yùn)行的由JSP文件產(chǎn)生的類對(duì)象,不建議一般讀者使用;

  • 9.exception對(duì)象則代表了JSP文件運(yùn)行時(shí)所產(chǎn)生的例外對(duì)象,此對(duì)象不能在一般JSP文件中直接使用,而只能在使用了<%@ page isErrorPage="true "%>的JSP文件中使用。

  • 一般使用最多的也就是request、session、application和pageContext這四個(gè)隱式對(duì)象。

四大作用域的區(qū)別:

  • 1.page里的變量沒法從001.jsp傳遞到002.jsp。只要頁面跳轉(zhuǎn)了,它們就不見了。

  • 2.request里的變量可以跨越forward前后的兩頁。但是只要刷新頁面,它們就重新計(jì)算了。

  • 3.session和application里的變量一直在累加,開始還看不出區(qū)別,只要關(guān)閉瀏覽器,再次重啟瀏覽器訪問這頁,session里的變量就重新計(jì)算了。

  • 4.application里的變量一直在累加,除非你重啟tomcat,否則它會(huì)一直變大。

最后:上面的作用域依次增大。

  • 如果把變量放到pageContext里,就說明它的作用域是page,它的有效范圍只在當(dāng)前jsp頁面里。從把變量放到pageContext開始,到j(luò)sp頁面結(jié)束,你都可以使用這個(gè)變量。

  • 如果把變量放到request里,就說明它的作用域是request,它的有效范圍是當(dāng)前請(qǐng)求周期。所謂請(qǐng)求周期,就是指從http請(qǐng)求發(fā)起,到服務(wù)器處理結(jié)束,返回響應(yīng)的整個(gè)過程。在這個(gè)過程中可能使用forward的方式跳轉(zhuǎn)了多個(gè)jsp頁面,在這些頁面里你都可以使用這個(gè)變量。

  • 如果把變量放到session里,就說明它的作用域是session,它的有效范圍是當(dāng)前會(huì)話。所謂當(dāng)前會(huì)話,就是指從用戶打開瀏覽器開始,到用戶關(guān)閉瀏覽器這中間的過程。這個(gè)過程可能包含多個(gè)請(qǐng)求響應(yīng)。也就是說,只要用戶不關(guān)瀏覽器,服務(wù)器就有辦法知道這些請(qǐng)求是一個(gè)人發(fā)起的,整個(gè)過程被稱為一個(gè)會(huì)話(session),而放到會(huì)話中的變量,就可以在當(dāng)前會(huì)話的所有請(qǐng)求里使用。

  • 如果把變量放到application里,就說明它的作用域是application,它的有效范圍是整個(gè)應(yīng)用。整個(gè)應(yīng)用是指從應(yīng)用啟動(dòng),到應(yīng)用結(jié)束。我們沒有說“從服務(wù)器啟動(dòng),到服務(wù)器關(guān)閉”,是因?yàn)橐粋€(gè)服務(wù)器可能部署多個(gè)應(yīng)用,當(dāng)然你關(guān)閉了服務(wù)器,就會(huì)把上面所有的應(yīng)用都關(guān)閉了。application作用域里的變量,它們的存活時(shí)間是最長的,如果不進(jìn)行手工刪除,它們就一直可以使用。與上述三個(gè)不同的是,application里的變量可以被所有用戶共用。如果用戶甲的操作修改了application中的變量,用戶乙訪問時(shí)得到的是修改后的值。這在其他scope中都是不會(huì)發(fā)生的,page, request,session都是完全隔離的,無論如何修改都不會(huì)影響其他人的數(shù)據(jù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.學(xué)習(xí)內(nèi)容 JSP技術(shù)入門和常用指令 JSP的內(nèi)置對(duì)象&標(biāo)簽介紹 EL表達(dá)式&EL的內(nèi)置對(duì)象 2.JSP技術(shù)入門...
    WendyVIV閱讀 2,338評(píng)論 1 18
  • 一、JSP基礎(chǔ) 1.1什么是JSP JSP(Java ServerPage)是Java服務(wù)器端動(dòng)態(tài)頁面技術(shù)。是su...
    晨星資源閱讀 1,273評(píng)論 0 6
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,853評(píng)論 18 399
  • 這部分主要是與Java Web和Web Service相關(guān)的面試題。 96、闡述Servlet和CGI的區(qū)別? 答...
    雜貨鋪老板閱讀 1,507評(píng)論 0 10
  • 前面講了servlet入門實(shí)踐現(xiàn)在開始介紹jsp入門實(shí)踐,開發(fā)環(huán)境的搭建請(qǐng)參考我前面的tomcat的文章,jsp入...
    伊豚wall閱讀 3,444評(píng)論 2 56

友情鏈接更多精彩內(nèi)容