Servlet_JSP最全學習資料教程

Servlet

img

1. Servlet運行流程:

  1. url:http://localhost:8080/Servlet_Test_login/loginServlet

    組成:服務器地址:端口號/虛擬項目名/servlet的別名

  2. uri:虛擬項目名/servlet別名

瀏覽器發送請求到服務器,服務器根據請求的URL地址中的URI信息在webapps目錄下找到對應的項目文件,然後再web.xml中檢索對應的servlet,找到後調用並執行servlet。

2. Servlet配置:

  1. 通過web.xml 配置

  2. 通過註解配置

    @WebServlet("/loginServlet")
    

loginServlet 即爲此servlet的別名,通過

http://localhost:8080/Servlet_Test_login/loginServlet 即可訪問。

3. doGet/doPost的區別與使用:

  1. 區別:

    在使用表單提交數據到服務器的時候有兩張方式可共選擇,一個是post一個是get。可在中的method屬性中指定提交的方式。如:,如果不指定method屬性,則會默認該屬性爲”get”方式。

    不同點一:

    通過get方式提交的數據有大小的限制,通常在1024字節左右。也就是說如果提交的數據很大,用get方法就可需要小心;而post方式沒有數據大小的限制,理論上傳送多少數據都可以。

    不同點二:

    通過get傳遞數據,實際上是將傳遞的數據按照”key,value”的方式跟在URL的後面來達到傳送的目的的;而post傳遞數據是通過http請求的附件進行的,在URL中並沒有明文顯示。

    不同點三:

    通過Get方式提交的數據安全性不高,而Post方式的更加安全。

  2. 使用:

    h5:

    <body>
        <form action="/loginServlet" method="post">
            用戶名:<input type="text" name="username"> <br>
            密碼:<input type="password" name="password"><br>
            <input type="submit" value="登錄">
        </form>
    </body>
    

    Servlet:

    @Override
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		request.setCharacterEncoding("UTF-8");
    		response.setCharacterEncoding("UTF-8");
    		//向服務器發送請求獲取到參數
    		String username=request.getParameter("username");
    		String password=request.getParameter("password");
    		System.out.println(username+"--"+password);
    		
    
    		response.setHeader("Content-Type", "text/html; charset=UTF-8");
    		Writer out=response.getWriter();
    		out.write("用戶名:"+username);
    		out.write("密碼:"+password);
    		out.flush();
    		out.close();
    

4. Request

1.概述

request是Servlet.service()方法的一個參數,在客戶端發出每個請求時,服務器都會創建一個request對象,並把請求數據封裝到request中,然後在調用Servlet.service()方法時傳遞給service()方法

HttpServletRequest對象代表客戶端的請求,當客戶端通過HTTP協議訪問服務器時,HTTP請求頭中的所有信息都封裝在這個對象中,開發人員通過這個對象的方法,可以獲得客戶這些信息。

2.常用方法

(1) 域方法:

  1. 存儲
//用來存儲一個對象,也可以稱之爲存儲一個域屬性
void setAttribute(String name, Object value)
    
Eg:servletContext.setAttribute(“xxx”, “XXX”)
//在ServletContext中保存了一個域屬性,域屬性名稱爲xxx,域屬性的值爲XXX
  1. 獲取
//用來獲取ServletContext中的數據
Object getAttribute(String name)
//獲取名爲xx的域屬性
Eg:String value = (String)servletContext.getAttribute(“xxx”);

//獲取所有域屬性的名稱;
Enumeration getAttributeNames()
  1. 移除
//用來移除ServletContext中的域屬性
void removeAttribute(String name)

(2) 獲取請求頭數據:

//獲取指定名稱的請求頭
String getHeader(String name)

//獲取所有請求頭名稱
Enumeration getHeaderNames()
    
//獲取值爲int類型的請求頭
int getIntHeader(String name)

(3) 獲取請求相關的其他方法

//獲取請求體的字節數,GET請求沒有請求體,沒有請求體返回-1;
int getContentLength()

/*	
	獲取請求類型,如果請求是GET,那麼這個方法返回null;如果是POST請求,那麼默認
	爲application/x-www-form-urlencoded,表示請求體內容使用了URL編碼;
*/
String getContentType()

//返回請求方法,例如:GET/POST
String getMethod()

//返回當前客戶端瀏覽器的Locale。java.util.Locale表示國家和言語,這個東西在國際化中很有用;
Locale getLocale()
    
/*
	獲取請求編碼,如果沒有setCharacterEncoding(),那麼返回null,表示使用
	ISO-8859-1編碼;
*/
String getCharacterEncoding()
    
/*
	設置請求編碼,只對請求體有效!注意,對於GET而言,沒有請求體!!!所以此方法
	只能對POST請求中的參數有效!
*/
void setCharacterEncoding(String code)

//返回上下文路徑,例如:/Dmoe1
String getContextPath()
    
//返回請求URL中的參數,例如:username=zhangSan
String getQueryString()
    
//返回請求URI路徑,例如:/Demo1/ServletDemo1
String getRequestURI()
    
/*
	返回請求URL路徑,例如:http://localhost/Demo1/ServletDemo1即返回除了參數
	以外的路徑信息;
*/
StringBuffer getRequestURL()
    
//返回Servlet路徑,例如:/ServletDemo1
String getServletPath()
    
//返回當前客戶端的IP地址
String getRemoteAddr()
    
//返回當前客戶端的主機名,但這個方法的實現還是獲取IP地址
String getRemoteHost()
    
//返回請求協議,例如:http
String getScheme()

//返回主機名,例如:localhost
String getServerName()
    
//返回服務器端口號,例如:8080
int getServerPort()

3)常用方法總結:

  1. 與Http請求相關:
    • getReader():返回一個緩衝讀取器,用於讀取請求正文中的文本。
    • getContentType() :返回請求正文的MIME類型,或者 null類型是否已知。
    • getContentLength() :返回請求正文的長度(以字節爲單位),並由輸入流提供,如果長度未知,則返回-1。
    • getCharacterEncoding() :返回此請求正文中使用的字符編碼的名稱。
    • setCharacterEncoding(java.lang.String env)設置此請求正文中使用的字符編碼的名稱。
    • setAttribute(String,Object):此方法將屬性存儲在請求上下文中; 這些屬性將在請求之間重置。
    • getProtocol():以protocol / majorVersion.minorVersion格式返回請求使用的協議的名稱和版本,例如HTTP / 1.1。
    • getScheme() :返回請求方式,例如 http,https或ftp。
  2. 請求客戶端相關:
    • getServerPort(): 返回發送請求的端口號。
    • getRemoteAddr(): 返回發送請求的客戶端或最後一個代理的Internet協議(IP)地址。
    • getRemoteHost() :返回客戶端的完全限定名稱或發送請求的最後一個代理。
    • getServerName(): 返回發送請求的服務器的主機名。
  3. 與request屬性相關:
    • setAttribute(java.lang.String name, java.lang.Object o)在此請求中存儲屬性。 如果第二參數爲null 那麼相當於removeAttribute
    • getAttributeNames():Returns an Enumeration containing the names of the attributes available to this request.
    • removeAttribute(java.lang.String name):從此請求中刪除屬性。
    • getParameter(java.lang.String name):以String形式返回請求參數的值,如果參數不存在,則返回null。
    • getParameterMap():返回此請求的參數的java.util.Map。
    • getParameterValues(java.lang.String name):返回包含給定請求參數所具有的所有值的String對象數組,如果參數不存在,則返回null。

4.request獲取請求參數

獲取請求參數的通用方式(Get/Post均可)

//根據參數名稱獲取參數值
String getParameter(String name)

//根據參數名稱獲取參數值的數組 
String[] getParameterValues(String name)

//獲取所有請求的參數名稱
Enumeration<String> getParameterNames()

//獲取所有參數的map集合
Map<String,String[]> getParameterMap()

通過表單提交數據:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/RequestDemo3" method="post">
   <table>
      <tr>
         <td>用戶名</td>
         <td><input type="text" name="username"></td>
      </tr>
      <tr>
         <td>密碼</td>
         <td><input type="password" name="password"></td>
      </tr>
      <tr>
         <td>性別</td>
         <td><input type="radio" name="gender" value="男"><td><input type="radio" name="gender" value="女"></td>
      </tr>
      <tr>
         <td>愛好</td>
         <td>
            <input type="checkbox" name="hobbies" value="游泳">游泳
            <input type="checkbox" name="hobbies" value="跑步">跑步
            <input type="checkbox" name="hobbies" value="網球">網球
      </tr>
      <input type="hidden" name="aaa" value="this is hidden text!">
      <tr>
         <td>從哪來的?</td>
         <td>
            <select name="address">    
               <option value="廣州">廣州</option>
               <option value="北京">北京</option>
               <option value="深圳">深圳</option>
            </select>
         </td>
      </tr>     
      <tr>
         <td>補充說明</td>
         <td>
            <textarea rows="2" cols="30" name="textarea"></textarea>
         </td>
      </tr>
      <tr>
         <td><input type="submit" value="提交"></td>
         <td><input type="reset" value="重置"></td>
      </tr>
   </table>
   </form>
</body>
</html>

在servlet 中接收:

@WebServlet("/RequestDemo3")
public class RequestDemo3 extends HttpServlet {
    public RequestDemo3() {
        super();
    }

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //設置request字符編碼的格式
    req.setCharacterEncoding("UTF-8");

    //通過html的name屬性,獲取到值
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    String gender = req.getParameter("gender");

    //複選框和下拉框有多個值,獲取到多個值
    String[] hobbies = req.getParameterValues("hobbies");
    String[] address = req.getParameterValues("address");

    //獲取到文本域的值
    String description = req.getParameter("textarea");

    //得到隱藏域的值
    String hiddenValue = req.getParameter("aaa");

    System.out.println("username: " + username);
    System.out.println("password: " + password);
    System.out.println("gender: " + gender);
    System.out.println("hobbies: " + Arrays.toString(hobbies));
    System.out.println("address: " + Arrays.toString(address));
    System.out.println("description: " + description);
    System.out.println("hiddenValue: " + hiddenValue);
 }
}

5.實現轉發:

服務器內部的資源跳轉方式:

  1. Servlet跳轉至html

    SuccessServlet

    //設置編碼否則將會亂碼:
    request.setCharacterEncoding("utf-8");
    
    //獲取到requestDispatcher對象,跳轉到successServlet.html
    RequestDispatcher requestDispatcher = request.getRequestDispatcher("/successServlet.html");
    
    //調用requestDispatcher對象的forward()實現轉發,傳入req和resp方法
    requestDispatcher.forward(request, response);
    
  2. Servlet內部的跳轉:

    //存儲數據
    req.setAttribute("user",user);
    //轉發
    req.getRequestDispatcher("/successServlet").forward(req,resp);
    

我們可以同時使用ServletContext和request實現Servlet之間的通訊

一般來說我們儘量使用request,因爲ServletContext代表着整個web應用,使用ServetContext會消耗大量的資源,而request對象會隨着請求的結束而技術,資源會被回收,使用request域進行Servlet進行Servlet之間的通訊在開發中是非常頻繁的

細節:

如果在調用foreard方法之前,在Servlet程序中寫入的部分已經被真正地傳到了客戶端,forward方法將拋出IllegalStateException異常,也就是說,不要在在轉發之前寫數據給瀏覽器

如果調用forward方法之前向Servlet引擎的緩衝區中寫入了內容,只要寫入到緩衝區中的內容還沒有被真正輸出到客戶端,forward方法就可以被正常執行,原來寫入到緩衝區中的內容將被清空,但是已寫入到HttpServletResponse對象中的響應頭字段信息保持有效

6.中文亂碼問題

*//設置request字符編碼的格式* 
request.setCharacterEncoding("UTF-8");

Tomcat服務器的默認編碼是ISO 8859-1,而瀏覽器使用的是UTF-8編碼。瀏覽器的中文數據提交給服務器,Tomacat以ISO 8859-1編碼對中文編碼,當我在Servlet讀取數據的時候自然拿到亂碼。所以設置request的編碼爲UTF-8,亂碼就解決了

注意:按照上述例子中(使用post方式)亂碼問題已經解決了,但是在get方式中嘗試仍然是亂碼。在此我們需要了解post方法是怎麼進行參數傳遞的。

當我們點擊提交按鈕的時候,數據封裝進了Form Data中,http請求中把實體主體帶過去了【傳輸的數據稱之爲主體】,既然request對象封裝了http請求,所以request對象可以解析到發送過來的數據,於是只要把編碼設置成UTF-8就可以解決亂碼問題而get方式不同,它的數據是從消息行帶過去的,沒有封裝到request中,所以使用request設置編碼是無效的。

解決方法: 我們既然知道Tomcat默認的編碼是ISO 8859-1,那麼get方式由消息體帶過去給瀏覽器的時候肯定是用ISO 8859-1編碼了。

5. Respone

1. 響應正文

response作爲響應對象,他提供了兩個響應流對象,可以向客戶端輸出響應正文

//獲取字符流
l PrintWriter out = response.getWriter()

//獲取字節流
l ServletOutputStream out = response.getOutputStream()
ServletOutputStream servletOutputStream = resp.getOutputStream();

servletOutputStream.write("你好世界".getBytes());

servletOutputStream.write("Just for test".getBytes());

如果Tomcat版本在8以下 在outputStream中使用print()方法接收字符串,由於編碼的問題,輸出中文字符串的時候,就會出現亂碼問題

原因是,outputStream是輸出二進制的數據,print()方法先有一個將字符串轉爲二進制的過程,Tomcat會使用IOS 8859-1編碼轉換,所以出現了問題

但是使用write()卻可以很好的解決這個問題,這是因爲,write(“Just for test”.getBytes());轉換爲byte[]數組的時候默認使用的是gb2312編碼,所以不會出現問題

建議寫法:

//設置編碼
response.setContentType("text/html;charset=utf-8");
//輸出
response.getWriter().write("登錄失敗,用戶名或密碼錯誤");

好處:不只會調用response.setCharaceterEncoding(“utf-8”),還會設置content-type響應頭(客戶端瀏覽器會使用content-type頭來解讀響應數據)

總結:響應正文內容爲字符,那麼使用respone.getWriter(),如果響應內容是字節,例如下載文件,可以使用 response.getOutputStream()

注意:在同一個請求中,不能同時使用這兩個流,否則會拋出 IllegalStateException 異常。

getWriter() 的緩衝區問題

它的類型是PrintWriter類型的,所以它有緩衝區,緩衝區的默認大小爲8KB,在限定代銷範圍以內,數據先存放在緩衝區,等到超過範圍後,服務器刷新流,緩衝區中的數據發送倒客戶端,如果想要響應數據馬上發送到客戶端,可以調用response.flushBuffer()方法來手動刷新緩衝區

2.設置響應頭信息、狀態碼以及其他

(1) 設置響應頭

使用 response 對象的 setHeader() 方法來設置響應頭

//設置content-type響應頭,告訴瀏覽器響應內容爲html類型,編碼爲utf-8。而且同時會設置response的字符流編碼爲utf-8,即response.setCharaceterEncoding(“uaav tf-8”);
response.setHeader(“content-type”, “text/html;charset=utf-8);

//5秒後自動跳轉到指定主頁
response.setHeader("Refresh","5; URL=http://www.xxx.com");

(2) 設置狀態碼

//設置狀態碼* 
response.setStatus(200) ;
//當發送錯誤狀態碼時,跳轉到指定錯誤頁面,但可以顯示錯誤信息
response.sendError(404, “您要查找的資源不存在”);

(3) 其他

//等同於response.setHeader(“content-type”, “text/html;charset=utf-8”)
response.setContentType("text/html;charset=utf-8")

//設置字符響應流的字符編碼爲UTF-8    
response.setCharacterEncoding(“utf-8)
    
//下例表示定時刷新,3秒後跳轉頁面
response.setHeader("Refresh", "3;URL=Bservlet");

3.常用方法總結:

  1. 數據寫入有關:
    • setBufferSize(size): 設置響應正文的首選緩衝區大小。
    • flushBuffer(): 強制將緩衝區中的任何內容寫入客戶端。
    • getBufferSize(): 返回用於響應的實際緩衝區大小。
    • getOutputStream(): 返回ServletOutputStream適合在響應中寫入二進制數據。
    • getWriter(): 返回PrintWriter可以將字符文本發送到客戶端的對象。
    • resetBuffer(): 清除響應中底層緩衝區的內容,而不清除標頭或狀態代碼。
  2. http相應有關:
    • setCharacterEncoding(charset): 設置發送到客戶端的響應的字符編碼(MIME字符集),例如,設置爲UTF-8。
    • getCharacterEncoding(): 返回用於此響應中發送的正文的字符編碼(MIME字符集)的名稱。
    • getContentType(): 返回用於此響應中發送的MIME正文的內容類型。
    • getLocale(): 使用該setLocale(java.util.Locale)方法返回爲此響應指定的語言環境。
    • isCommitted(): 返回一個布爾值,指示響應是否已提交。
    • reset(): 清除緩衝區中存在的所有數據以及狀態代碼和標頭。
    • setContentLength(len): 設置響應中內容主體的長度在HTTP-servlet中,此方法設置HTTP-Content-Length標頭。
    • setContentType(java.lang.String): 如果尚未提交響應,則設置發送到客戶端的響應的內容類型。
    • setLocale(java.util.Locale): 如果尚未提交響應,則設置響應的區域設置。

6. 重定向

當你訪問 www.xxx.com的時候,頁面被跳轉到了另一個頁面,並且瀏覽器地址欄中的URL也發生了變化,這種技術就叫做重定向

完成重定向有兩個關鍵的地方

設置響應碼
設置Location頭
響應碼200的意思是響應成功,而重定向對應的響應碼爲302,所以我們需要設置響應碼

因爲重定向的原理爲,發出二次請求,所以你需要給瀏覽器指定第二次請求的URL,所以需要蛇者Location頭

注意:同服務器下可以使用相對路徑

response.setStatus(302);

response.setHeader("Location", "www.xxx.com");

簡單的寫法

response.sendRedirect("www.xxx.com");

7. 轉發和重定向的區別與使用場景

1) 區別

(一) 實際發生未知不同,地址欄不同

A:轉發是發生在服務器的

B:轉發是由服務器進行跳轉的,轉發時,瀏覽器的地址欄是沒有發生變化的,(訪 問了Servlet1後即使頁面跳轉到了Servlet2,但瀏覽器的地址還是Servlet1的) 也就是說瀏覽器是不知道該跳轉的動作,實現轉發只是一次的http請求,一次轉 發中request和response對象都是同一個,這也解釋了爲什麼可以使用request 作爲域對象進行Servlet之間的通訊

C:重定向是發生在瀏覽器的

D:重定向是由瀏覽器進行跳轉的,進行重定向跳轉的時候,瀏覽器的地址會發生變化,實現重定向的原理是由response的狀態碼和location頭組合而實現的,這 是由瀏覽器進行的頁面跳轉實現會發出兩個http請求,request域對象是無效的, 因爲它不是同一個request對象

(二) 用法不同

原則:

  1. 給服務器用的直接從資源名開始寫,

  2. 給瀏覽器用的要把應用名協寫上

  3. Requst.getRequestDispatcher(“/資源名 URL”).forward(request,response);

​ 轉發時“/”代表的是本應用程序的根目錄(web-01)

  1. Response.send(“/web應用/資源名URL”);

    重定向時“/”代表的是webapps目錄

(三) 能夠去往的URL的範圍不同

轉發是服務器跳轉,只能去往當前web應用的資源

重定向是服務器跳轉,可以去往任何的資源

(四) 傳遞數據的類型不同

轉發的request對象可以傳遞各種類型的數據,包括對象

重定向只能傳遞字符串

(五) 跳轉的時間不同

轉發時:執行到跳轉語句就會立刻跳轉

重定向:整個頁面執行完後纔會執行跳轉

(2) 應用場景

總結:轉發是帶着轉發前的請求的參數。重定向時新的請求

典型的應用場景:

1:轉發:訪問Servlet處理業務邏輯,然後轉發到jsp中去處理結果,瀏覽器裏URL不變

2:重定向:提交表單,處理成功後重定向到另一個jsp,防止表單重複提交,瀏覽器裏的URL變了

8.Cookie

1) 爲什麼會有Cookie?

Web應用程序是使用HTTP協議傳輸數據的。HTTP協議是無狀態的協議。一旦數據交換完畢,客戶端與服務器端的連接就會關閉,再次交換數據需要建立新的連接。這就意味着服務器無法從連接上跟蹤會話。

你可能會有這樣的經歷,登陸一個網站的時候會提醒你要不要記住賬戶和密碼,這樣下次來你就不用再次輸入賬號密碼了。這就是cookie的作用,當我們再次訪問的時候,方便服務器直接根據我們的cookie來直接取上一次取過的東西(對於每一個cookie服務器會對這個cookie存儲上一次我們拿過的數據,下一次對於同一個cookie的時候,就直接在這裏取)

2) 什麼是Cookie

Cookie是由服務器端生成,發送給User-Agent(一般是瀏覽器),(服務器告訴瀏覽器設置一下cookie),瀏覽器自動會將Cookiekey/value保存到某個目錄下的文本文件內,下次請求同一網站時也會自動發送該Cookie給服務器,即添加在請求頭部(前提是瀏覽器設置爲啓用cookie)。
Cookie就是一個小型文件(瀏覽器對cookie的內存大小是有限制的-------用來記錄一些信息)

3) 創建一個Cookie

如果不設置Cookie的 MaxAge 最大存儲時間 那麼默認會存儲在瀏覽器運行內存之中 瀏覽器關閉之後 Cookie 信息消失。

構造函數 :

Cookie(java.lang.String name, java.lang.String value)

構造具有指定名稱和值的cookie。

  Cookie userName = new Cookie("UserName",UserID);
  Cookie userPassword = new Cookie("UserPassword",UserPwd);

  response.addCookie(userName);
  response.addCookie(userPassword);
  • setMaxAge(int expiry):以秒爲單位設置cookie的最大年齡。 返回值: void

  • setPath(java.lang.String uri):指定客戶端應返回cookie的cookie的路徑 返回值: void

  • setComment(java.lang.String purpose):指定描述cookie用途的註釋。返回值: void

  • setValue(java.lang.String newValue):創建cookie後,爲cookie分配新值。 返回值: void

    注:以上四個方法都有對應的get方法 返回類型爲設置的類型。

如果設置了存儲時間那麼cookie信息就存儲在瀏覽器文件中也就是說硬盤上面 如果不設置有效路徑那麼每一次對服務器的請求都會帶着cookie信息 而且由於會明文保存在
http協議中所以推薦對存儲的cookie信息進行加密存儲。

 userName.setMaxAge(60*60*24); //保存一天
 userPassword.setMaxAge(60*60*24); //保存一天

 userName.setPath("/Login.jsp"); //只有在請求/login.jsp 的時候才把cookie信息 加到http請求中

4)Cookie的存儲:

Cookie 存儲在HTTP 請求中 的Cookie 字段中 且你存什麼它保存什麼 本身並不加密存儲。

Request URL: http://localhost:8089/index.jsp
Request Method: GET
Status Code: 200 
Remote Address: [::1]:8089
Referrer Policy: no-referrer-when-downgrade
Content-Length: 145
Content-Type: text/html;charset=UTF-8
Date: Mon, 26 Nov 2018 00:29:15 GMT
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Cookie: UserPassword=123123;JSESSIONID=B6348CE35C47ED815CC1738C9E315A59;UserName=ad123123
Host: localhost:8089
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/69.0.3497.100 Safari/537.36

5) Cookie中獲取Cookie

小心一種特殊情況 就是用戶註銷了自己的信息 從數據庫中刪除了自己的信息 但是自己的cookie並沒有被刪除的問題

 int islogin = 0;
 for (Cookie ck : request.getCookies()) {
     if(ck.getName().equals("UserName")){ //不要用 == 去判斷
         response.getWriter().println("已經登錄成功");
         islogin ++;
     }
 }

 if(islogin == 0){
     response.getWriter().println("<a href='/Login.jsp'>點擊登錄</a>");
 }

6)Cookie的一些方法:

  • setMaxAge(int expiry):以秒爲單位設置cookie的最大年齡。 設置Cookie 過期時間
  • setValue(java.lang.String newValue):創建cookie後,爲cookie分配新值。
  • setDomain(java.lang.String pattern):指定應在其中顯示此cookie的域。
  • setComment(java.lang.String purpose):指定描述cookie用途的註釋。
  • setPath(java.lang.String uri):指定客戶端應返回cookie的cookie的路徑。
  • setSecure(boolean flag):向瀏覽器指示是否應僅使用安全協議(例如HTTPS或SSL)發送cookie。 設置Cookie Http-Only
  • setVersion(int v):設置此cookie符合的cookie協議的版本。

9.Session機制

1) 爲什麼有Session

除了使用Cookie,Web應用程序中還經常使用Session來記錄客戶端狀態。Session是服務器端使用的一種記錄客戶端狀態的機制,使用上比Cookie簡單一些,相應的也增加了服務器的存儲壓力。

2) 什麼是Session:

Session是另一種記錄客戶狀態的機制,不同的是 Cookie保存在客戶端瀏覽器中,而Session保存在服務器上 。客戶端瀏覽器訪問服務器的時候,服務器把客戶端信息以某種形式記錄在服務器上。這就是Session。客戶端瀏覽器再次訪問時只需要從該Session中查找該客戶的狀態就可以了。
如果說Cookie機制是通過檢查客戶身上的"通行證"來確定客戶身份的話,那麼Session機制就是通過檢查服務器上的"客戶明細表"來確認客戶身份。Session相當於程序在服務器上建立的一份客戶檔案,客戶來訪的時候只需要查詢客戶檔案表就可以了。

Session對應的類爲javax.servlet.http.HttpSession類。每個來訪者對應一個Session對象,所有該客戶的狀態信息都保存在這個Session對象裏。Session對象是在客戶端第一次請求服務器的時候創建的。Session也是一種key-value的屬性對,通過getAttribute(String key)和setAttribute(String key,Object value)方法讀寫客戶狀態信息。Servlet裏通過request.getSession()方法獲取該客戶的Session

3) 創建一個Session

HttpSession session = request.getSession(); //如果服務器已經創建那麼返回session 否則新建一個session 並返回

response.getWriter().println(session.getId());
  • HttpSession getSession():返回與此請求關聯的當前會話,或者如果請求沒有會話,則創建一個會話。
  • HttpSession getSession(boolean create):返回HttpSession 與此請求關聯的當前值,如果沒有當前會話且create爲true,則返回新會話。
  • int getMaxInactiveInterval():返回servlet容器在客戶端訪問之間保持此會話打開的最長時間間隔(以秒爲單位)
  • int setMaxInactiveInterval(int interval):指定servlet容器使此會話失效之前的客戶端請求之間的時間(以秒爲單位)

Session 本質是由客戶第一次訪問服務器由服務器自己創建的

4) Session存儲在哪裏?

  • Seeion ID的唯一性如何保證的:當用戶第一次訪問服務器的時候,服務器會創建一個Session對象給用戶,並且產生一個唯一標識ID 存在Session 對象中 並且將此唯一Session ID 發送到瀏覽器保存在瀏覽器中 [存儲在瀏覽器的Cookie中 名稱爲:JSESSIONID], 作爲用戶的唯一標識 也就是說 唯一標識Session的ID 會存儲一份在客戶瀏覽器中,Session 對象存儲在服務器中。

  • 本質上唯一標識只存儲在瀏覽器運行內存中 也就是說關閉瀏覽器就會失效。

  • Session 默認生效時間 30分鐘。

  • 如果session 失效了 那麼他又會生成一個session 併發送一個sessionID 給瀏覽器存儲。

  • 規則:如果Session 在規定的時間內沒有使用就銷燬 否則就重新計時。

 session.invalidate();
Request URL: http://localhost:8089/login
Request Method: POST
Status Code: 200 
Remote Address: [::1]:8089
Referrer Policy: no-referrer-when-downgrade
Content-Length: 57
Content-Type: text/html;charset=UTF-8
Date: Mon, 26 Nov 2018 01:11:19 GMT
Set-Cookie: UserName=3444444444444444
Set-Cookie: UserPassword=23423424
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 40
Content-Type: application/x-www-form-urlencoded
Cookie: Webstorm-66e715af=5d7e1fa0-a9e9-4c01-9c16-aaff75cf10f7; JSESSIONID=2AF4A84C2F8FC452F54C77D3092B2E1B; 
UserName=3444444444444444; UserPassword=23423424
Host: localhost:8089
Origin: http://localhost:8089
Referer: http://localhost:8089/Login.jsp
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/69.0.3497.100 Safari/537.36

5) Session存儲數據:

通過如下訪問 獲取或者存儲Session數據 當然你要保證你這次的Session 是你上次存儲的Session

  • void setAttribute(java.lang.String name, java.lang.Object value) :使用指定的名稱將對象綁定到此會話。
  • java.lang.Object getAttribute(java.lang.String name) :返回在此會話中使用指定名稱綁定的對象,或者 null如果名稱下沒有綁定任何對象。

最好用一個屬性存儲一個值表示 此時是否具有 有效Session 例如

  session.setAttribute("isLoginStore",true);
  session.setAttribute("id",userName);
  session.setAttribute("pwd",userPassword);

  //獲取
  if(getAttribute(isLoginStore) != null){
     session.getAttribute("id");
     session.getAttribute("pwd");
  }else{
     response.getWriter().println("登錄超時!請重新登錄");
  }

5) 獲取Session

HttpSession session = request.getSession();

另外維持一個會話的核心就是客戶端的唯一標識,即 session id

6)Session的一些方法:

  • Object getAttribute(java.lang.String name):返回在此會話中使用指定名稱綁定的對象,或者 null如果名稱下沒有綁定任何對象。
  • Enumeration getAttributeNames():返回Enumeration的String含有與本次會議的所有對象的名稱的對象。
  • long getCreationTime():返回創建此會話的時間,以格林威治標準時間1970年1月1日午夜以來的毫秒數爲單位。
  • String getId():返回包含分配給此會話的唯一標識符的字符串。
  • long getLastAccessedTime():返回客戶端最後一次發送與此會話關聯的請求 並以容器收到請求的時間爲標記。
  • getServletContext():返回此會話所屬的ServletContext。
  • invalidate():使此會話無效,然後取消綁定綁定到它的任何對象。
  • isNew() :返回true如果客戶端還不知道該會話或者如果客戶選擇不參加會議。
  • setMaxInactiveInterval(int interval)指定servlet容器使此會話失效之前的客戶端請求之間的時間(以秒爲單位)。
  • removeAttribute(java.lang.String name):從此會話中刪除與指定名稱綁定的對象。
  • setAttribute(java.lang.String name, java.lang.Object value)使用指定的名稱將對象綁定到此會話。

10.Cookie Session小結

首先 session 是一個抽象概念,開發者爲了實現中斷和繼續等操作,將 user agent 和 server 之間一對一的交互,抽象爲“會話”,進而衍生出“會話狀態”,也就是 session 的概念。

而 cookie 是一個實際存在的東西,http 協議中定義在 header 中的字段。可以 認爲是 session 的一種後端無狀態實現。

1,session 在服務器端,cookie 在客戶端(瀏覽器)。

2,session 默認被存在在服務器的一個文件裏(不是內存)。

3,session 的運行依賴 session id,而 session id 是存在 cookie 中的,也就是說,如果瀏覽器禁用了 cookie ,同時 session 也會失效(但是可以通過其它方式實現,比如在 url 中傳遞 session_id)。
4,session 可以放在 文件、數據庫、或內存中都可以。

免登錄使用Cookie

用戶驗證這種場合一般會用 session

11.ServletContext:

1)簡介:

ServletContext官方叫servlet上下文。服務器會爲每一個工程創建一個對象,這個對象就是ServletContext對象。這個對象全局唯一,而且工程內部的所有servlet都共享這個對象。所以叫全局應用程序共享對象。

實現Application的職責 完成所有用戶共享數據 使得不同用戶可以共享同一個對象 Servlet爲我們實現了ServletContent對象來完成這個功能 官方文檔

  • 由服務器創建
  • 所有用戶共享
  • 一個項目只有一個
  • 生命週期:從你將項目部署到服務器到 服務器停止此網站或項目被停止

2)作用:

  1. servletContext是一個域對象。

  2. 可以讀取全局配置參數。獲取項目中web.xml文件的全局配置信息。

    web-app下:

    <context-param>
        <param-name>Author</param-name>
        <param-value>JxKicker</param-value>
    </context-param>
    <context-param>
        <param-name>age</param-name>
        <param-value>18</param-value>
    </context-param>
    

    獲取配置信息:

    ServletContext sc = this.getServletConfig().getServletContext();
    String val = sc.getInitParameter("Author");
    String key[] = sc.getInitParameters(); //返回所有自定義配置項
    response.getWriter().println("作者:" + val );
    
  3. 獲取項目 webroot下的文件資源的絕對路徑。

    ServletContext sc = this.getServletConfig().getServletContext();
    String realPath = sc.getRealPath("/resources/my.txt");
    response.getWriter().println(realPath);
    
  4. 獲取項目 webroot下的文件資源的流對象 但是不能獲取類文件的流對象。

    InputStream stream_  = sc.getResourceAsStream("/resources/my.txt");
    
  5. 可以用來統計網站訪問情況。

2.1 域對象簡介

域對象是服務器在內存上創建的存儲空間,用於在不同動態資源(servlet)之間傳遞與共享數據。

2.2 域對象方法

凡是域對象都有如下3個方法:

  • 往域對象裏面添加數據,添加時以key-value形式添加。

    setAttribute(name,value);
    

    name是String類型,value是Object類型;

  • 根據指定的key讀取域對象裏面的數據。

    getAttribute(name);
    
  • 根據指定的key從域對象裏面刪除數據。

    removeAttribute(name);
    

3)獲取ServletContext對象

​ 在Servlet對象中可以直接使用this:

ServletContext sc = this.getServletContext();

​ 在jsp中:

ServletContext sc = this.getServletConfig().getServletContext();

​ 通過request獲取:

ServletContext context = req.getSession().getServletContext();

4)數據存儲交互:

  • void removeAttribute(java.lang.String name):

    從servlet上下文中刪除具有給定名稱的屬性。

  • void setAttribute(java.lang.String name, java.lang.Object object):

    將對象綁定到此servlet上下文中的給定屬性名稱。

  • java.lang.Object getAttribute(java.lang.String name) :

    返回具有給定名稱的servlet容器屬性,或者null如果該名稱沒有屬性。

  • java.util.Enumeration getAttributeNames():

    返回Enumeration包含此servlet上下文中可用的屬性名稱的內容。

5)其他方法:

01 Object getAttribute(String name) 返回給定名的屬性值

02 Enumeration getAttributeNames() 返回所有可用屬性名的枚舉
03 void setAttribute(String name,Object obj) 設定屬性的屬性值
04 void removeAttribute(String name) 刪除一屬性及其屬性值
05 String getServerInfo() 返回JSP(Servlet)引擎名及版本號
06 String getRealPath(String path) 返回一虛擬路徑的真實路徑
07 ServletContext getContext(String uripath) 返回指定WebApplication的application對象
08 int getMajorVersion() 返回服務器支持的Servlet API的最大版本號
09 int getMinorVersion() 返回服務器支持的Servlet API的最大版本號
10 String getMimeType(String file) 返回指定文件的MIME類型
11 URL getResource(String path) 返回指定資源(文件及目錄)的URL路徑
12 InputStream getResourceAsStream(String path) 返回指定資源的輸入流
13 RequestDispatcher getRequestDispatcher(String uripath) 返回指定資源的RequestDispatcher對象
14 Servlet getServlet(String name) 返回指定名的Servlet
15 Enumeration getServlets() 返回所有Servlet的枚舉
16 Enumeration getServletNames() 返回所有Servlet名的枚舉
17 void log(String msg) 把指定消息寫入Servlet的日誌文件
18 void log(Exception exception,String msg) 把指定異常的棧軌跡及錯誤消息寫入Servlet日誌文件
19 void log(String msg,Throwable throwable) 把棧軌跡及Throwable異常信息寫入Servlet日誌文件

JSP

1. JSP簡介

  • JSP全稱: Java Server Page,它是用於展示信息操作。
  • 爲了servlet展示信息的不方便,引入了JSP。
  • JSP本質上也是一個servlet。
  • JSP就是在HTML頁面中嵌入了java代碼。

2.JSP運行原理:

在Tomcat中的web.xml中,有一個默認的servlet,處理不可以處理的請求,還有一個JSPservlet,又叫servlet引擎,所有後綴爲.jsp的文件都處理。

當瀏覽器訪問http://localhost:8080/day9_1/index.jsp。服務器發現後綴爲.jsp,它會根據路徑找到index.jsp文件,會將index.jsp翻譯成index_jsp.java文件,對這個java文件進行編譯,產生一個index_jsp.class文件,將class文件加載運行。將JSP翻譯成java文件,它是將JSP中的所有的HTML代碼通過流進行輸出,也就是說最終翻譯成class,被虛擬機加載,它本質是servlet,它就會往回響應,響應回去就是把JSP中的HTML代碼以流的方式寫回瀏覽器。所以在JSP中展示出了HTML代碼。

3.在JSP中書寫JAVA代碼:

標籤 語法 作用
聲明標籤 <%! 變量或方法聲明%> 聲明JSP內所使用的全局變量或方法或內部類(它用於定義成員)(寫的內容在成員位置上)
表達式 <%= 表達式 %> 輸出java中變量或者表達式的值到頁面上(它用於輸出) out.print(內容)
程序代碼標籤 <%程序代碼%> 編寫java程序代碼,但不可以定義代碼(它用於定義局部)(聲明的變量在局部位置_jspService方法中)

4.JSP頁面組成:

一個JSP頁面可以被分爲以下幾部份:

  • 靜態數據,如HTML
  • JSP指令,如include指令:JSP指令控制JSP編譯器如何去生成servlet,以下是可用的指令
  • JSP腳本元素和變量
  • JSP動作
  • 用戶自定義標籤

指令標籤

頁面指令page –頁面指令有以下幾個選項: language指令 很少用,默認爲java 雖然一開始都在說jsp可能能支持其他語言例如C# php 但是一直到jsp死掉了 都沒有實現過。

  • import:使一個JAVA導入聲明被插入到最終頁面文件。導入Java包
 <%@ page import="java.util.*" %>
  • contentType:規定了生成內容的類型。當生成非HTML內容或者當前字符集character set並非默認字符集時使用。指定客戶端讀碼方式
  <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  • errorPage:處理HTTP請求時,如果出現異常則顯示該錯誤提示信息頁面。
  <%@ page  errorPage="Error.jsp" %>
  • isErrorPage:如果設置爲TRUE,則表示當前文件是一個錯誤提示頁面。
  <%@ page isErrorPage="true" %>
  • isThreadSafe:表示最終生成的servlet是否安全線程(threadsafe)。
  <%@ page isErrorPage="true" isThreadSafe="true" %>
  • pageEncoding:指定文件編碼,設定的是服務端以那種編碼格式讀取jsp文件
 <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
  • extend:指定這個jsp文件繼承自什麼類,默認不使用 亂用有麻煩。

include 指令

將另一個jsp文件包含進來,但是這個包含是靜態包含

  <%@include file="index.jsp" %>

JSP動作

JSP動作:JSP動作是一系列可以調用內建於網絡服務器中的功能的XML標籤。JSP提供了以下動作:

  • jsp:include 和子過程類似,JAVA SERVLET暫時接管對其它指定的JSP頁的請求和響應。當處理完該JSP頁後就馬上把控制權交還當前JSP頁。這樣JSP代碼就可以在多個JSP頁中共享而不用複製。
  • jsp:param 可以在jsp:include, jsp:forward或jsp:params塊之間使用。指定一個將加入請求的當前參數組中的參數。
  • jsp:forward 用於處理對另一個JSP或SERVLET的請求和響應。控制權永遠不會交還給當前JSP頁。
  • jsp:plugin Netscape Navigator的老版本和Internet Explorer使用不同的標籤以嵌入一個applet。這個動作產生爲嵌入一個APPLET所需要的指定瀏覽器標籤。
  • jsp:fallback 如果瀏覽器不支持APPLETS則會顯示的內容。
  • jsp:getProperty 從指定的JavaBean中獲取一個屬性值。
  • jsp:setProperty 在指定的JavaBean中設置一個屬性值。
  • jsp:useBean 創建或者複用一個JavaBean變量到JSP頁。`

JSP生命週期

JSP執行過程

  • JSP生命週期被定義爲從創建到破壞的過程。這類似於一個Servlet生命週期,需要一個額外的步驟來將JSP編譯成Servlet。JSP執行過程以下是JSP遵循的過程
  • 編譯: 解析JSP。將JSP轉換爲servlet。編譯servlet。
  • 初始化: 當容器加載JSP時,它會在處理任何請求之前調用jspInit()方法 ,一般會在jspInit()方法中初始化數據庫連接,打開文件和創建查找表。
  • 執行: JSP引擎將調用JSP中的_jspService()方法 響應請求
  • 清理: jspDestroy()方法,如:釋放數據庫連接或關閉打開的文件。

JSP 評價

是一個在當下已經落後的技術,學習的必要性在於許多框架和在運行項目任然在運行它,但是後續慢慢消失逐漸被新的框架取代是必然趨勢,就像ASP.NET 事件驅動動態web一樣都會逐漸消失

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章