JSP頁面翻譯原理

來源:互聯網
上載者:User

眾所周知,每一個JSP頁面都會被Web容器編譯成一個Java類,供web容器調用,並且產生HTML葉面回饋給使用者。而瞭解其中的變異方法和規則,對我們學習JSP是非常有好處的,可以說學習好了這個編譯原理,就已經學習好了大部分的JSP知識,剩下的工作就只剩下熟記一些tablib和反覆應用以使自己更加熟練而已了。。

先來看一下JSP頁面所對應的Class的基本結構。每一個JSP頁面都會被編譯成成如下的格式樣子,先給一個大致的印象,詳細的說明在後面。


public class My$jsp extends HttpJspBase {

static {}

public date$jsp() {}

private static boolean _jspx_inited = false;

public final void _jspx_init()
throws org.apache.jasper.runtime.JspException {};

public void _JSP pageservice(HttpServletRequest request,
HttpServletResponse response)
throws java.io.IOException, ServletException {

JspFactory _jspxFactory = null;
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;

Object page = this;
String _value = null;
try {
if (_jspx_inited == false) {
synchronized (this) {
if (_jspx_inited == false) {
_jspx_init();
_jspx_inited = true;
}
}
}
_jspxFactory = JspFactory.getDefaultFactory();
response.setContentType("text/html;charset=ISO-8859-1");
pageContext = _jspxFactory.getPageContext(this, request, response,
"", true, 8192, true);


application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();

// HTML // begin
out.write("<html>/r/n<head>/r/n<title>Date</title>/r/n" +
"</head>/r/n<body>/r/n<h3>/r/n" +
"The date is/r/n");
// end
// begin
out.println((new java.util.Date()).toString());
// end
// HTML // begin
out.write("/r/n </h3>/r/n </body>/r/n</html>");
// end

} catch (Throwable t) {
if (out != null && out.getBufferSize() != 0) {
out.clearBuffer();
}
if (pageContext != null) {
pageContext.handlePageException(t);
}
} finally {
if (_jspxFactory != null) {
_jspxFactory.releasePageContext(pageContext);
}
}
}
}

我們可以清楚地看到,這裡面最重要的函數就是pageservice,web容器在編譯好一個JSP類以後,就申請這個類的對象,並且直接調用pageservice來獲得Response,最後返回給客戶。作為細節,我們可以總結如下:

  1. 所有的JSP頁面翻譯出來的class,都從HttpJspBase繼承,並且命名為PageName$jsp
  2. 在第一次調用pageservice函數的時候,該class會進行一次初始化,而這個初始化函數是_jspx_init,如果我們想,我們還可以自訂這個函數,來實現JSP頁面的初始化。
  3. <% %> 這樣的代碼被轉換成什麼了?
    這樣的代碼被直接轉成Java代碼放到pageservice函數裡面。
  4. <%! %> 這樣的代碼被轉換成什麼了?
    這樣的代碼被翻譯成成員函數和成員變數,也就是說,這些聲明在JSP的生命週期內都是存在的。
  5. HTML代碼呢?
    html代碼直接被寫到PrintWriter裡面回饋給使用者。非常的直接
  6. 為什麼JSP頁面有那麼多省寫方式,比如說session , out , page , context之類。
    這都是在pageservice裡面定義的臨時變數,具體的初始化可以參看上面的例子代碼,每一次調用JSP頁面,這些變數都會被重新初始化一次。當然我們也可以方便的聲明自己的變數。
  7. 省寫方式<%= object.doSomething()%> 這麼理解? 這種省寫方式調用doSomething所得到的Object的toString(),然後直接寫到out裡面。相當於:
    out.print(object.doSomethiing().toString())
  8. JavaBean 裡面的scope定義了範圍範圍,這個範圍在這裡的意思是?
    這是Bean物件控點儲存的地方的意思。我們可以想象一下,一個page範圍的Bean只是pageservice裡面的一個局部變數,當一次處理結束後,這個變數就會被Java虛擬機器回收。而session變數。而request層級的Bean就應該是JSP頁面的成員變數。而session和application則不能在JSP頁面class裡面儲存,而應該儲存在JSP頁面的調用對象裡面。
  9. 關於<%@ page %>命令,這個就太簡單了,只是一個一個的對應為response.setContentType()的語句而已。
  10. 關於JSP頁面轉向問題。這個語句被翻譯為getServletContext().getRequestDispatcher("/List.jsp").forward(req, res);語句。
  11. <%@ include file="included.jsp" %> 遇到這個語句,JSP翻譯器就會把這個檔案的代碼和現在檔案的代碼混合然後一起編譯,產生JSP類。這個方法很好,可以讓我們統一文檔的樣式,比如說吧header寫成一個檔案,,而把footer也寫成一個JSP ,並且在index.html裡面把這兩個檔案包含近來,這樣,不管Content怎麼變,上下樣式都不會變,有利於樣式的統一。

以上是JSP翻譯過程的簡單探討,更加詳細的細節可以參考tomcat的原始碼,瞭解這些原理對於學習JSP來說,是非常重要的,能大大的提高學習的效率。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.