關於Servlet小總結

Jascen發表於2019-07-25

Servlet

Servlet簡介

  • Servlet(Service+Applet)伺服器小程式,主要用於生成動態的Web內容。
  • Servlet通常通過HTTP協議接收和響應來自Web客戶端的請求。
  • Servlet實際上是一個介面

Servlet簡單實現

  • 建立一個類:Myservlet 該檔案目錄為:D:\IdeaProjects\FirstServlet\src\servlet\MyServlet.java
package servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
//繼承HttpServlet類
public class MyServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter out = resp.getWriter();
        out.println("<h1 style='color:red'>"+"Hello Servlet"+"</h1>");
    }
}
  • 在WEB-INF資料夾下對web.xml中配置Servlet對映
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>myservlet</servlet-name>//類的別名
        <servlet-class>servlet.MyServlet</servlet-class>//該類的路徑
    </servlet>
    <servlet-mapping>
        <servlet-name>myservlet</servlet-name>//類的別名
        <url-pattern>/myservlet</url-pattern>//請求該類對應的URL
    </servlet-mapping>
</web-app>

實現原理:①當伺服器接受到客戶端瀏覽器的請求後,會解析請求URL路徑,獲取訪問的Servlet的資源路徑

               ②查詢web.xml檔案,是否有對應的<url-pattern>標籤體內容。

               ③如果有,則在找到對應的<servlet-class>全類名

               ④tomcat會將位元組碼檔案載入進記憶體,並且建立其物件

               ⑤呼叫其方法

建立Servlet的三種方法:

  • 實現Servlet介面

    *必須得實現介面中的抽象方法*
  • 繼承GenericServlet類

  • 繼承HttpServlet類

Servlet註解

每次建立Servlet類之後都要在WEB-INF資料夾下對web.xml中配置Servlet對映,但凡類較多的時候web.xml檔案會因為配置Servlet顯得檔案過長可讀性較差。而使用註解則不需要部署web.xml檔案。

PS:tomcat7之前的版本是不支援註解的。這是Servlet3的特性,所以在建立專案時指定版本3.0以上。

格式: @WebServlet("資源路徑") 在配置對映時,路徑要加斜槓,不然會報錯

package servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/myservlet")   //此處為Servlet註解 
//繼承HttpServlet類
public class MyServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter out = resp.getWriter();
        out.println("<h1 style='color:red'>"+"Hello Servlet"+"</h1>");
    }
}

Servlet生命週期

**①載入Servlet類。**

        類載入器負責載入servlet類。 當Web容器接收到servlet的第一個請求時,將載入servlet類。

**②建立Servlet例項。**

        載入servlet類之後在第一次訪問Servlet對應的URL時,tomcat會對該Servlet類建立物件,並執行建構函式。servlet例項在servlet生命週期中只建立一次。

**③呼叫Servlet類的`init`方法。初始化**

        在第一次建立Servlet時被呼叫,只呼叫一次,後續請求不再呼叫。用於一次性初始化。

**④呼叫Servlet類的`service`方法。提供服務**

        當對Servlet進行訪問時,就會提供訪問服務方法(如:`service()` `doGet()` `doPost()`)處理來自客戶端(瀏覽器)的請求,並把格式化的響應寫回給客戶端。

**⑤呼叫Servlet類的`destroy`方法。銷燬**

    從服務中刪除servlet例項之前(關閉或重啟tomcat),Web容器呼叫`destroy`方法。在呼叫 destroy() 方法之後,servlet 物件被標記為垃圾回收,釋放資源。

啟動時載入Servlet

啟動時載入常用於系統的預處理

  在web.xml使用<load-on-startup>設定啟動時載入,所傳遞的值表示載入時的優先順序,**若傳遞的為負值則系統第一個載入**

Servlet客戶端 HTTP請求的結構

  • HTTP請求包含三部分:請求行、請求頭、請求體

    • 請求行(請求方法、請求URL、HTTP協議及版本)

      如:POST /loginServlet HTTP/1.1

      關於請求方式:POST請求的請求引數在請求體中

                             **GET請求的請求引數在請求行中,在URL之後**
    • 請求頭

      Host: localhost:8080
         User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0
         Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
         Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2

      Accept-Encoding: gzip, deflate
      Content-Type: application/x-www-form-urlencoded
      Content-Length: 30
      Connection: keep-alive
      Referer: http://localhost:8080/FirstServlet/login.html
      Cookie: JSESSIONID=131FD70E4649021B826F5654951687CF
      Upgrade-Insecure-Requests: 1

      User-Agent(使用者環境,包括客戶使用的作業系統及版本 CPU型別 瀏覽器版本等一些資訊)

    • 請求體(封裝POST請求訊息的請求引數)

      username=admin&password=123456

Servlet伺服器 HTTP響應的結構

  • HTTP響應包含三部分:響應行、響應頭、響應體

    • 響應行(報文協議及版本、狀態碼及狀態描述)

      Http/1.1 200 OK
    • 響應頭(一些輔助資訊)

      Content-Type:text/html
      
          .......
    • 響應體(描述了瀏覽器要響應的資訊)

HTTP常見狀態碼

狀態碼 錯誤描述
200 伺服器處理成功
404 無法找到檔案
500 內部伺服器錯誤
403 伺服器拒絕訪問
301、302 請求重定向
400 無效的請求
401 未經過授權
503 伺服器超負荷或停機維護,無法處理請求

ConteneType的作用

  • ConteneType決定瀏覽器以何種方式來處理響應體
型別 描述
text/plain 純文字
text/html HTML文件
text/xml xml文件
application/x-msdownload 需要下載的資源

Servlet請求轉發與響應重定向

Servlet請求轉發

原理:輸入一個正確的URL之後,會產生一個請求傳送到Tomcat上,在Servlet_A處理完之後呼叫request.getRequestDispatcher().forward()方法之後,將HttpServletRequest物件原封不動的傳送給Servlet_B,在Servlet_B處理完之後產生響應返回給客戶端。

關於Servlet小總結

checkLogin.java

package servlet_direct;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/direct/check")
public class checkLogin extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("使用者登入成功!");
        req.getRequestDispatcher("/direct/index").forward(req,resp);//請求轉發語句
    }
}

indexServlet.java

package servlet_direct;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/direct/index")
public class indexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("<h1>This is index page</h1>" );
    }
}
    ②轉發只能訪問當前伺服器下的資源

    ③轉發是一次請求,可以使用request物件來共享資料

Servlet響應重定向

原理:輸入一個正確的URL之後,會產生一個請求傳送到Tomcat上,在Servlet_A處理完產生響應返回給客戶端,客戶端再產生新的請求跳轉到新地址上,由Tomcat傳送給Servlet_B處理完之後產生新的響應返回給客戶端。

關於Servlet小總結

checkLogin.java

package servlet_direct;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/direct/check")
public class checkLogin extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("使用者登入成功!");
        resp.sendRedirect("/FirstServlet/direct/index");//響應重定向語句
    }
}

indexServlet.java

package servlet_direct;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/direct/index")
public class indexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("<h1>This is index page</h1>" );
    }
}

請求轉發和響應重定向比較

請求轉發 響應重定向
轉發位址列路徑不變 位址列發生變化
只能訪問當前伺服器下的資源 可以訪問其他站點(伺服器)的資源
一次請求,可以使用request物件來共享資料 兩次請求。不能使用request物件來共享資料

會話技術(Cookie和Session)

會話:客戶端和伺服器之間發生一系列的請求與響應的過程。(一方斷開即會話結束)

作用:在一次會話的範圍內的多次請求間,共享資料

方式: 客戶端會話技術:Cookie

        伺服器端會話技術:Session

概念:客戶端會話技術,將資料儲存到客戶端。當使用者通過瀏覽器訪問Web伺服器時,伺服器會給客戶端傳送一些資訊伺服器向客戶端傳送Cookie時,會在HTTP響應頭中增加Set-Cookie響應頭資訊,這些資訊會儲存在Cookie中。這樣,當瀏覽器再次訪問伺服器時,會在請求頭中將Cookie傳送給伺服器,方便伺服器對瀏覽器做出正確的響應。

關於Servlet小總結

Cookie工作原理

當瀏覽器向伺服器傳送請求之後,伺服器會建立一個Cookie物件,將資料儲存在其中,然後把Cookie物件放在響應頭(response.addCookie(cookie物件))傳送給瀏覽器,瀏覽器接收響應後將Cookie儲存在客戶端;當瀏覽器再次訪問伺服器時,會把儲存的Cookie放在請求頭中一起傳送給伺服器,伺服器從中獲取Cookie(request.getCookie()),然後作出響應。

cookie_first.java

package servlet_cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/cookie_first")
public class cookie_first extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       //建立Cookie物件,儲存相應資料
        Cookie cookie = new Cookie("name", "Jack");
        //將生成的cookie傳送給瀏覽器
        response.addCookie(cookie);
       //設定持久化時間
        cookie.setMaxAge(60*2);//有效時間2分鐘
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

cookie_second.java

package servlet_cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/cookie_second")
public class cookie_second extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //伺服器從中獲取cookie
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            response.getWriter().println(cookie.getName()+"="+cookie.getValue());
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

Servlet Session

概念:伺服器端會話技術,在一次會話的多次請求間共享資料,將資料儲存在伺服器端的物件中。瀏覽器訪問Web伺服器時,Servlet容器就會建立一個Session物件和ID屬性,當客戶端後續訪問伺服器時,只要將標識號傳遞給伺服器,伺服器就能判斷該請求是哪個客戶端傳送的,從而選擇與之對應的Session物件為其服務。預設情況下session的有效時間為30分鐘。

關於Servlet小總結

Session工作原理

客戶端傳送一個全新的請求給伺服器,伺服器就會建立一個Session物件,並且設定SessionId:178HA。然後Servlet會執行session.setAttribute("name","王小二");設定自定義屬性,把資料封裝在這個Session物件中,將Session物件儲存在伺服器中。之後會將SessionID連同響應回瀏覽器,瀏覽器就會把SessionId值儲存在Cookie中。在下一次傳送請求時,會攜帶SessionID:178HA給伺服器。伺服器會根據所獲取的Session編號找到對應的Session物件,然後利用該Session物件把儲存的資料取出來!

loginServlet.java

package servlet_session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session/login")
public class loginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //建立Session物件
        HttpSession session = req.getSession();
        //設定自定義屬性
        session.setAttribute("name","王小二");
        //獲取SessionId
        System.out.println(session.getId());
        req.getRequestDispatcher("/session/index").forward(req,resp);
    }
}

indexServlet.java

package servlet_session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/session/index")
public class indexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        System.out.println(session.getId());
        //獲取自定義屬性
        String name =(String)session.getAttribute("name");
        //設定響應編碼格式
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().println("當前登入使用者為:"+name);
    }
}

Post請求中文亂碼

對於Tomcat8.X版本,預設Get請求傳送中文就是UTF-8格式,無須轉換。

而對於Post請求,通過呼叫setCharacterEncoding("UTF-8")來解決中文亂碼問題。

相關文章