JSP的運行過程具體以下:java
(1)客戶端發出請求,請求訪問JSP文件。web
(2)JSP容器先將JSP文件轉換成一個Java源文件(Java Servlet源程序),在轉換過程當中,若是發現JSP文件中存在任何語法錯誤,則中斷轉換過程,並向服務端和客戶端返回出錯信息。數據庫
(3)若是轉換成功,則JSP容器將生成的Java源文件編譯成相應的字節碼文件*.class。該class文件就是一個Servlet,Servlet容器會像處理其餘Servlet同樣來處理它。apache
爲了使同窗們更容易理解JSP的運行原理,接下來簡單介紹分析一下JSP所生成的Servlet代碼。設計模式
以HelloWorld.jsp爲例,當用戶第一次訪問HelloWorld.jsp頁面時,該頁面會先被JSP容器轉換爲一個名稱爲HelloWorld_jsp.java的源文件,而後將源文件編譯爲一個名稱爲HelloWorld_jsp.class字節碼文件。若是項目發佈在Tomcat的webapps目錄中,源文件和.class文件能夠在「Tomcat安裝目錄/work/Catalina/localhost/項目名/org/apache/jsp」下找到,如圖1-7所示。數組
JSP的工做模式是請求/響應模式,客戶端首先發出HTTP請求,JSP程序收到請求後進行處理並返回處理結果。在一個JSP文件第一次被請求時,JSP引擎(容器)把該JSP文件轉換成爲一個Servlet,而這個引擎自己也是一個Servlet。JSP的運行過程如圖1-6所示。瀏覽器
圖1-1 JSP的運行原理服務器
JSP的運行過程具體以下:cookie
(1)客戶端發出請求,請求訪問JSP文件。session
(2)JSP容器先將JSP文件轉換成一個Java源文件(Java Servlet源程序),在轉換過程當中,若是發現JSP文件中存在任何語法錯誤,則中斷轉換過程,並向服務端和客戶端返回出錯信息。
(3)若是轉換成功,則JSP容器將生成的Java源文件編譯成相應的字節碼文件*.class。該class文件就是一個Servlet,Servlet容器會像處理其餘Servlet同樣來處理它。
l 跨平臺:因爲JSP是基於Java語言的,它可使用Java API,因此它也是跨平臺的,能夠應用於不一樣的系統中,如Windows、Linux等。當從一個平臺移植到另外一個平臺時,JSP和JavaBean的代碼並不須要從新編譯,這是由於Java的字節碼是與平臺無關的,這也應驗了Java語言「一次編譯,處處運行」的特色。
l 業務代碼相分離:在使用JSP技術開發Web應用時,能夠將界面的開發與應用程序的開發分離開。開發人員使用HTML來設計界面,使用JSP標籤和腳原本動態生成頁面上的內容。在服務器端,JSP引擎(或容器,本書中指Tomcat)負責解析JSP標籤和腳本程序,生成所請求的內容,並將執行結果以HTML頁面的形式返回到瀏覽器。
l 組件重用:JSP中可使用JavaBean編寫業務組件,也就是使用一個JavaBean類封裝業務處理代碼或者做爲一個數據存儲模型,在JSP頁面中,甚至在整個項目中,均可以重複使用這個JavaBean,同時,JavaBean也能夠應用到其餘Java應用程序中。
l 預編譯:預編譯就是在用戶第一次經過瀏覽器訪問JSP頁面時,服務器將對JSP頁面代碼進行編譯,而且僅執行一次編譯。編譯好的代碼將被保存,在用戶下一次訪問時,會直接執行編譯好的代碼。這樣不只節約了服務器的CPU資源,還大大的提高了客戶端的訪問速度。
如何在jsp中編寫java代碼
l Jsp Scriptlets代碼段
n 格式: <% ..java代碼..%>
n 此處聲明的變量都是局部變量,最後編譯到servlet的_jspService()方法中
l Jsp聲明語句
n 格式:<%! ..java代碼..%>
n 此處聲明的java代碼會編譯到_jspService()方法外,定義的都是成員方法、成員變量等
l Jsp表達式
n 格式:<%=..java代碼…%>
n 主要用於代碼數據的輸出.
方式1:設置錯誤狀態碼 (常見)
<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
方式2:設置異常信息
<error-page>
<exception-type>java.lang.ArithmeticException</exception-type>
<location>/error.jsp</location>
</error-page>
其餘
language 解析當前JSP頁面使用的語言
import: jsp導入其餘包
import="java.util.List"
session : 控制jsp頁面 session內置對象是否可使用
在實際開發時,有時須要在JSP頁面靜態包含一個文件,例如HTML文件,文本文件等,這時,能夠經過include指令來實現,include指令的具體語法格式以下所示:
<%@ include file="被包含的文件地址"%> 路徑不須要加項目名
用於頁面中引入標籤庫的,這個指令會在後面介紹JSTL的時候講解
在JSP頁面中,有一些對象須要頻繁使用,若是每次都從新建立這些對象則會很是麻煩。爲了簡化Web應用程序的開發,JSP2.0規範中提供了9個隱式(內置)對象,它們是JSP默認建立的,能夠直接在JSP頁面中使用。
Jsp內置對象中使用固定字符串來表示Servlet中對應的類
request javax.servlet.http. HttpServletRequest 得到用戶請求
session javax.servlet.http. HttpSession 服務器端保存用戶信息
config javax.servlet. HttpServletConfig 當前servlet的配置對象
application javax.servlet. ServletContext 上下文對象,全部用戶共享數據
response javax.servlet.http. HttpServletResponse 返回動態響應信息
out java.io. PrintWriter(javax.servlet.jsp.JspWrite) 用於頁面輸出
pageContext javax.servlet.jsp.PageContext當前JSP對象
page java.lang.Object jsp編譯之後的Servlet對象
exception java.lang.Throwable 表示當前jsp頁面所發生的異常,在錯誤頁面才其做用
l page:表示當前頁,一般沒用。jsp標籤底層使用。
l request:表示一次請求。一般一次請求就一個頁面,但若是使用請求轉發,能夠涉及多個頁面。
l session:表示一次會話。能夠在屢次請求之間共享數據。
l application:表示 一個web應用(項目)。能夠整個web項目共享,屢次會話共享數據。
實際開發中,遵循能小不大的原則
在JSP頁面中,爲了把其餘資源的輸出內容插入到當前JSP頁面的輸出內容中,JSP技術提供了<jsp:include>動做元素,<jsp:include>動做元素的具體語法格式以下所示:
<jsp:include>包含頁面時 先編譯展現 jsp頁面 再展現包含頁面 若是jsp標籤中添加flush屬性 設置爲true 擇
主要用於操做域中的數據
,讓Jsp的代碼更加簡化
替代JSP表達式 <%= %>,用來向瀏覽器輸出內容
l .和[]的區別.
1)[]用於有下標的數據(數組,list集合) .用於有屬性的數據(map,對象)
2)若是屬性名中包含有特殊的字符.必須使用[]
n 導入jar包
n 引入標籤庫taglib
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
uri部分是固定
prefix表示給核心庫起別名,名稱任意定義,建議使用 prefix="c"
n 使用
<c:out value="你好"></c:out>
l JSTL核心庫—if標籤(掌握)
JSTL標籤庫支持EL表達式 c:if test="EL表達式"
<h3>List集合--String</h3>
<%
List<String> list = new ArrayList<String>();
list.add("One");
list.add("Two");
list.add("Three");
pageContext.setAttribute("list", list);
%>
<c:forEach items="${list}" var="str">
${str}<br>
</c:forEach>
<h3>List集合--JavaBean</h3>
<%
List<User> uses = new ArrayList<User>();
uses.add(new User("p001", "zhangsan", 18));
uses.add(new User("p002", "李四", 18));
uses.add(new User("p003", "王武", 18));
pageContext.setAttribute("uses", uses);
%>
<c:forEach items="${uses}" var="user">
${user.uname}<br>
</c:forEach>
l Model-View-controller的縮寫
理念:數據處理和數據顯示相分離
Servlet+JSP+javaBean
<%out 和response同時輸出內容response輸出的內容在前面%> 由於 out和response都存在緩衝區 out輸出前是將內容放到response緩衝區 因此response比out先輸出
<body>
<%
//使用 JSP 的輸出流
out.print("first");
//使用 Servlet 的輸出流
response.getWriter().print("second");
%>
</body>
分類 |
內置對象名稱 |
描述 |
做用域 |
pageScope |
page做用域 |
requestScope |
request做用域 |
|
sessionScope |
session做用域 |
|
applicationScope |
application做用域 |
|
請求參數 |
param |
得到一個參數 |
paramValues |
得到一組參數 |
|
請求頭 |
header |
得到一個請求頭 |
headerValues |
得到一組請求頭 |
|
JSP上下文對象 |
pageContext |
|
全局初始化參數 |
initParam |
|
cookie |
cookie |
|
l 得到指定做用域的數據
<%--初始化數據--%>
<%
pageContext.setAttribute("name", "pValue");
request.setAttribute("name", "rValue");
session.setAttribute("name", "sValue");
application.setAttribute("name", "aValue");
%>
<%--使用JSP腳本得到--%>
<%=pageContext.getAttribute("name") %> <!-- 若是沒找到 返回null -->
<%=request.getAttribute("name") %>
<%=session.getAttribute("name") %>
<%=application.getAttribute("name") %>
<%--得到指定做用域的數據--%>
${ pageScope.name } <!-- 返回的是"" -->
${ requestScope.name }
${ sessionScope.name }
${ applicationScope.name }
<%--依次得到數據--%>
${ name } <%-- 底層使用 pageContext.findAttribute("name") ,依次從page、request、session、application得到數據,若是都沒有返回null --%>
l 請求參數
//請求路徑:/day18/a_el.jsp?username=jack&hobby=xxx&hobby=yyy
<%--
param.xxx 對應 request.getParameter("xxx");
paramValue.xxx 對應 request.getParameterValues("xxx");
--%>
${param.username} <br/>
${param.hobby}<br/> <%--得到第一個參數--%>
${paramValues.hobby} <br/> <%--得到一組數據,使用數組 --%>
${paramValues.hobby[1]} <br/> <%--若是是數組,可使用下標得到 --%>
l 請求頭
<%--
header.xxx 對應 request.getHeader("xxx");
headerValues.xxx 對應 request.getHeaders("xxx");
--%>
${header.accept} <br/>
\${header.accept-Encoding} <br/> <%--非法的,有異常,「-」被解析成減號。使用"/"進行單個el表達式轉義 --%>
${header['accept-Encoding']} <br/>
${headerValues['accept-Encoding'][0]} <br/>
l pageContext
<%--
pageContext 對應 pageContext對象
--%>
jsp: <%= ((HttpServletRequest)pageContext.getRequest()).getContextPath() %> <br/>
el : ${pageContext.request.contextPath} <br/>
能夠看到<c:if>標籤有三個屬性,接下來將針對這三個屬性進行講解,具體以下:
l test屬性用於設置邏輯表達式;
l var屬性用於指定邏輯表達式中變量的名字;
l scope屬性用於指定var變量的做用範圍,默認值爲page。若是屬性test的計算結果爲true,那麼標籤體將被執行,不然標籤體不會被執行。
語法1:迭代包含多個對象的集合
<c:forEach [var="varName"] items="collection" [varStatus="varStatusName"]
[begin="begin"] [end="end"] [step="step"]>
body content
</c:forEach>
語法2:迭代指定範圍內的集合
<c:forEach [var="varName"] [varStatus="varStatusName"] begin="begin"
end="end" [step="step"]>
body content
</c:forEach>
在上述語法格式中,能夠看到<c:forEach>標籤有多個屬性。接下來針對這些屬性進行講解,具體以下:
l var屬性用於指將當前迭代到的元素保存到page域中的名稱;
l items屬性用於指定將要迭代的集合對象;
l varStatus用於指定當前迭代狀態信息的對象保存到page域中的名稱;
l begin屬性用於指定從集合中第幾個元素開始進行迭代,begin的索引值從0開始,若是沒有指定items屬性,就從begin指定的值開始迭代,直到迭代結束爲止;
l step屬性用於指定迭代的步長,即迭代因子的增量。
<c:forEach>標籤在程序開發中常常會被用到,所以熟練掌握<c:forEach>標籤是頗有必要的,接下來,經過幾個具體的案例來學習<c:forEach>標籤的使用
4.若是JSP表單元素的值爲空,如何避免null出如今頁面上?
答:能夠寫一個簡單的函數對空值進行處理,判斷值是否爲空,若是爲空就返回空字符串。實例代碼以下:
<%!
String blanknull(String e)
{
return (e==null)?"":s;
} %>
<%
<input type="text" name="username" value="<%=blanknull(username)%>"
%>
、如何避免JSP頁面自動生成session對象?爲何要這麼作?
答:在默認狀況下,在對一個JSP頁面發出請求時,若是session尚未創建,那麼JSP頁面會自動爲請求建立一個session對象,可是session是比較消耗資源的,若是沒有必要保持和使用session,就不該該建立session,例如一些只用來宣傳產品的網頁,每每不必使用session來保存信息,能夠在JSP中使用page指令進行設置,避免JSP頁面爲每一個請求都自動建立session。實例代碼以下:
<%@page session="false"%>
3八、在JSP頁面中如何刪除一個cookie?
答:
<%
Cookie cookie=new Cookie("cookie名","cookie值");
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);%>
刪除session session.removeattribute() session.attribute(null)
四、JSTL的功能,爲何要用JSTL?(JavaServer Pages Standard Tag Library)
答:
功能:主要用於基本輸入輸出、流程控制、循環、XML文件剖析、數據庫查詢及國際化和文字格式標準化的應用等。
緣由:在jsp頁面作條件判斷或者循環操做並輸出時,比較費力。
<%
//放置空對象
List list1=null;
request.setAttribute("l1", list1);
//放置空集合
List list2=new ArrayList();
//list2.add("1");
request.setAttribute("l2", list2);
//放置空字符串
request.setAttribute("kong", "");
request.setAttribute("i", 5);
%>
${empty l1 }<br> true
${empty l2 }<br> true
${empty kong }<br> true
${i>6?"i>6":"i<6" }
</body>
User p1=new User();
User p2=null;
request.setAttribute("p1", p1);
request.setAttribute("p2", p2);
%>
${empty p1 } false
${empty p1 } true
注意:list集合和對象 空參構造 結果不一樣
一、forward和redirect的區別
1.從地址欄顯示來講
forward是服務器請求資源,服務器直接訪問目標地址的URL,把那個URL的響應內容讀取過來,而後把這些內容再發給瀏覽器.瀏覽器根本不知道服務器發送的內容從哪裏來的,因此它的地址欄仍是原來的地址.
redirect是服務端根據邏輯,發送一個狀態碼,告訴瀏覽器從新去請求那個地址.因此地址欄顯示的是新的URL.
2.從數據共享來講
forward:轉發頁面和轉發到的頁面能夠共享request裏面的數據.
redirect:不能共享數據.
3從運用地方來講
forward:通常用於用戶登錄的時候,根據角色轉發到相應的模塊.
redirect:一般用於用戶註銷登錄時返回主頁面和跳轉到其它的網站等.
4.從效率來講
forward:高.
redirect:低.
5.forward不須要加項目名 由於是在項目中跳轉
Redirect 須要加項目名
3.jsp中的@page指令 中有errorpage屬性設置錯誤頁面的. session 設置成false關閉jsp自動生成session 節約服務器資源