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

JSP 原理

編輯:關於JSP

JSP 原理


1、JSP的由來

\

  在JSP出現之前,為了實現動態網頁的效果,服務器端利用 Servlet 的輸出流向客戶端發送HTML標簽以及HTML頁面中的內容,但是在多數動態網頁中,絕大部分內容是靜態的,只有少量內容需要動態實現。但是為了這少量的動態內容,程序猿依然要用Servlet 輸出其中所有的靜態內容,這就使得整個Servlet 程序代碼非常臃腫,導致Servlet 的開發效率非常低下。

  為了彌補Servlet 的缺陷,SUN公司在Servlet 的基礎上推出了JSP(Java Server Pages)技術作為解決方案。JSP是簡化Servlet 編寫的一種技術,它由態部分和動態部分兩部分組成,靜態部分用於寫入標准的HTML標簽及內容;動態部分就是嵌入的Java代碼與JSP動態標簽了。通過這種方式,使靜態的部分直接使用HTML代碼編寫,對於動態的內容則使用 JAVA 腳本編寫。

  對於Servlet 來說,無論動態、靜態都用Java代碼編寫;而JSP則將靜態的分出來,全部用HTML寫(底層還是使用Java包裝);動態的用Java 寫。究其本質還是一樣的,所以說,JSP的本質就是一種特殊的Servlet 。


2、JSP的語法


  JSP = HTML + Java 腳本 + JSP 標簽(指令),JSP中三種Java 腳本:

  ● <%...%>:Java代碼片段,用於定義0~N條Java 語句,方法中能夠寫什麼,這裡面就能放什麼;

  ● <%= %>:Java 表達式,用於輸出一條表達式或變量的結果。 response.getWriter().print() 方法中能夠寫什麼,這裡面就能夠寫什麼;

  ● <%! … %> :聲明,用來創建類的成員變量和成員方法,Java 類中能夠寫什麼,這裡面就能夠寫什麼,要注意的是,裡面的內容不在 _jspService() 方法之內,直接被JSP轉化後的類體包含。


3、JSP 原理


  前面已經闡述過,JSP的本質實質是一種特殊形式的 Servlet :

  ● 當用戶訪問一個JSP頁面時,會向 Servlet 容器(這裡是Tomcat)發出請求;

  ● 如果這個JSP頁面是第一次被訪問或者這個頁面被改動過時,服務器會把JSP 編譯成 .java文件,當然,這個.java 就是一個servlet類,然後再把 .java 文件編譯成.class 文件。因為編譯會耗費一定時間,所以頁面在第一次被訪問或改動後被訪問時會花費較長的訪問時間;

  ● 創建該類對象,最後由Servlet 容器調用它的service() 方法;

  ● 第二次請求同一JSP時,直接調用service() 方法。


4、驗證JSP原理


  首先,我們來寫一個hello.jsp文件:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%
String s = request.getHeader("User-Agent");
%>



  
    My JSP 'a.jsp' starting page
    
	
	
	    
	
	
	

  
  
  
 
	
	  姓名
	  年齡
	  性別
	
<%
	for(int i = 0; i < 10; i++) {
%>	
	
	  張三
	  18
	  男
	
<%  }%>




<%!
public void fun1() {
	System.out.println("hello");
}

%>
<%int a = 10; %>

<%a++; %>

<%=a %>

  


  然後讓我們在tomcat 下找到被編譯成的.java 文件,為了節省空間,我把一些解釋標記在代碼注釋中:

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/7.0.42
 * Generated at: 2015-12-27 10:03:19 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

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

public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {


public void fun1() {  //要特別注意,這是在<%! %>中定義的方法,沒有被放在service方法中
	System.out.println("hello");
}


  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map _jspx_dependants;

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

  public java.util.Map 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() {
  }

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

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

String s = request.getHeader("User-Agent");  //它的原身是String s = request.getHeader("User-Agent");,被直接拿過來了


      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");   //這些都是HTML代碼,底層被包裝成和Servlet 一樣的實現方式
      out.write("  \r\n");
      out.write("    My JSP 'a.jsp' starting page\r\n");
      out.write("    \r\n");
      out.write("\t\r\n");
      out.write("\t\r\n");
      out.write("\t    \r\n");
      out.write("\t\r\n");
      out.write("\t\r\n");
      out.write("\t\r\n");
      out.write("\r\n");
      out.write("  \r\n");
      out.write("  \r\n");
      out.write("  \r\n");
      out.write(" \r\n");
      out.write("\t\r\n");
      out.write("\t  姓名\r\n");
      out.write("\t  年齡\r\n");
      out.write("\t  性別\r\n");
      out.write("\t\r\n");

	for(int i = 0; i < 10; i++) {  //這也是直接拿過來的

      out.write("\t\r\n");
      out.write("\t\r\n");
      out.write("\t  張三\r\n");
      out.write("\t  18\r\n");
      out.write("\t  男\r\n");
      out.write("\t\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');
      out.write('\n');
int a = 10;   //這些是定義的變量,可以看到是放在了service方法中的
      out.write("\r\n");
      out.write("\r\n");
a++; 
      out.write("\r\n");
      out.write("\r\n");
      out.print(a );
      out.write("\r\n");
      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);
    }
  }
}

  得出結論,JSP中雖然能直接寫出HTML代碼,但是在底層依然是被包裝成 Servlet 實現方式的,所以更印證了JSP是特殊的Servlet 。

  其次,在<% %> 和 <%= %> 腳本中定義的Java 代碼都會放在JSP 的 _jspService() 方法中(實際上就是Servlet中的service 方法),而<%! %> 腳本中定義的卻會放到 hello_jsp 類的成員位置的,這一點很重要,因為JSP中鼎鼎大名的九大內置對象是在_jspService() 方法中初始化的,只有在本方法中才能夠使用內置對象,所以<%! %> 腳本中是不能使用內置對象的(在實際開發中,本腳本很少用到)。


5、JSP和HTML、Servlet 的比較


  ● Servlet:

    缺點:不適合設置html響應體,需要大量的response.getWriter().print("")

    優點:動態資源,可以編程。

  ● HTML:

    缺點:html是靜態頁面,不能包含動態信息

    優點:不用為輸出html標簽而發愁

  ● JSP:

    優點:在原有html的基礎上添加java腳本,構成jsp頁面。


6、JSP 和 Servlet 的分工


  在設計中,JSP和Servlet 是相互配合使用的,其分工為:

  ● JSP:

    作為請求發起頁面,例如顯示表單、超鏈接,並將請求發給 Servlet ;

    作為請求結束頁面,例如顯示數據。

  ● Servlet:

    作為請求中處理數據的環節。


  小結:JSP頁面必須要在JSP服務器內運行,如tomcat weblogic,jboss(這些都是 apache 中的子項目,apache是 Web 應用服務器,而 tomcat 等可以說是JSP或 Servle 的 Web 容器,簡稱Servlet 容器)等;JSP頁面的訪問者無須安裝任何客戶端,也不需要運行Java 環境,因為JSP頁面輸送到客戶端的是標准HTML頁面。




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