(八)JSP 技術知識點總結(來自那些年的筆記)


目錄javascript


多是JSP知識總結的最全的博客之一了,你想要尋找的知識,這裏都有 ;php

做者:淮左白衣

來源:筆者當時學web的筆記

時間:-2018年5月4日21:25:09

什麼是 jsp

JSP全稱是 java servlet pages,它和 servlet 技術同樣,都是Sun公司定義的一種用於開發動態web頁面的技術html

  • 爲何jsp也是一種動態web資源的開發技術呢?java

    jsp,雖然就像是在寫HTML,可是jsp容許在頁面中編寫java代碼,而且容許開發人員在頁面中獲取requestresponseweb開發經常使用對象,實現與瀏覽器的交互,因此jsp也是一種動態web資源的開發技術;web

    例子:輸出當前時間apache

Date date = new Date();
//這個out對象是能夠直接使用的,它是JspWriter的實例
out.write(date.toLocaleString());

Jsp 調用和運行原理(簡略版)

瀏覽器訪問 jsp 頁面時,Web 服務器是如何調用並執行一個jsp頁面的?

首先知道,咱們訪問服務器的資源時,不管訪問的是什麼?好比訪問的是HTML、jsp,其實咱們訪問的都是一個servlet,而不是真正的jsp、html ,所以,咱們訪問 jsp 其實就是去訪問 servlet編程

Jsp在被訪問的時候,服務器會將它 翻譯爲 servlet,轉換後的servlet,被保存在服務器目錄下的work/項目名/apache/…跨域

提問:瀏覽器

  • web 服務器在執行jsp頁面時,是如何把jsp頁面中的HTML排版標籤輸出給瀏覽器的?緩存

    這裏實際上是 jsp 對應的 servlet 的功勞,咱們知道服務器會將jsp轉爲一個servlet 對象,咱們去訪問jsp的時候,實際訪問到的也是這個servlet對象;

    在這個servlet對象對應的類中。它是經過out.writer()語句將 jsp 中的 HTML 語句,原封不動的打給瀏覽器;遇到<%java代碼%>,就直接執行;

  • jsp頁面中的java代碼,服務器是如何執行的?

    是原封不動的,代碼最後都在在servlet類中執行了;

  • Web服務器在調用jsp時,會給jsp提供一些什麼java對象

    會提供許多對象;request、response、out、application、session等這些對象,在jsp中是直接可使用的,由於在jsp對應的servlet類中已經提供好了
    若是想要得到jsp對應的servlet類的對象的自身,使用page,也是它內置提供的;

上面的幾個問題,其實均可以翻看對應的 servlet 類的源碼,,找到答案;


Jsp語法

  • Jsp模板元素

    Jsp 頁面中的 HTML 內容稱之爲 jsp 模板元素。

    Jsp的模板元素定義了網頁的基本骨架,即定義了頁面的結構和外觀;

下面的幾個概念,分清楚了,別混淆;

  • Jsp腳本表達式

    語法:<%= xxxx %>

    jsp腳本表達用於將程序數據輸出到客戶端,只能寫在一行

    Jsp引擎在翻譯腳本表達式時,會將程序數據轉成字符串,而後在相應的位置用out.print(...),將數據輸出給客戶端

    Jsp腳本表達式的變量或者表達式後面不能有分號 ,其實緣由很簡單,腳本表達式是要被放到 out.print(...) 裏面的,在結尾加上一個 ; 會被輸出,而咱們並不想輸出這個分號;

  • Jsp腳本片斷

    jsp腳本片斷用於在jsp頁面中編寫 多行 java代碼;

    語法:

<%
            多行java代碼
    %>

注意jsp腳本片斷中只能出現java代碼,不能出現其餘模板元素由於,jsp引擎在翻譯jsp頁面時,會將jsp腳本片斷中的 java代碼原封不動的放到 servlet_jspService 方法中。

jsp腳本片斷中的java代碼,必須嚴格遵照java語法!廢話,最後被轉到servlet中,java代碼原封不動的;

在一個jsp頁面中能夠有多個腳本片斷,在腳本片斷之間是能夠寫上模板元素的;而且多個腳本片斷之間的數據是共享的;(瞭解下底層原理,就知道爲啥共享了

單個腳本片斷中的java代碼能夠是不完整的,可是多個腳本片斷中,java代碼必須完整了 ;

  • Jsp聲明

    在jsp中,腳本片斷中java代碼,都被翻譯到servlet的jspService方法中了;

    那麼假如,咱們想要將java代碼,寫到jspService方法外面的話,就須要使用jsp聲明了;

<%!
    java代碼
%>

咱們就能夠爲servlet類添加方法字段等屬性了,可是通常沒啥人使用這個技術;

  • Jsp註釋

    格式:

<%--
    註釋信息
--%>

JSP引擎在將 jsp 頁面翻譯成 servlet 程序時,會 忽略jsp頁面中被註釋的內容 ;注意是被jsp引擎翻譯時,就拋棄了,也就是在servlet類中將沒有這個註釋的內容;可是你要是使用HTML的註釋,就不行了;

  • Jsp指令

    jsp指令 是爲 jsp引擎 而設計的。它們並不直接產生任何可見輸出而只是告訴引擎如何處理jsp頁面中的其他部分
    jsp2.0規範中共定義3個指令:

    今天2018年4月23日,jsp規範,早就不是2.0點了。須要注意下,可是不影響你學習JSP

    page指令
    Include指令
    taglib指令


Jsp指令簡介

  • jsp指令的基本語法格式:
<%@ 指令 屬性名=「值」 %>

舉例:

<%@ page contentType="text/html; ISO-8859-1" %>

若是一個指令有多個屬性,這多個屬性能夠寫在一個指令中,用 空格 分隔多個屬性,也能夠分開寫 ;

下面講解3大指令;


Page指令

page指令用於定義jsp頁面的各類屬性,不管page指令出如今jsp頁面中的什麼地方,它做用的都是整個jsp頁面;

爲了保持程序的可讀性和遵循良好的編程習慣,page指令最好是放在整個jsp頁面的初始位置。

Jsp2.0規範中定義的 page指令 的完整語法:

屬性名 = 「 做 用
pageEncoding = "xxx" 指明翻譯 jsp 的時候,使用 xxx 碼錶
contentType = "text/html;charset=UTF-8" 指明jsp翻譯成的 servlet 文件,裏面的 response 使用的碼錶
language = "java" 指明 jsp 頁面中的語言是 java
extends = "xxx.class" 表名生成jsp翻譯的servlet類繼承自xxx,不過通常,繼承自默認類,便可。不須要改動
import = "xxx" 表示,咱們的java語句,須要導入的包,通常自動導包就行了,不用咱們手動去指定這個屬性
session = "false / true " false 表示,翻譯過去的servlet中不要自動建立session 對象,目的是爲了,在不須要 session 的狀況下,避免生成 session,減輕服務器的壓力。或者咱們須要session對象,可是,咱們想手動讓服務器建立session對象的
buffer = "8kb / none / xx kb" out.print()的數據,不是直接寫到瀏覽器中(效率太慢),仍是先寫到緩衝區中,再寫到瀏覽器,buffer指定緩衝區的大小,默認是8kb
autoFlush = "false / true" 是否自動刷新緩衝區,默認爲true
isThreadSafe = "true" 翻譯過去的servlet是不是線程安全的,這個最TM奇怪了,默認爲true。可是表示默認線程不安全
isErrorPage = "true" 表示該jsp是頁面 錯誤處理 頁面,屬性值置爲true時,jsp 翻譯爲 servlet時,會傳進去一個異常對象,表示錯誤的異常;

做用 當服務器出錯了,跳到錯誤頁面(404頁面),而後返回給瀏覽器,但這404是個正確的頁面,服務器就會返回200狀態碼,咱們 爲了告知瀏覽器咱們出錯了,就在頁面中加上這個屬性值,服務器將返回500
isELIgnored = "true" 是否忽略 EL表達式
errorPage = "url" 用來指定當前頁面出錯時,跳轉的界面。屬性值必須使用相對路徑,以 / 開頭則相對當前 web 應用;沒有 / 打頭,則相對於當前頁面;

固然,咱們也能夠在服務器的 web.xml 文件 使用<error-page>元素爲整個web應用指定錯誤處理頁面,其中的兩個子標籤,一個用於指明異常的類型(寫全名),這個子標籤還能夠寫成狀態碼,一個用於指明出現該異常。跳準的界面地址;

若是咱們在 jsp 中寫明瞭 errorPage 屬性,那麼web.xml文件中的錯誤處理配置,對此jsp不生效

Include指令

include 指令用於引入 jsp 頁面,若是使用 include 引入其餘 jsp 頁面,那麼 jsp 引擎將把這兩個jsp翻譯爲一個servlet,因此,include指令引入一般也稱爲 靜態導入

屬性名 = 「 做 用
file = "url" 其中的file屬性用於指定被引入文件的路徑。路徑以「/」開頭,來表示當前web應用;

細節

  • 被引入的文件必須遵循jsp語法
  • 被引入的文件可使用任意的擴展名,即便是HTML擴展名,jsp引擎仍是會按照處理jsp頁面的方式處理頁面的內容;爲了,見名思意,jsp規範建議使用 .jspf 做爲靜態導入文件的擴展名;
  • 因爲使用.jspf指令會涉及到兩個jsp頁面,並會把2個jsp翻譯爲一個servlet,全部這兩個jsp頁面的指令不能衝突
  • 被導入的頁面,不要包含HTML語句了,不然頁面將不是一個完成的頁面,會出現兩個 <head> 這樣的標籤;

動態包含

語法: request.getRequestDispatcher("url").include(request,response);

這是在運行時包含,會將 每個 jsp 都對應生成一個servlet也就是最終生成不止一個 servlet

咱們通常選擇靜態導入,性能高 ;


taglib指令

在講標籤庫的時候,再講;


Jsp亂碼問題

亂碼產生的根由無外乎兩種

  • jsp文件 保存的編碼和服務器翻譯 servlet 的時候的編碼不一致
  • 瀏覽器的編碼和翻譯的servletresponse 的編碼編碼不一致;

解決方法<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8" %>

咱們發現只要這兩個地方使用相同的編碼,亂碼就不會產生;

pageEncoding=」xxx」 告訴服務器翻譯時使用什麼碼錶;

contentType="text/html;charset=UTF-8" 再告訴瀏覽器用什麼碼錶打開 ;

其實能夠不告訴瀏覽器用什麼碼錶,由於 只要告訴服務器翻譯的碼錶,服務器會自動將servlet的response的碼錶設爲一致的;可是,咱們仍是寫上吧


jsp運行原理(詳細版)

每一個jsp頁面在 第一次 被訪問時,web容器 都會把請求交給 jsp引擎(即一個java程序)去處理。Jsp引擎 先將 jsp 翻譯成一個_jspServlet(實際上就是一個servlet),而後按照 servlet 的調用方式進行調用 ;

因爲JSP第一次訪問時,會被翻譯成servlet,全部第一次訪問一般會比較慢可是第二次訪問,JSP引擎 若是發現 JSP 沒有變化,就再也不翻譯,而是直接調用,因此程序的執行效率不會受到影響


JSP中的九大隱式對象

JSP引擎 在調用 JSP 對應的 _JspServlet 時,會 傳遞或建立 9個與WEB開發相關的對象供_JspServlet使用

JSP技術的設計者爲了方便web開發人員在編寫JSP頁面時,得到這些對象的引用,特地定義了9個相應的變量,開發人員在JSP頁面中經過這9個變量就能夠快速的得到這9大對象的引用

這九大隱式對象就是:responserequestsessionapplication(ServletContext)page (jsp對象自身)、config(servlertConfig)exceptionout(JspWriter)PageContext

前面7個,在學JSP以前,都已經學過了,這裏重點講最後兩個;

  • Out隱式對象

    做用Out隱式對象 用於向客戶端發送文本數據;

    Out對象 是經過調用 PageContext 對象的 getOut() 方法返回的,其做用和用法與servletResponse.getWriter方法返回的 PrintWriter 對象很是類似。

    JSP頁面中的out隱式對象的類型爲JspWriterJspWriter至關於一種帶緩存功能PrintWriter,設置JSP頁面的page指令的buffer屬性能夠調整它的緩存大小,甚相當閉它的緩存(buffer屬性的值爲none);

    只有向out對象中寫入了內容,且 知足以下任何一個條件時(至關於刷新緩衝區)out對象纔會去調用servletResponse.getWriter方法,而且經過該方法返回PrinterWriter對象將out對象緩衝區中的內容 真正的寫入 servlet引擎提供的緩衝區中(response緩衝區):

    條件
    √ 設置page指令的buffer屬性關閉了out對象的緩存功能
    out對象的緩衝區已滿 ;
    √ 整個JSP頁面結束;

    備註
    Out對象輸出的數據 可能滯後於 response.getWriter 對象輸出的數據,緣由就在於out對象本身的緩衝區;out對象的緩存區滿了,纔將數據刷新到response的緩衝區;服務器發現response緩衝區有數據,纔會將數據發送到客戶端


PageContext對象

jsp技術中最重要的一個對象,它表明jsp頁面的運行環境

生命週期是一個jsp頁面;

這個對象自身就封裝可其餘8大隱式對象的引用;(這個最厲害了)

它自身仍是一個域對象,能夠用來保存數據;

這個對象中,還封裝了web開發中常常涉及到的一些經常使用操做,例如引入和跳轉其餘資源、檢索其餘域對象中的屬性;


經過PageContext對象得到其餘對象

經過 getXXX()方法;

PageContext對象中包含其餘8大隱式對象的引用;

首先知道一個事實:JSP頁面中是不該該出現java代碼,良好的jsp中,是不該該出現一行java代碼的;

可是有些時候,咱們爲了獲取servlet傳過來的數據,不得已要使用java代碼,這時候,咱們就須要一個技術:自定義標籤;(之後會講這個技術)

咱們把java代碼替換成一個自定義標籤,這個標籤對應着一個java類,咱們須要把web中的這些對象傳給java類,一個一個傳,很麻煩的,所以,咱們就直接傳一個pageContext對象過去;


Javaweb的四個域

範圍(從小到大
Page域: pageContext,最小的域,只能在頁面中使用
Request域: 請求域
Session域: 會話級別的域
ServletContext域: 最大的域,在整個應用程序中可用

PageContext域的方法

獲取數據

pageContext.getAttribute(String) ;

設置數據

pageContext.setAttribute(String,String);

移除數據

pageContext.removeAttribute(String);

PageContext跨域訪問的方法

獲取id對應的域的數據

pageContext.getAttribute(String,id) ;

設置id對應的域數據

pageContext.setAttribute(String,String,id);

移除id對應的域數據

pageContext.removeAttribute(String,id);

PageContext查找屬性的方法

pageContext.findAttribute(String)

用於查找某個屬性的屬性值,它會依次從pagerequestsessionapplication四個域,從小到大的查找,在某個域中查到數據,即刻返回這個數據,不會再繼續查下去。若是四個域都沒查到,則返回null

這個方法,便利於咱們能夠在jsp中直接使用這個方法來查找數據,而不要去關注數據在哪個域中;


引入和跳轉到其餘資源

PageContext類中定義了一個forward方法和兩個include方法來分別簡化和替代RequestDispatcher(...).forward方法和RequestDispatcher(...).include方法。

原始的操做

// forward
request.getRequestDispatcher("/xxx").forward(request, response);
// include
request.getRequestDispatcher("/xxx").include(request, response);

使用pageContext簡化:

// forward
pageContext.forward("/xxx");
// include
pageContext.include("/xxxx");

方法接受的資源若是以 / 開頭,/ 表明當前web應用;


JSP標籤

JSP Action (JSP動做)它用於jsp頁面中提供業務邏輯功能,避免在JSP頁面中直接編寫java代碼,形成jsp頁面難以維護

經常使用的三種標籤:

 // 動態包含
<jsp:include page=""> </jsp:include>  

 //跳轉頁面
<jsp:forward page="">    
 // 負責帶數據到另外一個JSP頁面中,value的值,能夠是腳本表達式 // 通常和包含include便籤一塊兒使用
 <jsp:param name="" value=""></jsp:param>
 // 將數據帶到xxx.jsp 中
<jsp:include page="xxxx.jsp">  
    <jsp:param name="xxx" value="xxx"/>  
</jsp:include>

其中 </jsp:forward> Jsp跳轉 應用場景:

在配置歡迎首頁的時候,是不讓配置servlet的,只能配置成jsp 所以,在jsp中進行跳轉頁面;


映射JSP

<servlet>
    <servlet-name>myform</servlet-name>
    <!--Jsp的路徑須要 / 來指認 -->
    <jsp-file>/form.jsp</jsp-file>
</servlet>
<servlet-mapping>
    <servlet-name>myform</servlet-name>
    <url-pattern>/myform.html</url-pattern>
</servlet-mapping>

JSP抽風時好時壞的緣由

若是訪問JSP的時候,出現服務器報錯,緊接着再次訪問,服務器又不報錯的狀況,像神經病同樣一時好一時壞;

出現這樣的問題的緣由在於:JSP文件被咱們寫錯了;並其寫錯以前,這個JSP曾經被咱們正確寫對過,而且在服務器中有翻譯過的servlet,這樣,當咱們把JSP修改出錯之後,再次訪問,服務器發現JSP被修改過,就會從新翻譯一次,生成新的servlet,覆蓋以前的servlet。可是因爲,JSP語法有錯,沒法被正確的翻譯爲servlet這樣舊的servlet就不會被覆蓋掉。還存在在服務器中

這樣,當咱們第一次訪問的時候,服務器翻譯JSP失敗,就會爆錯,可是咱們緊接着,再次訪問,服務器發現,這人怎麼回事啊,我剛翻譯完這個servlet啊,它就不會再次翻譯servlet,而是把以前舊的servlet當成上一次翻譯的servlet這個過程,跟JSP變沒變,沒有任何關係,應該是JSP設計者,爲了減輕服務器的壓力設計的),給咱們;這就是咱們第一次報錯,緊接着再次訪問,就正確的緣由;

當咱們,過一會再次訪問,服務器就會發現,我曹這個JSP,我並無翻譯啊,就會再次翻譯,而後,就會再次報錯,周而復始,給咱們的感受就是JSP在抽風,時好時壞;


彷彿一會兒回到了90年代的夏天,你光着上身,穿着大褲衩,一雙簡單的人字拖,搖着一把破舊的芭蕉扇,VCD裏轉動着盜版的碟片,滿滿都是廣東香港氾濫到內地的流行歌曲和港片,手裏的冰激凌在融化,碟片偶爾會卡,你拿起遙控摁了一下快進鍵,一會兒就這麼快進了十幾年。
寫的真好!

《over》

相關文章
相關標籤/搜索