Java EE基礎(chǔ)之JSP(二)

?????接著上篇文章,我們上篇文章講到了jsp的基本原理以及和servlet的關(guān)系,還介紹了jsp的基本語(yǔ)法部分,本篇文章就繼續(xù)介紹余下的內(nèi)容。

  • 編譯指令Page和include
  • 基本的動(dòng)作指令
  • 內(nèi)置對(duì)象

一、兩個(gè)編譯指令
?????Page指令顧名思義,操作當(dāng)前頁(yè)面的。首先我們要知道使用編譯指令的格式:<%@ page 屬性名="屬性值"%>,關(guān)于page的屬性有哪些,如下圖所示:

這里寫(xiě)圖片描述

?????簡(jiǎn)單說(shuō)明一下,language指定的是本頁(yè)面使用的腳本語(yǔ)言,contentType指定了本頁(yè)面的類(lèi)型,有text/html,img/png等。import可以引入指定的包,默認(rèn)情況下已經(jīng)為我們引入了java.lang.,javax.servlet.jsp.,javax.servlet.http.*。所有在jsp頁(yè)面引入的包,都會(huì)對(duì)應(yīng)到servlet實(shí)例中。session指定當(dāng)前頁(yè)面是否支持會(huì)話(后面詳細(xì)介紹),errorPage指定了當(dāng)前頁(yè)面如果出現(xiàn)異常調(diào)用的頁(yè)面,如果沒(méi)有為當(dāng)前頁(yè)面指定errorPage頁(yè)面,就會(huì)直接拋出異常信息個(gè)瀏覽器(這是我們所不愿意看到的),isErrorPage指定了當(dāng)前頁(yè)面是否是錯(cuò)誤頁(yè)面,如果是,當(dāng)別的頁(yè)面出錯(cuò)的時(shí)候就會(huì)跳轉(zhuǎn)到此頁(yè)面,默認(rèn)為false。這么多的屬性,我們只要稍微有點(diǎn)印象,實(shí)際用的時(shí)候再過(guò)來(lái)參考即可。
?????我們說(shuō)jsp頁(yè)面中是不需要處理任何異常的,甚至是檢查類(lèi)異常都是不需要處理的。我們來(lái)看看為什么。從servlet類(lèi)的源代碼中找原因,因?yàn)檫@是本質(zhì)。

public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {

    final java.lang.String _jspx_method = request.getMethod();
    if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
      return;
    }

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\n");
      out.write("\n");
      out.write("<html>\n");
      out.write("  <head>\n");
      out.write("    <title></title>\n");
      out.write("  </head>\n");
      out.write("  <body>\n");
      out.write("\t\t");
for(int a=0;a<10;a++){
      out.write("\n");
      out.write("\t\t\t<p>Walker</p>\n");
      out.write("\t\t");
}
      out.write("\n");
      out.write("  </body>\n");
      out.write("</html>\n");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try {
            if (response.isCommitted()) {
              out.flush();
            } else {
              out.clearBuffer();
            }
          } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }

?????我們就看看這個(gè)用來(lái)響應(yīng)用戶請(qǐng)求的方法,_jspservice(),不知道大家看到?jīng)]有,整個(gè)輸出html頁(yè)面信息的代碼塊都被try....catch了,而看到catch捕捉的異常時(shí)異常機(jī)制的源頭Throwable ,所有的異常都是繼承自它的。而我們看到捕捉到異常之后所進(jìn)行的操作是,如果當(dāng)前對(duì)象不為空,就調(diào)用該對(duì)象的處理方法,處理方法就是判斷當(dāng)前頁(yè)面是否制定的errorPage頁(yè)面,如果沒(méi)有拋異常給瀏覽器,如果有,跳向錯(cuò)誤頁(yè)面。所以無(wú)論你jsp頁(yè)面會(huì)拋出什么異常,在被編譯到servlet實(shí)例中,已經(jīng)做了處理了,這就是為什么jsp頁(yè)面不需要處理異常的原因。

第二個(gè)指令是include指令,這是一個(gè)用來(lái)包含指定頁(yè)面的內(nèi)容的編譯指令,<%@include file="文件路徑"%>,我們來(lái)看一個(gè)例子:

<html>
  <head>
    <title></title>
  </head>
  <body>
        <h1>這是當(dāng)前頁(yè)面</h1>
        <%@include file="convert.jsp"%>
  </body>
</html>

<html>
  <head>
    <title></title>
  </head>
  <body>
    <h1>這是引入頁(yè)面</h1>
  </body>
</html>

運(yùn)行結(jié)果的圖片就不貼了,從servlet實(shí)例中可以明顯看出,這一切都做了什么。

out.write("\n");
      out.write("\n");
      out.write("<html>\n");
      out.write("  <head>\n");
      out.write("    <title></title>\n");
      out.write("  </head>\n");
      out.write("  <body>\n");
      out.write("\t\t<h1>這是當(dāng)前頁(yè)面</h1>\n");
      out.write("\t\t");
      out.write("\n");
      out.write("\n");
      
      out.write("<html>\n");
      out.write("  <head>\n");
      out.write("    <title></title>\n");
      out.write("  </head>\n");
      out.write("  <body>\n");
      out.write("\t<h1>這是引入頁(yè)面</h1>\n");
      out.write("  </body>\n");
      out.write("</html>\n");
      
      out.write("\n");
      out.write("  </body>\n");
      out.write("</html>\n");

?????不知道大家看出來(lái)了沒(méi)有,一個(gè)頁(yè)面里竟然包含了兩個(gè)html標(biāo)簽和title和body標(biāo)簽,可見(jiàn),這個(gè)編譯指令就是在編譯的時(shí)候?qū)⒁氲捻?yè)面中的全部信息直接插入在指定位置上。

二、基本的工作指令
?????第一個(gè)動(dòng)作指令是,forward指令,這個(gè)指令用來(lái)向另外的一個(gè)頁(yè)面進(jìn)行跳轉(zhuǎn)。用法如下:

<html>
  <head>
    <title>index.jsp</title>
  </head>
  <body>
        <h1>這是當(dāng)前頁(yè)面</h1>
        
        <jsp:forward page="convert.jsp">
        /*這是傳入?yún)?shù),暫時(shí)可以不用關(guān)心*/
            <jsp:param name="key" value="v" />
        </jsp:forward>
        
  </body>
</html>

<html>
  <head>
    <title>convert.jsp</title>
  </head>
  <body>
    <h1>這是引入頁(yè)面</h1>
  </body>
</html>
這里寫(xiě)圖片描述

?????從運(yùn)行結(jié)果上看,至少可以看出兩點(diǎn)。第一,地址欄上的地址依然是index頁(yè)面,也就是說(shuō)頁(yè)面并沒(méi)有跳走,第二,我們看原來(lái)index頁(yè)面的所有信息都被替換成convert頁(yè)面的內(nèi)容。由此我們可以推斷出,所謂的跳轉(zhuǎn)指令,其實(shí)并沒(méi)有完成跳轉(zhuǎn)的操作,只是將目標(biāo)頁(yè)面的所有信息全部替換當(dāng)前頁(yè)面,這和我們之前說(shuō)過(guò)的一個(gè)編譯指令很是類(lèi)似,他是include,我們應(yīng)該可以記得,include編譯指令是將目標(biāo)頁(yè)面中所有內(nèi)容替換到當(dāng)前頁(yè)面的某個(gè)位置,也就是替換了當(dāng)前頁(yè)面中的部分內(nèi)容。而可以將跳轉(zhuǎn)指令forward理解為替換了當(dāng)前頁(yè)面的所有內(nèi)容。

      out.write("\n");
      out.write("\n");
      out.write("<html>\n");
      out.write("  <head>\n");
      out.write("    <title>1</title>\n");
      out.write("  </head>\n");
      out.write("  <body>\n");
      out.write("\t\t<h1>這是當(dāng)前頁(yè)面</h1>\n");
      out.write("\t\t");
      if (true) {
        _jspx_page_context.forward("convert.jsp" + "?" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("key", request.getCharacterEncoding())+ "=" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("v", request.getCharacterEncoding()));
        return;
      }
      out.write("\n");
      out.write("  </body>\n");
      out.write("</html>\n");

?????從servlet源代碼中,我們可以看到,index中前面的代碼正常加載,當(dāng)加載到我們的跳轉(zhuǎn)指令的時(shí)候,它實(shí)際上構(gòu)建以個(gè)URL:convert.jsp?key=v,默默的請(qǐng)求了此頁(yè)面然后將返回的結(jié)果顯示在當(dāng)前的頁(yè)面中,其實(shí)就是去拿來(lái)目標(biāo)頁(yè)面中的內(nèi)容覆蓋當(dāng)前頁(yè)面,對(duì)于index頁(yè)面的一些請(qǐng)求參數(shù),不會(huì)丟失。(關(guān)于請(qǐng)求參數(shù)的接收,下文介紹)
?????第二個(gè)動(dòng)作指令,include指令,用來(lái)動(dòng)態(tài)引入外部文件到當(dāng)前頁(yè)面,和我們的include編譯指令相似,但是也有著顯著的區(qū)別。先看怎么使用:

<html>
  <head>
    <title>1</title>
  </head>
  <body>
        <h1>這是當(dāng)前頁(yè)面</h1>
        
        <jsp:include page="convert.jsp">
            <jsp:param name="a" value="c" />
        </jsp:include>
  </body>
</html>

<html>
  <head>
    <title>2</title>
  </head>
  <body>
    <h1>這是引入頁(yè)面</h1>

  </body>
</html>
out.write("\n");
      out.write("\n");
      out.write("<html>\n");
      out.write("  <head>\n");
      out.write("    <title>1</title>\n");
      out.write("  </head>\n");
      out.write("  <body>\n");
      out.write("\t\t<h1>這是當(dāng)前頁(yè)面</h1>\n");
      out.write("\t\t\n");
      out.write("\t\t");
      org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "convert.jsp" + "?" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("a", request.getCharacterEncoding())+ "=" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("c", request.getCharacterEncoding()), out, false);
      out.write("\n");
      out.write("  </body>\n");
      out.write("</html>\n");

?????我們可以看到,動(dòng)作指令include實(shí)際上不想編譯指令include將目標(biāo)頁(yè)面的所有信息全部插入到指定位置,動(dòng)態(tài)include指令調(diào)用的是一個(gè)include方法,動(dòng)態(tài)的將目標(biāo)頁(yè)面的body部分的內(nèi)容拿過(guò)來(lái),并且還允許傳入?yún)?shù)。可能結(jié)果和編譯指令include一樣,但是內(nèi)部的實(shí)現(xiàn)確是截然不同的,各自有各自的適用場(chǎng)所。
?????第三個(gè)動(dòng)作指令,param,這是我們之前一直在使用的指令,只是一直沒(méi)有說(shuō)明。param指令一般都不會(huì)單獨(dú)使用,通常都是結(jié)合jsp:include,jsp:forward等使用。使用的格式如下:

<jsp:include page="convert.jsp">
        <jsp:param name="a" value="c" />
</jsp:include>

?????name指定參數(shù)名,value指定參數(shù)數(shù)值。至于怎么獲取,我們?cè)诮榻Brequest對(duì)象的時(shí)候加以說(shuō)明。request對(duì)象就是一個(gè)專(zhuān)門(mén)用于處理用戶請(qǐng)求的對(duì)象,所以所有的參數(shù)傳遞都是可以使用這個(gè)對(duì)象進(jìn)行接收的。還有一些動(dòng)作指令牽扯到j(luò)avabean知識(shí),暫時(shí)不說(shuō)。

三、JSP內(nèi)置對(duì)象
?????我們打開(kāi)任意的servlet源代碼,可以看到在用于響應(yīng)用戶請(qǐng)求的方法_jspservice();的頭部有一些成員變量的定義和初始化??矗?/p>

public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response){
.....
    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;
.......
}

?????接下來(lái)我們會(huì)詳細(xì)介紹這些對(duì)象的含義及其具體的操作。由于篇幅限制,未完待續(xù)。。

最后編輯于
?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,692評(píng)論 18 399
  • 1.學(xué)習(xí)內(nèi)容 JSP技術(shù)入門(mén)和常用指令 JSP的內(nèi)置對(duì)象&標(biāo)簽介紹 EL表達(dá)式&EL的內(nèi)置對(duì)象 2.JSP技術(shù)入門(mén)...
    WendyVIV閱讀 2,326評(píng)論 1 18
  • 1.什么是JSP (1)jsp全稱(chēng)是Java Server Pages,它和Servlet技術(shù)一樣都是sun公司定...
    yjaal閱讀 3,836評(píng)論 5 99
  • 一、JSP基礎(chǔ) 1.1什么是JSP JSP(Java ServerPage)是Java服務(wù)器端動(dòng)態(tài)頁(yè)面技術(shù)。是su...
    晨星資源閱讀 1,268評(píng)論 0 6
  • 什么是jsp? 很久之前,我們的網(wǎng)頁(yè)都是靜態(tài)的,就是我們所看到的頁(yè)面在編寫(xiě)好之后總是唯一的。后來(lái)有人便提出動(dòng)態(tài)頁(yè)面...
    ezsync小智閱讀 1,666評(píng)論 0 13

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