如圖:php
JSP全名爲Java Server Pages,其根本是一個簡化的Servlet設計,他實現了再Java當中使用HTML標籤。JSP是一種動態網頁技術標準也是JavaEE的標準。JSP與Servlet同樣,是在服務器端執行的。css
JSP實際上就是Servlet。JSP這門技術的最大的特色在於:寫jsp就像在寫html,但它相比html而言,html只能爲用戶提供靜態數據,而Jsp技術容許在頁面中嵌套java代碼,爲用戶提供動態數據。html
Servlet:服務器端的小應用程序。適合編寫Java邏輯代碼,若是編寫網頁內容------->費時費力,太苦java
HTML:靜態內容web
jsp(java server pages):適合編寫輸出動態內容,但不適合編寫Java邏輯數據庫
JSP編程
Servlet數組
jsp=html+java腳本+jsp標籤(指令)瀏覽器
jsp中無需建立便可使用的對象一共有9個,稱爲九大內置對象。緩存
3種java腳本:
jsp實際上是一種特殊的Servlet
一、IE瀏覽器在訪問JSP頁面時,Web服務器是如何調用並執行一個jsp頁面的?(Servlet)
二、Web服務器在執行jsp頁面時,是如何把Jsp頁面中的html排版標籤發送到客戶端的?
三、Jsp頁面中的java代碼服務器是如何執行的?
四、Web服務器在調用jsp時,會給jsp提供一些什麼java對象(內置對象)?
Servlet:控制器。重點編寫java代碼邏輯。(獲取表單數據、處理業務邏輯、分發轉向)
JSP:代碼顯示模板。重點在於顯示數據。(爲何顯示數據不直接用.html文件呢?由於.jsp文件中能夠插入java代碼顯示回顯消息,簡言之,jsp功能更強大)
JSP的模版元素:簡言之就是網頁的靜態內容
例如:html標籤和普通文本。
JSP的腳本:
<%= 2 + 3 %> 等價於out.print(2 + 3);
註釋:
特色:安全,省流量
特色:不安全,費流量
JSP指令(directive)是爲JSP引擎而設計的,它們並不直接產生任何可見輸出,而只是告訴引擎如何處理JSP頁面中的其他部分。
在JSP 2.0規範中共定義了三個指令:
例如:
做用:
屬性:
<%@ page import="java.util.Date, java.util.List" %>
或者:
<%@ page import="java.util.Date" %>
<%@ page import="java.util.List" %>
import java.lang.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
若是寫"/"則表明當前應用的目錄下,絕對路徑。
若是不寫"/"則表明相對路徑。
例如:<%@ page pageEncoding="gbk" %>
例如:${1+1} 等價於out.print(1+1);
include指令用於引入其它JSP頁面,若是使用include指令引入了其它JSP頁面,那麼JSP引擎將把這兩個JSP翻譯成一個servlet。因此include指令引入一般也稱之爲靜態引入。
<%@ include file="/include/header.jsp" %>
<jsp:include page="/include/header.jsp"></jsp:include>
二者的區別:轉譯(翻譯)的時間段不一樣
使用原則:能用靜的就不用動的。緣由之一是:能夠省略一些代碼的書寫。
JSP API容許用戶自定義標籤,一個自定義標籤庫就是自定義標籤的集合。
Taglib指令引入一個自定義標籤集合的定義,包括庫路徑、自定義標籤。
Taglib指令的語法:
<%@ taglib uri="uri" prefix="prefixOfTag" %> 複製代碼
uri屬性肯定標籤庫的位置,prefix屬性指定標籤庫的前綴。
等價的XML語法:
<jsp:directive.taglib uri="uri" prefix="prefixOfTag" /> 複製代碼
做用:在JSP頁面中導入JSTL標籤庫。替換jsp中的java代碼片斷。
<%@ taglib uri=" java.sun.com/jsp/jstl/co…" prefix="c" %>
prefix:前綴(至關於從新給uri起個名字)
示例:
<%   if (5 > 3) {   out.print(5);   } %> <%-- 上下二種方式是等價的 --%> <c:if test="${5>3}">   aaa </c:if> 複製代碼
下面的這種方式很好用!後面慢慢體會。
使用標籤的形式來表示一段java代碼。
JSP行爲標籤使用XML語法結構來控制servlet引擎。它可以動態插入一個文件,重用JavaBean組件,引導用戶去另外一個頁面,爲Java插件產生相關的HTML等等。
行爲標籤只有一種語法格式,它嚴格遵照XML標準:
<jsp:action_name attribute="value" /> 複製代碼
行爲標籤基本上是一些預先就定義好的函數,下表羅列出了一些可用的JSP行爲標籤:
指在JSP的<%=%> 和<% %>中能夠直接使用的對象,服務器給咱們建立好的對象,直接拿過來用就好了。
例如:
<%=request.getParameter("name") %> <%    Student stu = new Student();    stu.setName("tom");   out.print(stu.getName());    // request.getRequestDispatcher("/7.jsp").forward(request, response); %> 複製代碼
request對象是javax.servlet.http.HttpServletRequest類的實例。每當客戶端請求一個頁面時,JSP引擎就會產生一個新的對象來表明這個請求。
request對象提供了一系列方法來獲取HTTP信息頭,包括表單數據,cookies,HTTP方法等等。
接下來將會介紹一些在JSP編程中經常使用的獲取HTTP信息頭的方法。詳細內容請見下表:
在這個例子中,咱們會使用HttpServletRequest類的getHeaderNames()方法來讀取HTTP信息頭。這個方法以枚舉的形式返回當前HTTP請求的頭信息。
獲取Enumeration對象後,用標準的方式來遍歷Enumeration對象,用hasMoreElements()方法來肯定何時中止,用nextElement()方法來得到每一個參數的名字
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.io.*,java.util.*" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body> <h2>HTTP 頭部請求實例</h2> <table width="100%" border="1" align="center"> <tr bgcolor="#949494"> <th>Header Name</th><th>Header Value(s)</th> </tr> <% Enumeration headerNames = request.getHeaderNames(); while(headerNames.hasMoreElements()) { String paramName = (String)headerNames.nextElement(); out.print("<tr><td>" + paramName + "</td>\n"); String paramValue = request.getHeader(paramName); out.println("<td> " + paramValue + "</td></tr>\n"); } %> </table> </body> </html> 複製代碼
response 對象是 javax.servlet.http.HttpServletResponse 類的一個實例。就像服務器會建立request對象同樣,它也會建立一個客戶端響應。
response對象定義了處理建立HTTP信息頭的接口。經過使用這個對象,開發者們能夠添加新的cookie或時間戳,還有HTTP狀態碼等等。
下表列出了用來設置HTTP響應頭的方法,這些方法由HttpServletResponse 類提供:
接下來的例子使用setIntHeader()方法和setRefreshHeader()方法來模擬一個數字時鐘:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.io.*,java.util.*" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body> <h2>自動刷新實例</h2> <% // 設置每隔5秒自動刷新 response.setIntHeader("Refresh", 5); // 獲取當前時間 Calendar calendar = new GregorianCalendar(); String am_pm; int hour = calendar.get(Calendar.HOUR); int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); if(calendar.get(Calendar.AM_PM) == 0) am_pm = "AM"; else am_pm = "PM"; String CT = hour+":"+ minute +":"+ second +" "+ am_pm; out.println("當前時間: " + CT + "\n"); %> </body> </html> 複製代碼
咱們在瀏覽網頁的時候,常常須要向服務器提交信息,並讓後臺程序處理。瀏覽器中使用 GET 和 POST 方法向服務器提交數據。
GET方法將請求的編碼信息添加在網址後面,網址與編碼信息經過"?"號分隔。以下所示:
www.runoob.com/hello?key1=… GET方法是瀏覽器默認傳遞參數的方法,一些敏感信息,如密碼等建議不使用GET方法。
用get時,傳輸數據的大小有限制 (注意不是參數的個數有限制),最大爲1024字節。
一些敏感信息,如密碼等咱們能夠經過POST方法傳遞,POST提交數據是隱式的。
POST提交數據是不可見的,GET是經過在url裏面傳遞的(能夠看一下你瀏覽器的地址欄)。
JSP使用getParameter()來得到傳遞的參數,getInputStream()方法用來處理客戶端的二進制數據流的請求。
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %> <!DOCTYPE html> <html> <head> <title>表單信息</title> </head> <body> <form action="Demo1.jsp" method="post"> <input type="text" name="name"/><br> <input type="text" name="url"/><br> <input type="checkbox" name="mao" checked="checked"/>貓<br> <input type="checkbox" name="gou"/>狗<br> <input type="checkbox" name="ji" checked="checked"/>雞<br> <input type="checkbox" name="ya"/>鴨<br> <input type="submit" value="提交"> </form> </body> </html> 複製代碼
<%@ page import="java.util.Enumeration" %> <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JSP</title> </head> <body> <h1>讀取參數信息</h1> <table align="center" border="1" width="100%"> <tr bgcolor="#f0f8ff"> <th>參數名</th> <th>對應值</th> </tr> <% Enumeration<String> parameterNames = request.getParameterNames(); request.setCharacterEncoding("utf-8"); while (parameterNames.hasMoreElements()){ String name = parameterNames.nextElement(); out.println("<tr><td>"+name+"</td>\n"); String url = request.getParameter(name); out.println("<td>"+url+"</td></tr>\n"); } %> </table> <% %> </body> </html> 複製代碼
PageContext:pageConext
存放的數據僅在當前頁面有效。開發時使用較少。當前頁面存放數據用表單標籤中的 ,且該存值方式用戶看不到。
ServletRequest: request
存放的數據在一次請求(轉發:能夠傳數據)內有效。使用很是多。
HttpSession: session
存放的數據在一次會話(屢次請求)中有效。使用的比較多。例如:存放用戶的登陸信息、購物車功能。
ServletContext: application
存放的數據在整個應用範圍內都有效。由於範圍太大,應儘可能少用。用於統計在線人數。
會話可簡單理解爲:用戶開一個瀏覽器,點擊多個超連接,訪問服務器多個web資源,而後關閉瀏覽器,整個過程稱之爲一個會話。
每一個用戶在使用瀏覽器與服務器進行會話的過程當中,不可避免各自會產生一些數據,程序要想辦法爲每一個用戶保存這些數據。
例如:用戶點擊超連接經過一個servlet購買了一個商品,程序應該想辦法保存用戶購買的商品,以便於用戶點結賬servlet時,結賬servlet能夠獲得用戶購買的商品爲用戶結賬。
思考:用戶購買的商品保存在request或servletContext中行不行?答:不行。
保存會話數據的兩種技術:
當用戶使用瀏覽器再去訪問服務器中的web資源時,就會帶着各自的數據去。這樣,web資源處理的就是用戶各自的數據了。
因爲session爲用戶瀏覽器獨享,因此用戶在訪問服務器的web資源時,能夠把各自的數據放在各自的session中,當用戶再去訪問服務器中的其它web資源時,其它web資源再從用戶各自的session中取出數據爲用戶服務。
無狀態是指,當瀏覽器發送請求給服務器時,服務器響應客戶端請求。可是當同一個瀏覽器再次發送請求給服務器時,服務器並不知道它就是剛纔那個瀏覽器。簡單來講,就是服務器不會去記得你,因此就是無狀態協議。
Cookie是存儲在客戶機的文本文件,它們保存了大量軌跡信息。在servlet技術基礎上,JSP顯然可以提供對HTTP cookie的支持。
一般有三個步驟來識別回頭客:
JSP Cookie 處理須要對中文進行編碼與解碼,方法以下:
String str = java.net.URLEncoder.encode("中文","UTF-8"); //編碼 String str = java.net.URLDecoder.decode("編碼後的字符串","UTF-8"); // 解碼 複製代碼
使用JSP設置cookie包含三個步驟:
Cookie cookie = new Cookie("key","value"); 複製代碼
請務必牢記,名稱和值中都不能包含空格或者以下的字符:
[ ] ( ) = , " / ? @ : ; 複製代碼
cookie.setMaxAge(60*60*24); 複製代碼
response.addCookie(cookie); 複製代碼
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>表單提交</title> </head> <body> <form action="CookieDemo.jsp" method=GET> 站點名: <input type="text" name="name"> <br /> 網址: <input type="text" name="url" /> <input type="submit" value="提交" /> </form> </body> </html> 複製代碼
<%@ page import="java.net.URLEncoder" %> <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %> <% // 編碼,解決中文亂碼 String str = URLEncoder.encode(request.getParameter("name"),"utf-8"); // 設置 name 和 url cookie Cookie name = new Cookie("name", str); Cookie url = new Cookie("url", request.getParameter("url")); // 設置cookie過時時間爲24小時。 name.setMaxAge(60*60*24); url.setMaxAge(60*60*24); // 在響應頭部添加cookie response.addCookie( name ); response.addCookie( url ); %> <html> <head> <title>設置 Cookie</title> </head> <body> <h1>設置 Cookie</h1> <ul> <li><p><b>網站名:</b> <%= request.getParameter("name")%> </p></li> <li><p><b>網址:</b> <%= request.getParameter("url")%> </p></li> </ul> </body> </html> 複製代碼
想要讀取cookie,您就須要調用request.getCookies()方法來得到一個javax.servlet.http.Cookie對象的數組,而後遍歷這個數組,使用getName()方法和getValue()方法來獲取每個cookie的名稱和值。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="java.net.*" %> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>獲取 Cookie</title> </head> <body> <% Cookie cookie = null; Cookie[] cookies = null; // 獲取cookies的數據,是一個數組 cookies = request.getCookies(); if( cookies != null ){ out.println("<h2> 查找 Cookie 名與值</h2>"); for (int i = 0; i < cookies.length; i++){ cookie = cookies[i]; out.print("參數名 : " + cookie.getName()); out.print("<br>"); out.print("參數值: " + URLDecoder.decode(cookie.getValue(), "utf-8") +" <br>"); out.print("------------------------------------<br>"); } }else{ out.println("<h2>沒有發現 Cookie</h2>"); } %> </body> </html> 複製代碼
刪除cookie很是簡單。若是您想要刪除一個cookie,按照下面給的步驟來作就好了:
下面的程序刪除一個名爲"name"的cookie,當您第二次運行CookieDemo2.jsp時,name 將會爲 null。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="java.net.*" %> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>獲取 Cookie</title> </head> <body> <% Cookie cookie = null; Cookie[] cookies = null; // 獲取當前域名下的cookies,是一個數組 cookies = request.getCookies(); if( cookies != null ){ out.println("<h2> 查找 Cookie 名與值</h2>"); for (int i = 0; i < cookies.length; i++){ cookie = cookies[i]; if((cookie.getName( )).compareTo("name") == 0 ){ cookie.setMaxAge(0); response.addCookie(cookie); out.print("刪除 Cookie: " + cookie.getName( ) + "<br/>"); } out.print("參數名 : " + cookie.getName()); out.print("<br>"); out.print("參數值: " + URLDecoder.decode(cookie.getValue(), "utf-8") +" <br>"); out.print("------------------------------------<br>"); } }else{ out.println("<h2>沒有發現 Cookie</h2>"); } %> </body> </html> 複製代碼
HttpSession是有JavaWeb提供的,用來會話跟蹤的類,session是服務器對象,保存在服務器端;
HttpSession是Servlet三大域對象之一(request、session、application),因此它也有setAttribute()、getAttribute()、removeAttribute()方法;
HttpSession底層依賴Cookie,或是URL重寫。
會話範圍:會話範圍是某個用戶從首次訪問服務器開始,到該用戶關閉瀏覽器結束; 會話:一個用戶對服務器的屢次連貫性請求,所謂連貫性請求,就是該用戶屢次請求中間沒有關閉瀏覽器。
服務器會爲每一個客戶端建立一個session對象,session就比如客戶在服務器端的帳戶,它們被服務器保存到一個Map中,這個Map被稱爲session緩存。
Servlet中獲得session對象:HttpSession session = request.getSession();
JSP中獲得session對象:session是jsp內置對象之下,不用建立就能夠直接使用。
void setAttribute(String name,Object val); Object getAttribute(String name); void removeAttribute(String name); 複製代碼
案例相關頁面和Servlet:
login.jsp:登陸頁面
LoginSuccess.jsp:只有登陸成功才能訪問的頁面
LoginServlet:校驗用戶是否登陸成功
各頁面和Servlet內容:
login.jsp:提供登陸表單,提交表單請求LoginServlet
LoginServlet:獲取請求參數,校驗用戶是否登陸成功
失敗:保存錯誤信息到request域,轉發到login.jsp,在login.jsp中顯示request域中的錯誤信息;
成功:保存用戶信息到session域中,重定向到LoginSuccess.jsp頁面,顯示session域中的用戶信息。
LoginSuccess.jsp:從session域獲取用戶信息,若是不存在,顯示「您尚未登陸」,存在則顯示用戶信息;
只要用戶沒有關閉瀏覽器,session就一直存在,那麼保存在session中的用戶信息也就一塊兒存在,那麼用戶訪問LoginSuccess.jsp就會經過
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html> <head> <title>登陸頁面</title> </head> <body> <% //獲取cookie的值 String name = ""; String pwd = ""; Cookie[] cs = request.getCookies(); if(cs!=null){ for(Cookie c : cs){ if("username".equals(c.getName())){ name = c.getValue(); } if("pwd".equals(c.getName())){ pwd = c.getValue(); } } } %> <% //獲取request信息 String message=""; String mess = (String)request.getAttribute("message"); if(mess!=null){ message = mess; } %> <h1>用戶登陸</h1> <span color="red"><%=message %></span> <form action="/LoginServlet" method="post"> <p> 帳號:<input type="text" name="username" value="<%=name %>" /> </p> <p> 密碼:<input type="password" name="pwd" value="<%=pwd %>" /> </p> <p> <input type="submit" value="登陸"> </p> </form> </body> </html> 複製代碼
LoginServlet.java
package com.demo.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException; @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //設置請求的字符編碼 request.setCharacterEncoding("utf-8"); //接收客戶端請求 String username = request.getParameter("username"); String pwd = request.getParameter("pwd"); //判斷是否登陸成功 if("admin".equals(username) && "1234".equals(pwd)){ //登陸成功,把信息保存到cookie中 Cookie c1 = new Cookie("username",username); Cookie c2 = new Cookie("pwd",pwd); c1.setMaxAge(60*60*24); c2.setMaxAge(60*60*24); response.addCookie(c1); response.addCookie(c2); //登陸成功,保存用戶名到session中,並重定向到LoginSuccess.jsp HttpSession session = request.getSession(); session.setAttribute("username", username); response.sendRedirect("/LoginSuccess.jsp"); }else{ //轉發給客戶端「登陸失敗」 request.setAttribute("message", "用戶信息錯誤,請從新登陸"); request.getRequestDispatcher("/login.jsp").forward(request, response); } } } 複製代碼
LoginSuccess.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html> <head> <title>登陸成功</title> </head> <body> <% //獲取session信息 String name = (String)session.getAttribute("username"); if(name==null){ //session不存在,轉發到登陸頁面,並提示信息 request.setAttribute("message", "您尚未登陸,不能訪問頁面"); request.getRequestDispatcher("/login.jsp").forward(request, response); //重定向到login.jsp,不會顯示request提示的信息 //response.sendRedirect("/login/login.jsp"); return; } %> <h1>登陸成功</h1> 你好<%=name %>,歡迎登陸! </body> </html> 複製代碼
一個網絡服務器能夠發送一個隱藏的HTML表單域和一個惟一的session ID,就像下面這樣:
<input type="hidden" name="sessionid" value="12345"> 複製代碼
這個條目意味着,當表單被提交時,指定的名稱和值將會自動包含在GET或POST數據中。每當瀏覽器發送一個請求,session_id的值就能夠用來保存不一樣瀏覽器的軌跡。
這種方式多是一種有效的方式,但點擊標籤中的超連接時不會產生表單提交事件,所以隱藏表單域也不支持通用會話跟蹤。
您能夠在每一個URL後面添加一些額外的數據來區分會話,服務器可以根據這些數據來關聯session標識符。
舉例來講,w3cschool.cc/file.htm;se… session標識符爲sessionid=12345,服務器能夠用這個數據來識別客戶端。
相比而言,重寫URL是更好的方式來,就算瀏覽器不支持cookies也能工做,但缺點是您必須爲每一個URL動態指定session ID,就算這是個簡單的HTML頁面。
除了以上幾種方法外,JSP利用servlet提供的HttpSession接口來識別一個用戶,存儲這個用戶的全部訪問信息。
默認狀況下,JSP容許會話跟蹤,一個新的HttpSession對象將會自動地爲新的客戶端實例化。禁止會話跟蹤須要顯式地關掉它,經過將page指令中session屬性值設爲false來實現,就像下面這樣:
<%@ page session="false" %> 複製代碼
JSP引擎將隱含的session對象暴露給開發者。因爲提供了session對象,開發者就能夠方便地存儲或檢索數據。
下表列出了session對象的一些重要方法:
服務器不會立刻給你建立session,在第一次獲取session時,即reques.getSession()方法執行時,纔會建立session。
獲取Cookie中的JSESSIONID: