程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> JSP編程 >> 關於JSP >> JSP編譯成Servlet(三)JSP編譯後的Servlet

JSP編譯成Servlet(三)JSP編譯後的Servlet

編輯:關於JSP

JSP編譯成Servlet(三)JSP編譯後的Servlet


JSP編譯後的Servlet類會是怎樣的呢?他們之間有著什麼樣的映射關系?在探討JSP與Servlet之間的關系時先看一個簡單的HelloWorld.jsp編譯成HelloWorld.java後會是什麼樣。

①HelloWorld.jsp

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

<%

out.println("HelloWorld");

%>

②HelloWorld_jsp.java

package org.apache.jsp;

 

import javax.servlet.*;

import javax.servlet.http.*;

import javax.servlet.jsp.*;

public final class HelloWorld_jsp extends org.apache.jasper.runtime.HttpJspBase

implements org.apache.jasper.runtime.JspSourceDependent {

private static final javax.servlet.jsp.JspFactory _jspxFactory =

javax.servlet.jsp.JspFactory.getDefaultFactory();

private static java.util.Map _jspx_dependants;

public java.util.Map getDependants() {

return _jspx_dependants;

}

public void _jspInit() {

}

public void _jspDestroy() {

}

public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)

throws java.io.IOException, javax.servlet.ServletException {

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=gb2312");

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("\r\n");

out.write("\r\n");

out.write("

\r\n");

out.write("

\r\n");

out.write("

\r\n");

out.write(" \r\n");

out.write("

\r\n");

out.println("HelloWorld");

out.write("\r\n");

out.write("\r\n");

out.write("\r\n");

} catch (java.lang.Throwable t) {

if (!(t instanceof javax.servlet.jsp.SkipPageException)){

out = _jspx_out;

if (out != null && out.getBufferSize() != 0)

try { 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);

}

}

}

經過前面介紹的語法解析及使用訪問者模式對HelloWorld.jsp文件編譯成相應的HelloWorld_jsp.java文件,可以看到Servlet類名是由jsp文件名_jsp拼成。再往下看HelloWorld_jsp.java文件的詳細內容,類包名默認為org.apache.jsp,默認有三個導入“import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.jsp.*;”。

接下去是真正的類主體,jsp生成的java類都必須繼承org.apache.jasper.runtime.HttpJspBase,這個類的結構圖如下,繼承了HttpServlet是為了將HttpServlet的所有功能都繼承下來,另外又實現HttpJspPage接口定義了一個JSP類的Servlet的核心處理方法_jspService,除此之外還有_jspInit和_jspDestroy用於在jsp初始化和銷毀時執行,這些方法其實都是由Servlet的service、init、destroy方法間接去調用,所以jsp生成servlet主要就是實現這三個方法。

\

除了繼承HttpJspBase外還需實現org.apache.jasper.runtime.JspSourceDependent接口,這個接口只有一個返回Map類型的getDependants()方法,Map的鍵值分別為資源名和最後修改時間,這個實現主要是為了記錄某些依賴資源是否過時,依賴資源可能是page指令導入的也可能是標簽文件引用等。在生成servlet時如果jsp頁面做了上述依賴的話則會在servlet類中添加一個static塊,static塊會將資源及最後修改時間添加到Map中。

在jsp類servlet處理過程中會依賴很多資源,比如我要操作會話的話就需要此次訪問的HttpSession對象,比如我要操作Context容器級別的對象就要ServletContext對象,再比如我要獲取servlet配置信息就要ServletConfig對象,最後還需要一個輸出對象用於在處理過程中將內容輸出。這些對象都在核心方法_jspService中使用,作為servlet類要獲取這些對象其實非常簡單,因為這些本身就屬於servlet屬性,有相關方法直接獲取。但這裡因為JSP有自己的標准,所以必須按照它的標准去實現。

具體的JSP標准是怎樣的?首先,為了方便JSP的實現提供一個統一的工廠類JspFactory用於獲取不同的資源;其次,由於按照標准規定不能直接使用servlet上下文,所以需要定義一個PageContext類封裝servlet上下文;最後,同樣按照標准需要定義一個輸出類JspWriter封裝servlet的輸出。所以可以看到PageContext對象通過JspFactory獲取,其他ServletContext對象、ServletConfig對象、HttpSession對象及JspWriter則通過PageContext對象獲取。通過這些對象再加上前面章節語法解析得到的語法樹對象,再利用訪問者模式對語法樹遍歷就可以生成核心處理方法_jspService了。

上面只是介紹了最簡單的一個jsp頁面轉變成servlet的過程,旨在說明jsp到servlet轉化的原理,實際上需要處理很多jsp指令標簽。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved