前面講了servlet入門實踐現在開始介紹jsp入門實踐,開發環境的搭建請參考我前面的tomcat的文章,jsp入門教程分為上下兩部分,第一部分簡單講解:jsp語法的規范,以及三大編譯指令,七個動作指令和九大內置對象,生命周期講解等。
全部代碼下載:鏈接
JSP全名為Java Server Pages,中文名叫java服務器頁面,其根本是一個簡化的Servlet設計,它[1] 是由Sun Microsystems公司倡導、許多公司參與一起建立的一種動態網頁技術標准。JSP技術有點類似ASP技術,它是在傳統的網頁HTML(標准通用標記語言的子集)文件(.htm,.html)中插入Java程序段(Scriptlet)和JSP標記(tag),從而形成JSP文件,後綴名為(*.jsp)。 用JSP開發的Web應用是跨平台的,既能在Linux下運行,也能在其他操作系統上運行。
第一個jsp程序:
1. 在eclipse中建立動態web工程
2. 在WebContent上右擊建立jsp文件
3. 在jsp文件中輸入如下:
<%@ page language=java contentType=text/html; charset=UTF-8
pageEncoding=UTF-8%>
<% out.print(hello peace); %>
在浏覽器中輸入如下:http://localhost:8080/工程名/NewFile.jsp腳本程序,就是為了在HTML中穿插java代碼,可以包含任意語法真確的java語句,變量,方法或表達式。生成servlet源碼時該處的代碼被放到_jspService()方法中
1. 腳本程序的語法:
<% 代碼片段 %>
就像第一個jsp程序那樣
<%
out.print(hello peace);
%>
注意:腳本中不能出現標簽和jsp元素,記住只能寫java就行;但是可以穿插寫:如下:
<%
for(int i=0;i<5;i++)
{
out.print(hello peace+i);
%>
<%
out.print(換行符穿插在中間了,一樣會被循環輸出);
}//for循環結束
%>
一個聲明語句可以聲明一個或多個變量、方法,供後面的Java代碼使用。在JSP文件中,您必須先聲明這些變量和方法然後才能使用它們。生成servlet源碼時該處的代碼成為類的屬性和方法;
1. JSP聲明的語法:
<%! declaration; [ declaration; ]+ … %>
2. 演示如下:
<%! private int i=10; %>
<%!
public void test(){
int a=0;
int b=2;
a=a+b;
System.out.print(a);
}
%>
查看生成的servlet文件可以知道剛才在jsp聲明的變量和方法,成為了相應的屬性和方法
一個JSP表達式中包含的腳本語言表達式,先被轉化成String,然後插入到表達式出現的地方,作用相當於腳本中的out(輸出)
由於表達式的值會被轉化成String,所以您可以在一個文本行中使用表達式而不用去管它是否是HTML標簽。
表達式元素中可以包含任何符合Java語言規范的表達式,但是不能使用分號來結束表達式。
生成servlet源碼時該處的代碼被放到_jspService()方法中
1. JSP表達式的語法格式
<%= 表達式 %>
2. 演示如下:
<%--在腳本處聲明的變量是局部變量不能帶有修飾符 --%>
<%
String nick=sisi;
int a=10,b=10;
%>
3.jsp表達式:
<%--表達式可以輸出相當於out.write 不需要分號結束--%>
<%=(a-b) %>
<%=nick %>
JSP注釋不會出現在html的源碼中 可以用來注釋jsp的代碼,html注釋會出現在html的源碼中;
1. JSP注釋的語法格式:
<%– 這裡可以填寫 JSP 注釋 –%>
2. 演示如下:
1.jsp注釋:
<%-- 這些注釋不會出現在html的源碼中 可以用來注釋jsp的代碼--%>
JSP編譯指令用來設置與整個JSP頁面相關的屬性;
主要有三大編譯指令:
<%@ page ... %> 定義頁面的依賴屬性,比如腳本語言、error頁面、緩存需求等等
<%@ include ... %> 包含其他文件
<%@ taglib ... %> 引入標簽庫的定義,可以是自定義標簽
Page指令為容器提供當前頁面的使用說明。一個JSP頁面可以包含多個page指令。
1. Page指令的語法格式:
<%@ page attribute=”value” %>
2. 屬性:
3. 演示如下:
<%@ page language=java contentType=text/html; charset=UTF-8
pageEncoding=UTF-8 import=java.util.Random%>
JSP可以通過include指令來包含其他文件。被包含的文件可以是JSP文件、HTML文件或文本文件。包含的文件就好像是該JSP文件的一部分,會被同時編譯執行。
1. Include指令的語法格式如下:
<%@ include file=”url” %>
2. Include指令中的文件名實際上是一個相對的URL。如果您沒有給文件關聯一個路徑,JSP編譯器默認在當前路徑下尋找。
3. 演示如下:
<%-- 1.原理是把被包含的頁面(header.jsp)
的內容翻譯到包含頁面(index.jsp)中,合並成翻譯成一個java源文件,
再編譯運行!!,這種包含叫靜態包含(源碼包含)
2.被包含頁面中不需要出現全局的html標簽了!!!
(如html、head、body)--%>
<%@include file=/common/header.jsp%>
JSP API允許用戶自定義標簽,一個自定義標簽庫就是自定義標簽的集合。Taglib指令引入一個自定義標簽集合的定義,包括庫路徑、自定義標簽。
1. taglib指令的語法:
<%@ taglib uri=”uri” prefix=”prefixOfTag” %>
2. uri為屬性確定的標簽位置,prefix屬性指定標簽庫的前綴。此處後面會進一步介紹;
3. 演示如下:
自己定義的標簽庫
<%@ taglib uri=http://rlovep.com prefix=rlovep %>
動作指令與編譯指令不同,編譯指令時通知servlet引擎的處理消息,而動作指令只是運行時的動作。編譯指令在將JSP編譯成Servlet時起作用,而處理指令通常可替換成JSP腳本,它只是JSP腳本的標准化寫法。
(1)JSP:forward 執行頁面轉向,將請求的處理轉發到下一個頁面。
(2)JSP:param 用於傳遞參數,必須與其他支持參數的標簽一起使用
(3)JSP:include 用於動態引入一個JSP頁面
(4)JSP:plugin 用於下載JavaBean或者Applet到客戶端執行
(5) JSP:useBean 創建一個Javabean實例
(6) JSP:setProperty 設置JavaBean實例的屬性值
(7)JSP:getProperty 獲取JavaBean實例的屬性值
jsp:forward動作把請求轉到另外的頁面。jsp:forward標記只有一個屬性page。
1. 語法格式如下所示:
2. page屬性:page屬性包含的是一個相對URL。page的值既可以直接給出,也可以在請求的時候動態計算,可以是一個JSP頁面或者一個 Java Servlet.
3. 執行forward指令時,用戶請求的地址依然沒有發生改變,仍然是一次請求,但頁面內容完全變為被forward目標頁的內容。執行forward指令轉發請求時,客戶端的請求參數不會丟失。類似於servlet中的
getRequestDispatcher(“/GetData”).forward(request, response);
4. 可以附帶增加額外的請求參數:配合JSP:param動作指令
<%--轉發 jsp:foward
參數 jsp:param
--%>
jsp:include>動作元素用來包含靜態和動態的文件。該動作把指定文件插入正在生成的頁面
1. 語法格式如下:
2. 前面介紹過include的編譯指令與前面不同的是這裡的是動態包含,靜態包含是在JSP文件被轉換成Servlet的時候引入文件,而這裡的jsp:include動作不同,插入文件的時間是在頁面被請求的時候。如果被包含的頁面是jsp一樣會另一個生成servlet;
3. 屬性介紹:
page:被包含頁面的url
flush:布爾屬性,定義在包含資源前是否刷新緩存區。
4. 可以附帶增加額外的請求參數:配合JSP:param動作指令
<%--動態包括 --%>
動態包括:
這三個指令都是與JavaBean相關的指令,其中userBean指令用於在JSP頁面中初始化一個java實例,setProperty指令用於為JavaBean實例的屬性設置值;getProperty指令用於輸出JavaBean實例的屬性。
1. jsp:useBean動作簡單的語法為:
其中,id屬性是JavaBean的實例名,class屬性確定JavaBean的實現類。scope屬性用於指定JavaBean實例的作用范圍。
2. jsp:setProperty的語法格式:
其中,name屬性是要確定JavaBean的實例名,property屬性要確定設置屬性的屬性名,value屬性時要確定屬性名對應的值。
3. jsp:getProperty的語法格式:
其中,name屬性時要確定JavaBean的實例名,name屬性是指定要獲取的屬性名對應的值。
4. 演示如下:
<%--useBean setProperty getProperty --%>
<%--創建Student的實例
實例名稱為student
屬性范圍為page
--%>
<%--設置student的name值 --%> <%--輸出 student的name值--%> name:
param用於設置參數值,這個指令本身不能單獨使用,因此單獨的param指令沒有實際意義,param指令可以與以下指令結合使用
jsp:include jsp:forward jsp:plugin。使用方法上面已經介紹;
plugin指令主要用於下載服務器端的JavaBean或Applet到到客戶端執行,由於程序在客戶端執行,因此客戶端必須安裝虛擬機。該指令用處較少,不做介紹;
需要建立,action.jsp本文件,以級轉發頁面action2.jsp,被包含頁面/common/header1.jsp,JavaBean:Student類
<%--轉發 jsp:foward
參數 jsp:param
--%>
<%--動態包括 --%>
動態包括:
<%--useBean setProperty getProperty --%>
<%--創建Student的實例
實例名稱為student
屬性范圍為page
--%>
<%--設置student的name值 --%> <%--輸出 student的name值--%> name:
JSP腳本中包含9個內置對象,這9個內置對象都是Servlet API接口的實例,只是JSP規范對他們默認進行了初始化(由JSP頁面對應的Servlet的_jspService()方法來創建這些實例)。也就是它們已經是對象,可以直接使用。
JSP初始化該9個對象的地方可以通過生成的servlet類看到如下:
request、response兩個對象是_jspService()方法的形參,當Tomcat調用該方法時會初始化這兩個對象。而page、pageContext、application、config、session、out都是_jspService()方法的局部變量,由該方法完成初始化。
<%@ page language=java contentType=text/html; charset=UTF-8
pageEncoding=UTF-8
%>
<%--out對象:對應jspwriter --%> <% /* for(int i=0;i<=1024;i++){ out.write(a); } System.out.println(當前緩存區大小:+out.getBufferSize()); System.out.println(剩余緩存區大小:+out.getRemaining()); */ //如果不刷新則,123先輸出; //out.flush(); response.getWriter().write(123); %> <%-- application對象:對應servlet中的context 存儲的屬性,是整個應用共享的;同樣可以獲得配置參數; --%> <% //存儲屬性 application.setAttribute(name, peace); %> <%=application.getInitParameter(keys) %> <%-- config對象:對應servlet中的config 用處不是很大 --%> <%=config.getServletName() %> <%-- exception對象:在錯誤頁面中有效,可以獲得異常屬性 親發生錯誤:該對象只有當編譯指令page的isErrorPage=true才有效 <%=exception.getMessage() %> --%> <%-- request對象:對應servlet中的request --%> <%=request.getLocalName() %> <%-- response對象:對應servlet中的response --%> <% response.getWriter().println(hello respose); %> <%-- session對象:對應servlet中的session --%> <% session.setAttribute(pass, 567); %> <%-- pagecontext對象:jsp的頁面對象 可以獲得其他八個對象: --%> <% //獲得其他對象 response.getWriter().write(是否相等?+(out==pageContext.getOut())+
); %> <%--可以往不同的域中存對象 --%> <% pageContext.setAttribute(message, wang); pageContext.setAttribute(age, 22, PageContext.REQUEST_SCOPE); pageContext.setAttribute(qq, 374126165, pageContext.SESSION_SCOPE); pageContext.setAttribute(tl,1881679,pageContext.APPLICATION_SCOPE); //重定向到另一個頁面取得數據: response.sendRedirect(request.getContextPath()+/pageget.jsp); //刪除存儲的對象 pageContext.removeAttribute(age,PageContext.REQUEST_SCOPE ); %>
理解JSP底層功能的關鍵就是去理解它們所遵守的生命周期。JSP生命周期就是從創建到銷毀的整個過程,類似於servlet生命周期,區別在於JSP生命周期還包括將JSP文件編譯成servlet。
訪問:http://localhost:8080/工程名/NewFile.jsp
1. 訪問到NewFile.jsp頁面,tomcat掃描到jsp文件,在/work/Catalina/localhost/stuJsp/org/apache/jsp把jsp文件翻譯成java源文件
(NewFile.jsp -> NewFile_jsp.java) (翻譯)
2. tomcat服務器把java源文件編譯成class字節碼文件 (編譯)
(NewFile_jsp.java ->NewFile_jsp.class)
3. tomcat服務器構造NewFile_jsp類對象
4. tomcat服務器調用NewFile_jsp類裡面方法,返回內容顯示到浏覽器。
第一次訪問jsp:走(1)(2)(3)(4)
之後的訪問:走(4)
注意:jsp文件修改了或jsp的臨時文件被刪除了,要重新走翻譯(1)和編譯(2)的過程
<%!
public void jspInit(){
initVar++;
System.out.println(jspInit(): JSP被初始化了+initVar+次);
}
%>
JSP執行:
<%!
public void jspDestroy(){
destroyVar++;
System.out.println(jspDestroy(): JSP被銷毀了+destroyVar+次);
} %>
JSP與servlet的生命周期對比
Servlet的生命周期:
1)構造方法(第1次訪問)
2)init方法(第1次訪問)
3)service方法
4)destroy方法
Jsp的生命周期:
1)翻譯: jsp->java文件
2)編譯: java文件->class文件(servlet程序)
3)構造方法(第1次訪問)
4)init方法(第1次訪問):_jspInit()
5)service方法:_jspService()
6)destroy方法:_jspDestroy()
<%@ page language=java contentType=text/html; charset=UTF-8
pageEncoding=UTF-8%>
<%! //記錄執行次數: private int initVar=0; private int serviceVar=0; private int destroyVar=0; %> <%! public void jspInit(){ initVar++; System.out.println(jspInit(): JSP被初始化了+initVar+次); } public void jspDestroy(){ destroyVar++; System.out.println(jspDestroy(): JSP被銷毀了+destroyVar+次); } %> <% serviceVar++;// System.out.println(_jspService(): JSP共響應了+serviceVar+次請求); //對各個的執行次數計數 String content1=初始化次數 : +initVar; String content2=響應客戶請求次數 : +serviceVar; String content3=銷毀次數 : +destroyVar; %> <%-- 輸出顯示 --%>
<%=content1 %>
<%=content2 %>
<%=content3 %>
顯示如下: