1. 程式人生 > >jsp初步認識 與其servlet編譯原理

jsp初步認識 與其servlet編譯原理


前面只是介紹一點概念。

JSP的編譯原理:

   jsp實際上一個Servlet物件


 參看tomcat目錄下的各專案的work目錄,生成的jsp編譯成的.java檔案

jsp頁面:

<span style="color:#000000;"><%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>login</title>
	<script type="text/javascript">
	  /* function imgUpdate(){
	       var imgNode= document.getElementsByTagName("img").item(0);
	       //瀏覽器的快取,對相同url的請求無效,改變引數來達到重新整理
	       var t=new Date().getTime();
	       imgNode.src="/WebStudy/Captcha?"+t;
	   }*/
	   onload=function(){
	       var value=document.getElementById("has").value;
	       if(value=="true"){
	           alert("使用者已存在");
	       }
	       var value=document.getElementById("add").value;
	       
	       if(value=="true")
	           alert("使用者建立成功");
	       else if(value=="false")
	           alert("使用者建立失敗");
	     
	   };
	</script>
  </head>
  
  <body>
     <!-- /WebStudy/Captcha 對servelt的請求,需要在web.xml配置servel的路徑對映url-pattern 
    <img src="/WebStudy/Captcha"/><a href="javascript:imgUpdate()">看不清</a>
    <a href="OneServelt">一次轉發</a>
    <a href="/WebStudy/OneServelt">一次轉發</a>
    <a href="">多次轉發</a>
    <a href="ChongServelt">重定向</a>-->
    <form action="LoginServlet" method="post">
            姓名:<input type="text" name="name"/>
             密碼:<input type="password" name="pwd"/>
     <input type="submit" value="提交">
     <input type="hidden" value="<%=request.getAttribute("has") %>" id="has"> 
     <input type="hidden" value="<%=request.getParameter("add") %>" id="add"> 
     </form>
     <a href="LoginServlet">檢視所有使用者</a>
     <a href="MyServletConfig">配置引數</a>
     <a href="MyConTextServlet">留言板</a>
     <a href="PicServlet">picDown</a>
     <a href="RequestServlet">request</a>
      <form action="RequestServlet" method="post" enctype="application/x-www-form-urlencoded">
      Name:<input type="text" name="name"/><br/>
      Age:<input type="text" name="age"/><br/>
            愛好:
       <input type="checkbox" name="hoby" value="MUSIC"/>音樂   
       <input type="checkbox" name="hoby" value="MTV"/>電視  
       <input type="checkbox" name="hoby" value="driver"/>開車<br/>
             性別:
       <input type="radio" name="sex" value="0" checked="checked"/>男 
       <input type="radio" name="sex" value="1"/>女
      <input type="submit" value="提交"/>
    </form>
      <form action="UploadServlet" method="post" enctype="multipart/form-data">
      Name:<input type="text" name="name"/><br/>
      Age:<input type="text" name="age"/><br/>
            愛好:
       <input type="checkbox" name="hoby" value="MUSIC"/>音樂   
       <input type="checkbox" name="hoby" value="MTV"/>電視  
       <input type="checkbox" name="hoby" value="driver"/>開車<br/>
             性別:
       <input type="radio" name="sex" value="0" checked="checked"/>男 
       <input type="radio" name="sex" value="1"/>女
       上傳檔案:
       <input type="file" name="txtFile">
       <input type="file" name="imgFile">
      <input type="submit" value="提交"/>
    </form>
    <a href="cookieServlet">Cookie</a>
    <a href="show.jsp">圖片</a><br/>
    <a href="jsCookie.jsp">js操作Cookie</a><br/>
    <a href="sessionServlet">session</a>
     <form action="getServlet" method="post">
      Name:<input type="text" name="name"/><br/>
      Age:<input type="text" name="age"/><br/>
      <input type="submit" value="提交"/>
     </form>
     驗證碼:
     <form action="validateServlet" method="post">
      Name:<input type="text" name="name"/><br/>
      Age:<input type="text" name="age"/><br/>
      <img src="bufImgServlet"><input type="text" name="validate"/><br/>
      <input type="submit" value="提交"/>
     </form>
  </body>
</html></span>

編譯後的.java檔案
<span style="color:#000000;">package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;

public final class index_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<java.lang.String,java.lang.Long> _jspx_dependants;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
  }

  public void _jspDestroy() {
  }

 </span><pre name="code" class="java"> public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {
<span style="color:#FF0000;">
    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;</span>


    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("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
      out.write("<html>\r\n");
      out.write("  <head>\r\n");
      out.write("    <title>login</title>\r\n");
      out.write("\t<script type=\"text/javascript\">\r\n");
      out.write("\t  /* function imgUpdate(){\r\n");
      out.write("\t       var imgNode= document.getElementsByTagName(\"img\").item(0);\r\n");
      out.write("\t       //瀏覽器的快取,對相同url的請求無效,改變引數來達到重新整理\r\n");
      out.write("\t       var t=new Date().getTime();\r\n");
      out.write("\t       imgNode.src=\"/WebStudy/Captcha?\"+t;\r\n");
      out.write("\t   }*/\r\n");
      out.write("\t   onload=function(){\r\n");
      out.write("\t       var value=document.getElementById(\"has\").value;\r\n");
      out.write("\t       if(value==\"true\"){\r\n");
      out.write("\t           alert(\"使用者已存在\");\r\n");
      out.write("\t       }\r\n");
      out.write("\t       var value=document.getElementById(\"add\").value;\r\n");
      out.write("\t       \r\n");
      out.write("\t       if(value==\"true\")\r\n");
      out.write("\t           alert(\"使用者建立成功\");\r\n");
      out.write("\t       else if(value==\"false\")\r\n");
      out.write("\t           alert(\"使用者建立失敗\");\r\n");
      out.write("\t     \r\n");
      out.write("\t   };\r\n");
      out.write("\t</script>\r\n");
      out.write("  </head>\r\n");
      out.write("  \r\n");
      out.write("  <body>\r\n");
      out.write("     <!-- /WebStudy/Captcha 對servelt的請求,需要在web.xml配置servel的路徑對映url-pattern \r\n");
      out.write("    <img src=\"/WebStudy/Captcha\"/><a href=\"javascript:imgUpdate()\">看不清</a>\r\n");
      out.write("    <a href=\"OneServelt\">一次轉發</a>\r\n");
      out.write("    <a href=\"/WebStudy/OneServelt\">一次轉發</a>\r\n");
      out.write("    <a href=\"\">多次轉發</a>\r\n");
      out.write("    <a href=\"ChongServelt\">重定向</a>-->\r\n");
      out.write("    <form action=\"LoginServlet\" method=\"post\">\r\n");
      out.write("            姓名:<input type=\"text\" name=\"name\"/>\r\n");
      out.write("             密碼:<input type=\"password\" name=\"pwd\"/>\r\n");
      out.write("     <input type=\"submit\" value=\"提交\">\r\n");
      out.write("     <input type=\"hidden\" value=\"");
      out.print(request.getAttribute("has") );
      out.write("\" id=\"has\"> \r\n");
      out.write("     <input type=\"hidden\" value=\"");
      out.print(request.getParameter("add") );
      out.write("\" id=\"add\"> \r\n");
      out.write("     </form>\r\n");
      out.write("     <a href=\"LoginServlet\">檢視所有使用者</a>\r\n");
      out.write("     <a href=\"MyServletConfig\">配置引數</a>\r\n");
      out.write("     <a href=\"MyConTextServlet\">留言板</a>\r\n");
      out.write("     <a href=\"PicServlet\">picDown</a>\r\n");
      out.write("     <a href=\"RequestServlet\">request</a>\r\n");
      out.write("      <form action=\"RequestServlet\" method=\"post\" enctype=\"application/x-www-form-urlencoded\">\r\n");
      out.write("      Name:<input type=\"text\" name=\"name\"/><br/>\r\n");
      out.write("      Age:<input type=\"text\" name=\"age\"/><br/>\r\n");
      out.write("            愛好:\r\n");
      out.write("       <input type=\"checkbox\" name=\"hoby\" value=\"MUSIC\"/>音樂   \r\n");
      out.write("       <input type=\"checkbox\" name=\"hoby\" value=\"MTV\"/>電視  \r\n");
      out.write("       <input type=\"checkbox\" name=\"hoby\" value=\"driver\"/>開車<br/>\r\n");
      out.write("             性別:\r\n");
      out.write("       <input type=\"radio\" name=\"sex\" value=\"0\" checked=\"checked\"/>男 \r\n");
      out.write("       <input type=\"radio\" name=\"sex\" value=\"1\"/>女\r\n");
      out.write("      <input type=\"submit\" value=\"提交\"/>\r\n");
      out.write("    </form>\r\n");
      out.write("      <form action=\"UploadServlet\" method=\"post\" enctype=\"multipart/form-data\">\r\n");
      out.write("      Name:<input type=\"text\" name=\"name\"/><br/>\r\n");
      out.write("      Age:<input type=\"text\" name=\"age\"/><br/>\r\n");
      out.write("            愛好:\r\n");
      out.write("       <input type=\"checkbox\" name=\"hoby\" value=\"MUSIC\"/>音樂   \r\n");
      out.write("       <input type=\"checkbox\" name=\"hoby\" value=\"MTV\"/>電視  \r\n");
      out.write("       <input type=\"checkbox\" name=\"hoby\" value=\"driver\"/>開車<br/>\r\n");
      out.write("             性別:\r\n");
      out.write("       <input type=\"radio\" name=\"sex\" value=\"0\" checked=\"checked\"/>男 \r\n");
      out.write("       <input type=\"radio\" name=\"sex\" value=\"1\"/>女\r\n");
      out.write("       上傳檔案:\r\n");
      out.write("       <input type=\"file\" name=\"txtFile\">\r\n");
      out.write("       <input type=\"file\" name=\"imgFile\">\r\n");
      out.write("      <input type=\"submit\" value=\"提交\"/>\r\n");
      out.write("    </form>\r\n");
      out.write("    <a href=\"cookieServlet\">Cookie</a>\r\n");
      out.write("    <a href=\"show.jsp\">圖片</a><br/>\r\n");
      out.write("    <a href=\"jsCookie.jsp\">js操作Cookie</a><br/>\r\n");
      out.write("    <a href=\"sessionServlet\">session</a>\r\n");
      out.write("     <form action=\"getServlet\" method=\"post\">\r\n");
      out.write("      Name:<input type=\"text\" name=\"name\"/><br/>\r\n");
      out.write("      Age:<input type=\"text\" name=\"age\"/><br/>\r\n");
      out.write("      <input type=\"submit\" value=\"提交\"/>\r\n");
      out.write("     </form>\r\n");
      out.write("     驗證碼:\r\n");
      out.write("     <form action=\"validateServlet\" method=\"post\">\r\n");
      out.write("      Name:<input type=\"text\" name=\"name\"/><br/>\r\n");
      out.write("      Age:<input type=\"text\" name=\"age\"/><br/>\r\n");
      out.write("      <img src=\"bufImgServlet\"><input type=\"text\" name=\"validate\"/><br/>\r\n");
      out.write("      <input type=\"submit\" value=\"提交\"/>\r\n");
      out.write("     </form>\r\n");
      out.write("  </body>\r\n");
      out.write("</html>\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);
    }
  }
}


我們可以看出jsp編譯後是一個public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase

jsp頁面中的html程式碼全部以PrintWrite.wirte()列印流輸出。將jsp頁面的java程式碼複製到_jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)這個函式的相應的位置執行

下來看一下org.apache.jasper.runtime.HttpJspBase是否是一個Servlet?
package org.apache.jasper.runtime;

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.HttpJspPage;
import org.apache.jasper.compiler.Localizer;

<span style="color:#FF0000;">public abstract class HttpJspBase extends HttpServlet</span>
  implements HttpJspPage
{
  private static final long serialVersionUID = 1L;

  public final void init(ServletConfig config)
    throws ServletException
  {
    super.init(config);
    jspInit();
    _jspInit();
  }

  public String getServletInfo()
  {
    return Localizer.getMessage("jsp.engine.info");
  }

  public final void destroy()
  {
    jspDestroy();
    _jspDestroy();
  }

public final void service(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException
  {
    _jspService(request, response);
  }</span>

  public void jspInit()
  {
  }

  public void _jspInit()
  {
  }

  public void jspDestroy()
  {
  }

  protected void _jspDestroy()
  {
  }

  public abstract void _jspService(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse)
    throws ServletException, IOException;
}

可以發現org.apache.jasper.runtime.HttpJspBase這就是一個抽象的servlet,那麼是servlet,就會呼叫其中的service方法,而HttpJspBase覆蓋了,呼叫_jspService方法,顯然我們的jsp編譯後形成的servlet是一個實現了httpjspbase的方法,因此呼叫了我們子類自己的_jspService方法。

既然jsp編譯執行時就是一個servlet,那麼在看servlet中有什麼

隱含物件?為什麼Java程式碼的物件變數不需要什麼宣告定義就能使用?

<span style="color:#000000;">
public void _jspService(final javax.servlet.http.HttpServletRequest <span style="color:#FF0000;">request</span>, final javax.servlet.http.HttpServletResponse <span style="color:#FF0000;">response</span>)
        throws java.io.IOException, javax.servlet.ServletException {

    final javax.servlet.jsp.PageContext <span style="color:#FF0000;">pageContext;</span>
    javax.servlet.http.HttpSession <span style="color:#FF0000;">session</span> = null;
    final javax.servlet.ServletContext <span style="color:#FF0000;">application</span>;
    final javax.servlet.ServletConfig <span style="color:#FF0000;">config</span>;
    javax.servlet.jsp.JspWriter <span style="color:#FF0000;">out</span> = null;
    final java.lang.Object <span style="color:#FF0000;">page</span> = this;
    javax.servlet.jsp.JspWriter <span style="color:#FF0000;">_jspx_out</span> = null;
    javax.servlet.jsp.PageContext <span style="color:#FF0000;">_jspx_page_context</span> = 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;</span>

在編譯後的檔案中,我們發現。原來這些變數,tomcat早已經幫我宣告定義好了,並非不定義(java程式碼是強型別語句,絕對沒有一個變數不定義就可以用)

因此我們就可以使用這些jsp的九大變量了。

既然jsp是一個servlet,我們可以自己定義session,config,servletcontext等等物件變量了

JSP的語法:

我們知道jsp中可以有多段<%     %>java程式碼,實際上就是將這些程式碼複製到_jspservice方法中去,此處定義的全是該函式的區域性變數

如果想在jsp中新增函式,即:在servlet寫函式,那麼需要<%!    %>此處程式碼不會複製到jspservice方法中,而是定義成類成員變數

註釋:<%--   --%>

快速輸出:<%= %>,我們常疑惑,變數為什麼不加;號。因為在編譯時會將其中的程式碼複製到out.print()函式中作為函式引數,一個函式引數怎麼能有;號?

<%@ %>這個有三大屬性:page,include,taglib

靜態匯入和動態匯入區別:

  1:靜態:調入的介面是將程式碼複製到呼叫jsp頁面中,編譯時只生成一個servlet;動態採取req,resp的傳參,編譯時生成各自的servlet檔案

  2:區域性變數在靜態匯入是共享的,動態不共享區域性變數

  3: 靜態包含發生成編譯時。動態包含發生在執行時。由於靜態包含最終編譯成一個Servlet檔案,所以在執行時,它的執行效率要高於動態包含。

請求轉發:

 

jsp異常處理: