校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁 > 知識庫 > JSP的運行內幕

JSP的運行內幕

熱門標簽:騰訊地圖標注商戶改名注冊入駐 開封便宜外呼系統報價 黃石智能營銷電銷機器人效果 地圖標注人員兼職 商丘百應電話機器人有沒有效果 怎樣把地圖標注出來 漯河辦理400電話 電話機器人的特色和創新 淮南騰訊地圖標注

    經常有朋友問起,JSP和Servlet之間有什么區別,兩者之間又有什么聯系?其實Servlet技術的出現時間很早,是當時為了Java的服務器端應用而開發的。大家都知道Applet是應用小程序,Servlet就是服務器端小程序了。但在Microsoft公司的ASP技術出現后,使用Servlet進行響應輸出時一行行的輸出語句就顯得非常笨拙,對于復雜布局或者顯示頁面更是如此。JSP就是為了滿足這種需求在Servlet技術之上開發的。可見,JSP和Servlet之間有著內在的血緣關系,在學習JSP時,如果能夠抓住這種聯系,就能更深刻地理解JSP的運行機理,達到事半功倍的效果。

本文將通過對一個JSP運行過程的剖析,深入JSP運行的內幕,并從全新的視角闡述一些JSP中的技術要點。

HelloWorld.jsp

我們以Tomcat 4.1.17服務器為例,來看看最簡單的HelloWorld.jsp是怎么運行的。

代碼清單1:HelloWorld.jsp

HelloWorld.jsp
%
 String message = "Hello World!";
%>
%=message%>
 


  這個文件非常簡單,僅僅定義了一個String的變量,并且輸出。把這個文件放到Tomcat的webapps\ROOT\目錄下,啟動Tomcat,在瀏覽器中訪問http://localhost:8080/HelloWorld.jsp,瀏覽器中的輸出為“HelloWorld!”

  讓我們來看看Tomcat都做了什么。轉到Tomcat的\work\Standalone\localhost\_目錄下,可以找到如下的HelloWorld_jsp.java,這個文件就是Tomcat解析HelloWorld.jsp時生成的源文件:

  代碼清單2:HelloWorld_jsp.java

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import org.apache.jasper.runtime.*;

public class HelloWorld_jsp extends HttpJspBase {
 ......
public void _jspService(HttpServletRequest request,
HttpServletResponse response)throws java.io.IOException, ServletException
 {
  JspFactory _jspxFactory = null;
  javax.servlet.jsp.PageContext pageContext = null;
  HttpSession session = null;
  ServletContext application = null;
  ServletConfig config = null;
  JspWriter out = null;
  Object page = this;
  JspWriter _jspx_out = null;

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

   String message = "Hello World!";
   out.print(message);
  } catch (Throwable t) {
   out = _jspx_out;
   if (out != null out.getBufferSize() != 0)
    out.clearBuffer();
   if (pageContext != null) pageContext.handlePageException(t);
  } finally {
  if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);
  }
 }
}
 


  從上面可以看出,HelloWorld.jsp在運行時首先解析成一個Java類HelloWorld_jsp.java,該類繼承于org.apache.jasper.runtime.HttpJspBase基類,HttpJspBase實現了HttpServlet接口。可見,JSP在運行前首先將編譯為一個Servlet,這就是理解JSP技術的關鍵。

  我們還知道JSP頁面中內置了幾個對象,如pageContext、application、config、page、session、out等,你可能會奇怪,為什么在JSP中的代碼片斷中可以直接使用這些內置對象。觀察_jspService()方法,實際上這幾個內置對象就是在這里定義的。在對JSP文件中的代碼片斷進行解析之前,先對這幾個內置對象進行初始化。

  首先,調用JspFactory的getDefaultFactory()方法獲取容器實現(本文中指Tomcat 4.1.17)的一個JspFactory對象的引用。JspFactory是javax.servlet.jsp包中定義的一個抽象類,其中定義了兩個靜態方法set/getDefaultFactory()。set方法由JSP容器(Tomcat)實例化該頁面Servlet(即HelloWorld_jsp類)的時候置入,所以可以直接調用JspFactory.getDefaultFactory()方法得到這個JSP工廠的實現類。Tomcat是調用org.apache.jasper.runtime.JspFactoryImpl類。

  然后,調用這個JspFactoryImpl的getPageContext()方法,填充一個PageContext返回,并賦給內置變量pageConext。其它內置對象都經由該pageContext得到。具體過程見上面的代碼,這里不再贅述。該頁面Servlet的環境設置完畢,開始對頁面進行解析。HelloWorld.jsp頁面僅僅定義了一個String變量,然后直接輸出。解析后的代碼如下:

  代碼清單3:JSP頁面解析后的代碼片斷

String message = "Hello World!";
out.print(message);
 


  定制標簽的解析過程

  在一個中大型的Web應用中,通常使用JSP定制標簽來封裝頁面顯示邏輯。剖析容器對定制標簽的解析過程,對我們深入理解定制標簽的運行機理非常有幫助。下面我們以Struts1.1b中附帶的struts-example應用的主頁運行為例加以說明。

  包含定制標簽的index.jsp

  Struts1.1b的下載地址是http://jakarta.apache.org/struts/index.html。將下載的包解壓,在webapps目錄下可以找到struts-example.war。將該War包拷貝到Tomcat的webapps目錄下,Tomcat會自動安裝此應用包。在瀏覽器中通過http://localhost:8080/struts-example訪問struts-example應用,將顯示應用的首頁(見圖1)。

 

  圖一 應用的首頁

  代碼清單4:index.jsp

%@ page contentType="text/html;charset=UTF-8" language="java" %>
%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
html:html locale="true">
head>
title>bean:message key="index.title"/>/title>
html:base/>
/head>
body bgcolor="white">
……
/body>
/html:html>
 


  我們僅以index.jsp中的bean:message/>標簽的解析為例進行分析,看容器是怎樣把這個自定義標簽解析成HTML輸出的。上面代碼省略了頁面的其它顯示部分。首先,查看上面瀏覽器中頁面的源文件:

html lang="zh">
head>
title>MailReader Demonstration Application (Struts 1.0)/title>
/head>
body bgcolor="white">
……
/body>
/html>
 


  可見,容器已經把bean:message key="index.title"/>替換成一個字串,顯示為頁面的標題。

  解析過程

  那么,JSP容器是怎樣完成解析的呢?查看在工作目錄jakarta-tomcat-4.1.17\work\Standalone\localhost\struts-example下解析后的index_jsp.java文件:

  代碼清單5:index_jsp.java

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import org.apache.jasper.runtime.*;
public class index_jsp extends HttpJspBase {
 //為所有的定制標簽定義處理器池類的引用
 private org.apache.jasper.runtime.TagHandlerPool ;
 _jspx_tagPool_bean_message_key;
 ……
 //頁面類構造方法
 public index_jsp() {
  _jspx_tagPool_bean_message_key =
  new org.apache.jasper.runtime.TagHandlerPool();
   ……
 }

 public void _jspService(HttpServletRequest request,
   HttpServletResponse response)
   throws java.io.IOException, ServletException {
  ……
  _jspxFactory = JspFactory.getDefaultFactory();
  response.setContentType("text/html;charset=UTF-8");
  pageContext = _jspxFactory.getPageContext(this,
    request, response,null, true, 8192, true);
  application = pageContext.getServletContext();
  config = pageContext.getServletConfig();
  session = pageContext.getSession();
  out = pageContext.getOut();
  _jspx_out = out;
  ……
  if (_jspx_meth_html_html_0(pageContext))
  return;
  ……
 }
 //頁面在處理退出時釋放所有定制標簽的屬性
 public void _jspDestroy() {
  _jspx_tagPool_bean_message_key.release();
  ……
 }
}
 


  生成的index_jsp.java繼承于org.apache. jasper.runtime.HttpJspBase。研究這個文件為我們了解定制標簽的運行機理提供了途徑。

  從上面可以看出,Tomcat在解析一個JSP頁面時,首先為每一個定制標簽定義并實例化了一個TagHandlerPool對象。頁面的處理方法覆蓋父類的_ jspService()方法,_jspService方法首先初始化環境,為內置對象賦值。由于index.jsp頁面整體由一個html:html/>標簽包裹,Tomcat對每一個標簽都產生一個私有方法加以實現。html:html/>標簽的處理方法是_jspx_meth_html_html_0()。這個方法的命名規范大家也可以從這里看出,就是“_jspx_meth + 標簽的前綴 + 標簽名 + 該標簽在JSP頁面同類標簽中出現的序號”。其它標簽都被包含在該標簽中,所以其它標簽在_jspx_meth_html_html_0()方法中進行解析。具體的代碼實現請參見賽迪網http://linux.ccidnet.com期刊瀏覽2003年第6期。

  在_jspx_meth_html_html_0()方法中,首先從_jspx_tagPool_html_html_locale池中得到一個org.apache.struts.taglib.html.HtmlTag的實例,然后設置這個tag實例的頁面上下文及上級標簽,由于html:html標簽是頁面的最頂層標簽,所以它的parent是null。然后對該標簽的內容進行解析。HTML代碼直接輸出,下面主要看看html:html>/html:html>標簽之間包含的bean:message key="index.title"/>標簽的解析。對bean:message標簽的解析類似于html:html,Tomcat也將其放入一個單獨的方法_jspx_meth_bean_message_0()中進行。

  bean:message標簽的解析

  代碼清單7:_jspx_meth_bean_message_0()方法片斷

//對message定制標簽的處理方法
private boolean _jspx_meth_bean_message_0(
javax.servlet.jsp.tagext.Tag _jspx_th_html_html_0,
javax.servlet.jsp.PageContext pageContext) throws Throwable {
 JspWriter out = pageContext.getOut();
 /* ----  bean:message ---- */
 org.apache.struts.taglib.bean.MessageTag
 _jspx_th_bean_message_0 =
 (org.apache.struts.taglib.bean.MessageTag)
 _jspx_tagPool_bean_message_key.get(
 org.apache.struts.taglib.bean.MessageTag.class);
 _jspx_th_bean_message_0.setPageContext(pageContext);
 _jspx_th_bean_message_0.setParent(_jspx_th_html_html_0);
 _jspx_th_bean_message_0.setKey("index.title");
 int _jspx_eval_bean_message_0 = _jspx_th_bean_message_0.doStartTag();
 if (_jspx_th_bean_message_0.doEndTag()== javax.servlet.jsp.tagext.Tag.SKIP_PAGE)
  return true;
 _jspx_tagPool_bean_message_key.reuse(_jspx_th_bean_message_0);
  return false;
}
 


  同樣,對html:bean也需要從池中得到一個標簽類的實例,然后設置環境。這里不再贅述。我們只專注對MessageTag定制標簽類特殊的處理部分。定制標簽類的開發不在本文討論范圍之內。在index.jsp中定義了一個bean:message標簽,并設置了一個屬性:bean:message key="index.title"/>。Tomcat在解析時,調用MessageTag對象的key屬性設置方法setKey(),將該屬性置入。然后調用MessageTag的doStartTag()和doEndTag()方法,完成解析。如果doEndTag()方法的返回值為javax.servlet.jsp.tagext.Tag. SKIP_PAGE,表明已經完成解析,返回true,Tomcat將立即停止剩余頁面代碼的執行,并返回。否則把該MessageTag的實例放回池中。

  標簽類對象實例的池化

  為了提高運行效率,Tomcat對所有的定制標簽類進行了池化,池化工作由org.apache.jasper. runtime.TagHandlerPool類完成。TagHandlerPool類主要有兩個方法,代碼如下:

  代碼清單8:TagHandlerPool.java

public class TagHandlerPool {
 private static final int MAX_POOL_SIZE = 5;
 private Tag[] handlers;
 public synchronized Tag get(Class handlerClass) throws JspException {……}
 public synchronized void reuse(Tag handler) {……}
}
 


  TagHandlerPool簡單地實現了對標簽類的池化,其中MAX_POOL_SIZE是池的初始大小,handlers是一個Tag的數組,存儲標簽類的實例。get(Class handlerClass)得到一個指定標簽類的實例,如果池中沒有可用實例,則新實例化一個。reuse(Tag handler)把handler對象放回池中。

  至此,我們對JSP在容器中的運行過程已經了然于胸了。雖然每種JSP容器的解析結果會有差異,但其中的原理都雷同。對于編寫JSP應用,我們并不需要干涉容器中的運行過程,但如果你對整個底層的運行機制比較熟悉,就能對JSP/Servlet技術有更深的認識。

標簽:拉薩 武威 岳陽 亳州 大興安嶺 鄭州 馬鞍山 紅河

巨人網絡通訊聲明:本文標題《JSP的運行內幕》,本文關鍵詞  JSP,的,運行,內幕,JSP,的,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《JSP的運行內幕》相關的同類信息!
  • 本頁收集關于JSP的運行內幕的相關信息資訊供網民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    国产精品18久久久久久久久久久久| 日韩电影免费在线| 亚洲国产精品久久久男人的天堂| 国产一区二区在线观看视频| 日韩欧美自拍偷拍| 视频精品一区二区| 日韩欧美国产精品| 成人黄色免费短视频| 中文字幕在线一区二区三区| 日本亚洲免费观看| 天天综合天天做天天综合| 欧美激情综合五月色丁香| 国产成人亚洲综合色影视| 成人欧美一区二区三区黑人麻豆| 中文字幕不卡在线观看| 久久久99精品免费观看不卡| 不卡一区二区中文字幕| 成人av中文字幕| av在线不卡观看免费观看| 日韩av一级片| 久久机这里只有精品| 久久日一线二线三线suv| 国产一区999| 国产v综合v亚洲欧| 日韩激情在线观看| 免费观看成人鲁鲁鲁鲁鲁视频| 亚洲国产成人在线| 成人欧美一区二区三区白人| 亚洲欧美一区二区在线观看| 亚洲欧洲综合另类| 日韩一区二区三区高清免费看看| 日韩精品专区在线| 亚洲色图19p| 中文字幕日韩欧美一区二区三区| 亚洲天堂中文字幕| 日韩**一区毛片| 国产精品99久久久久久久vr | 97精品超碰一区二区三区| 亚洲成人动漫av| 一区二区三区欧美亚洲| 国产亚洲综合色| 亚洲激情图片qvod| 亚洲欧美一区二区三区极速播放| 午夜激情久久久| 成人午夜免费av| 国产剧情在线观看一区二区| 成人动漫中文字幕| 不卡av电影在线播放| 91精品国产综合久久久久| 日本aⅴ精品一区二区三区 | a4yy欧美一区二区三区| 91在线视频18| 欧美日韩aaa| 精品伊人久久久久7777人| 日韩美女啊v在线免费观看| 一区二区视频在线| 免费av成人在线| 91丝袜美腿高跟国产极品老师| 亚洲黄色小说网站| 奇米777欧美一区二区| 国产乱色国产精品免费视频| 色呦呦国产精品| 成人动漫一区二区三区| 欧美性猛片aaaaaaa做受| 99热这里都是精品| 日韩一级大片在线| 精品国免费一区二区三区| 日韩欧美一区在线| 亚洲日本丝袜连裤袜办公室| 视频一区二区欧美| 91久久奴性调教| 国产肉丝袜一区二区| 久久这里只精品最新地址| 亚洲女同ⅹxx女同tv| 国产综合久久久久影院| 黄一区二区三区| 欧美色综合久久| 国产精品嫩草久久久久| 狠狠色狠狠色合久久伊人| 在线精品视频免费观看| 5858s免费视频成人| 亚洲免费观看高清完整版在线观看 | 国产91色综合久久免费分享| 在线观看一区二区精品视频| 国产精品欧美一区二区三区| 免费成人在线播放| 欧美日韩一级二级| 日韩亚洲欧美在线| 亚洲靠逼com| 99精品热视频| 国产精品视频看| 国产综合色产在线精品| 精品国产免费久久| 日本欧美一区二区三区乱码| 日本久久电影网| 亚洲一卡二卡三卡四卡无卡久久| 91浏览器在线视频| 中文字幕视频一区| 91在线观看下载| 综合中文字幕亚洲| 91在线视频观看| 亚洲精品欧美二区三区中文字幕| 99国产欧美久久久精品| 最好看的中文字幕久久| 一本到高清视频免费精品| 久久精品一区二区三区不卡牛牛| 成人三级伦理片| 国产精品美日韩| 91在线精品一区二区三区| 1区2区3区精品视频| 91美女片黄在线观看| 亚洲五码中文字幕| 欧美日韩久久一区二区| 琪琪久久久久日韩精品| 精品国产a毛片| 精品一区精品二区高清| 日韩一区在线播放| 欧美精品日韩综合在线| 免费观看成人av| 欧美激情自拍偷拍| 国产精品一区二区果冻传媒| 精品国产伦一区二区三区观看方式 | 国产在线日韩欧美| 国产精品麻豆网站| 欧美亚洲国产怡红院影院| 婷婷开心激情综合| 欧美丰满美乳xxx高潮www| 成人免费毛片app| 亚洲尤物视频在线| 精品日本一线二线三线不卡| 粉嫩一区二区三区性色av| 亚洲美腿欧美偷拍| 日韩欧美高清一区| 99精品久久只有精品| 三级欧美韩日大片在线看| 久久久久综合网| 欧美天天综合网| 国产乱子伦一区二区三区国色天香| 自拍偷拍亚洲综合| 日韩欧美国产麻豆| 成人永久看片免费视频天堂| 亚洲精品中文字幕乱码三区| 在线免费一区三区| 成人av影院在线| 日本成人在线不卡视频| 亚洲婷婷在线视频| 精品电影一区二区三区| 欧美综合一区二区三区| 国产精品系列在线观看| 日韩在线a电影| 亚洲欧美日韩综合aⅴ视频| 精品国产伦一区二区三区观看体验 | 成人黄色免费短视频| 免费不卡在线观看| 亚洲制服丝袜一区| 亚洲图片你懂的| 国产欧美一区二区精品性| 欧美成人在线直播| 69堂国产成人免费视频| 欧美日韩在线播| 99久久精品免费| 成人深夜福利app| 国产一区二区不卡老阿姨| 日韩影院在线观看| 亚洲国产精品人人做人人爽| 亚洲天堂精品在线观看| xvideos.蜜桃一区二区| 国产日产精品1区| 久久先锋资源网| 欧美大片免费久久精品三p| 欧美日韩国产片| 欧美亚洲图片小说| 欧美日韩视频不卡| 在线亚洲+欧美+日本专区| 日本韩国欧美三级| 成人久久久精品乱码一区二区三区| 99久久精品免费精品国产| www..com久久爱| 99久久精品一区| 一本大道av伊人久久综合| jlzzjlzz亚洲日本少妇| 91麻豆精品秘密| 91极品视觉盛宴| 欧美影片第一页| 欧美丝袜丝nylons| 日韩一区二区高清| 国产日韩欧美电影| 国产精品久久99| 亚洲男人的天堂av| 亚洲h在线观看| 久久精品国产77777蜜臀| 国产精品资源在线| 高清不卡在线观看av| 成人午夜在线播放| 99久久精品国产一区| 在线日韩国产精品| 欧美tickling网站挠脚心| 中文字幕二三区不卡| 一区二区激情小说| 裸体歌舞表演一区二区|