J2EE梳理(三)——servlet基礎知識


通過servlet實現登錄功能
來自於how2java

步驟一:創建login.html

  • ctrl+n 新建 html
  • 添加form元素:
    • action=“login” 標題會提交到login路徑,login路徑在後續步驟會映射到LoginServlet
    • method=“post” post方式表示提交的密碼信息在瀏覽器地址欄看不到
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登錄頁面</title>
</head>
<body>
  
<form action="login" method="post">
賬號: <input type="text" name="name"> <br>
密碼: <input type="password" name="password"> <br>
<input type="submit" value="登錄">
</form>
  
</body>
</html>

步驟二:創建LoginServlet

  • 因爲瀏覽器中的form的method是post,所以LoginServlet需要提供一個doPost方法
  • 在doPost方法中,通過request.getParameter 根據name取出對應的賬號和密碼
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
  
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String name = request.getParameter("name");
        String password = request.getParameter("password");
  
        System.out.println("name:" + name);
        System.out.println("password:" + password);
    }
}

步驟四:映射loginservlet到路徑login

  • 即爲了當訪問login.html 點擊form action時候,對應的login 映射到servlet,
  • 在web.xml中新增映射
 <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>LoginServlet</servlet-class>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>   

步驟五:提交數據

  • 重啓tomcat
  • 訪問http://localhost/login
  • 在這裏插入圖片描述

步驟六:返回html響應

根據瀏覽器提交的賬號密碼返回登錄成功或者失敗
這一步本來應該通過訪問數據庫來實現,這裏簡化一下,直接在內存中進行校驗
如果賬號是 admin,密碼是123, 就返回登錄成功,否則返回登錄失敗

  • 判斷賬號密碼是否爲 admin 123,如果是就打印
    success 否則就打印 fail
  • 根據賬號密碼,創建對應的html字符串。
  • 然後通過response.getWriter().println() 發送到瀏覽器。
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
  
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
  
        String name = request.getParameter("name");
        String password = request.getParameter("password");
  
        String html = null;
  
        if ("admin".equals(name) && "123".equals(password))
            html = "<div style='color:green'>success</div>";
        else
            html = "<div style='color:red'>fail</div>";
  
        PrintWriter pw = response.getWriter();
        pw.println(html);
  
    }
  
}

在這裏插入圖片描述
注:在response中寫html只是爲了自己練習

總結:servlet流程梳理

  • 流程圖:在這裏插入圖片描述
  • login.html: 首先訪問http://127.0.0.1/login.html:打開一個靜態html,這個頁面可以通過form,以post的方式提交數據
  • /login路徑: 在上一步的login.html中,用form,把賬號和密碼,提交到/login這個路徑,並且附帶method=“post”
  • 找到對應的Servlet: tomcat接到一個請求http://localhost/login,路徑是/login,就去web.xml中進行匹配,根據標籤<servlet-mapping> 會匹配到LoginServlet,接下來根據這個servlet進行
  • 實例化servlet對象: tomcat定位到LoginServlet,發現沒有實例存在,於是就調用LoginServlet的構造方法實例化一個對象。
  • 調用doGet或者doPost: Tomcat拿到LoginServlet後,就根據頁面login.html提交的信息method="post"去調用對應的doPost方法;<form action="login" method="post">表示這個form會提交到action login
  • request獲取參數: doPost方法中
    protected void doPost(HttpServletRequest request, HttpServletResponse response){ ... } 其中通過參數request,取出頁面提交的信息:
    String name = request.getParameter("name"); String password = request.getParameter("password");
  • **response響應:**把html字符串通過如下方式,設置在了response對象上。
    PrintWriter pw = response.getWriter(); pw.println(html);
  • tomcat把html傳遞給瀏覽器::在Servlet完成工作之後,tomcat拿到被Servlet修改過的response,根據這個response生成html 字符串,然後再通過HTTP協議,這個html字符串,回發給瀏覽器,瀏覽器再根據HTTP協議獲取這個html字符串,並渲染在界面上。
    這樣在效果上,瀏覽器就可以看到Servlet中生成的字符串了

doService

  • doGet(): 當瀏覽器使用get方式提交數據的時候,servlet需要提供doGet()方法

    • form默認的提交方式
    • 如果通過一個超鏈訪問某個地址
    • 如果在地址欄直接輸入某個地址
    • ajax指定使用get方式的時候
  • doPost(): 當瀏覽器使用post方式提交數據的時候,servlet需要提供doPost()方法

    • 在form上顯示設置 method="post"的時候
    • ajax指定post方式的時候
  • service(): LoginServlet繼承了HttpServlet,同時也繼承了一個方法:service(HttpServletRequest , HttpServletResponse )

    • 實際上,在執行doGet()或者doPost()之前,都會先執行service(),由service()方法進行判斷,到底該調用doGet()還是doPost()
    • service(), doGet(), doPost() 三種方式的參數列表都是一樣的。
    • 所以,有時候也會直接重寫service()方法,在其中提供相應的服務,就不用區分到底是get還是post了。
    • 比如把前面的登錄的LoginServlet,改爲提供service方法,也可以達到相同的效果:
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class LoginServlet extends HttpServlet {
 
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
 
        String name = request.getParameter("name");
        String password = request.getParameter("password");
 
        String html = null;
 
        if ("admin".equals(name) && "123".equals(password))
            html = "<div style='color:green'>success</div>";
        else
            html = "<div style='color:red'>fail</div>";
 
        PrintWriter pw = response.getWriter();
        pw.println(html);
 
    }
 
}

獲取中文參數

  • login.html 中加上<meta http-equiv="Content-Type" content="text/html;charset="UTF-8">這句話的目的是告訴瀏覽器,等下發消息給服務器的時候,使用UTF-8編碼
  • 在servlet進行編碼解碼:
    • 當servlet不編碼解碼直接拿string:
    protected void service(HttpServletRequest request, HttpServletResponse response)
              throws ServletException, IOException {
          //request.setCharacterEncoding("UTF-8");
          String name = request.getParameter("name");
    
           /*byte[] bytes = name.getBytes("ISO-8859-1");
           name = new String(bytes, "UTF-8");*/
    
          String password = request.getParameter("password");
    
          System.out.println("name:" + name);
    
      }```
    

在這裏插入圖片描述

  • 當添加byte[] bytes = name.getBytes("ISO-8859-1");
    name = new String(bytes, "UTF-8");在這裏插入圖片描述
    先根據ISO-8859-1解碼,然後用UTF-8編碼
    這樣就可以得到正確的中文參數了

  • 這樣需要對每一個提交的數據都進行編碼和解碼處理,如果覺得麻煩,也可以使用一句話代替:request.setCharacterEncoding("UTF-8");不過這句話要在request.getParameter("name"); 之前,因爲如果不setCharactoerEncoding(),servlet會默認使用iso8859-1進行編碼,這也是我們上面byte[] bytes = name.getBytes("ISO-8859-1"); name = new String(bytes, "UTF-8");的原理。

  • 返回中文響應:同理,在servlet中加上response.setContentType("text/html; charset=UTF-8");
    所以這段代碼:

import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class LoginServlet extends HttpServlet {
 
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
 		request.setCharacterEncoding("UTF-8");
        String name = request.getParameter("name");
        String password = request.getParameter("password");
 		//System.out.println("name:" + name);
        String html = null;
 
        if ("admin".equals(name) && "123".equals(password))
            html = "<div style='color:green'>登錄成功</div>";
        else
            html = "<div style='color:red'>登錄失敗</div>";
 
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter pw = response.getWriter();
        pw.println(html);
 
    }
 
}

生命週期

  • 一個Servlet的生命週期由 實例化,初始化,提供服務,銷燬,被回收 幾個步驟組成
  • 在這裏插入圖片描述
  • 實例化:當用戶通過瀏覽器輸入一個路徑,這個路徑對應的servlet被調用的時候,該Servlet就會被實例化
    • 無論訪問了多少次LoginServlet,LoginServlet構造方法 只會執行一次,所以Servlet是單實例的
    • public LoginServlet(){ System.out.println("LoginServlet 構造方法 被調用"); }
  • 初始化:LoginServlet 繼承了HttpServlet,同時也繼承了init(ServletConfig) 方法
    • init 方法是一個實例方法,所以會在構造方法執行後執行。
    • 無論訪問了多少次LoginSerlvet,init初始化 只會執行一次
    • public void init(ServletConfig config) { System.out.println("init(ServletConfig)"); }
  • do service :在service()中就會編寫我們的業務代碼,在本例中就是判斷用戶輸入的賬號和密碼是否正確
  • 銷燬 :接着是銷燬destroy(),在如下幾種情況下,會調用destroy()
    • 該Servlet所在的web應用重新啓動,在server.xml中配置該web應用的時候用到了
      • <Context path="/" docBase="e:\\project\\j2ee\\web" debug="0" reloadable="false" />
      • 如果把 reloadable="false" 改爲reloadable="true" 就表示有任何類發生的更新,web應用會自動重啓,當web應用自動重啓的時候,destroy()方法就會被調用
    • 關閉tomcat的時候 destroy()方法會被調用,但是這個一般都發生的很快,不易被發現。
    • public void destroy() { System.out.println("destroy()"); }
  • 回收: 當servlet被銷燬,就滿足垃圾回收條件;當下次GC來的時候,就可能被回收
  • 下面我們通過一個實例觀察生命週期
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class LoginServlet extends HttpServlet {
	public LoginServlet(){
        System.out.println("LoginServlet 構造方法 被調用");
    }
	
	public void init(ServletConfig config) {
        System.out.println("init(ServletConfig)");
    }
	
	public void destroy() {
        System.out.println("destroy()!");
    }
	
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
 		request.setCharacterEncoding("UTF-8");
        String name = request.getParameter("name");
        String password = request.getParameter("password");
        System.out.println("name:" + name);
        String html = null;
 
        if ("admin".equals(name) && "123".equals(password))
            html = "<div style='color:green'>登錄成功</div>";
        else
            html = "<div style='color:red'>登錄失敗</div>";
 
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter pw = response.getWriter();
        pw.println(html);
 
    }
 
}

在這裏插入圖片描述

發佈了117 篇原創文章 · 獲贊 59 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章