国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Servlet】Servlet 詳解(使用+原理)

這篇具有很好參考價值的文章主要介紹了【Servlet】Servlet 詳解(使用+原理)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1. Servlet 介紹

1.1 什么是 Servlet

  • Servlet(Server Applet 的縮寫,全稱 Java Servlet):用 Java 編寫的服務(wù)器端程序。其主要功能在于交互式地瀏覽和修改數(shù)據(jù),生成動態(tài) Web 內(nèi)容。狹義的 Servlet 是指 Java 語言實現(xiàn)的一個接口,廣義的 Servlet 是指任何實現(xiàn)了這個 Servlet 接口的類,一般情況下,人們將 Servlet 理解為后者。

  • Servlet 運行于支持 Java 的應(yīng)用服務(wù)器中。從原理上講,Servlet 可以響應(yīng)任何類型的請求,但絕大多數(shù)情況下 Servlet 只用來擴展基于 HTTP 協(xié)議的 Web 服務(wù)器。

  • Servlet 是一種實現(xiàn)動態(tài)頁面的技術(shù),是一組由 Tomcat 提供給程序員的 API,幫助程序員簡單高效的開發(fā)一個 web app

1.2 Servlet 的主要工作

  • 允許程序員注冊一個類,在 Tomcat 收到的某個特定的 HTTP 請求的時候,執(zhí)行這個類中的一些代碼
  • 幫助程序員解析 HTTP 請求,把 HTTP 請求從一個字符串解析成一個 HttpRequest 對象
  • 幫助程序員構(gòu)造 HTTP 響應(yīng),程序員只要給指定的 HttpResponse 對象填寫一些屬性字段,Servlet 就會自動的按照 HTTP 協(xié)議的方式構(gòu)造出一個 HTTP 響應(yīng)字符串,并通過 Socket 編寫返回給客戶端

2. Servlet 程序創(chuàng)建步驟

2.1 創(chuàng)建項目

以下使用 IDEA 帶大家編寫一個簡單的 Servlet 程序,主要是讓大家了解一個大致的流程

  • 首先使用 IDEA 創(chuàng)建一個 Maven 項目【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 創(chuàng)建好的項目如下

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 通過上圖我們可以看到創(chuàng)建好的項目中有一些目錄結(jié)構(gòu),這是 Maven 項目的標(biāo)準(zhǔn)結(jié)構(gòu),其中

    • src 用于存放源代碼和測試代碼的根目錄
    • main 用于存放源代碼的目錄
    • test 用于存放測試代碼的目錄
    • java 用于存放 Java 代碼的目錄
    • resources 用于存放依賴的資源文件
    • pom.xml 是 Maven 項目的核心配置文件,關(guān)于這個 Maven 項目的相關(guān)屬性,都是在這個 xml 中進行配置

2.2 引入依賴

Maven 項目創(chuàng)建完成后,會自動生成一個 pom.xml 文件,我們需要在這個文件中引入 Servlet API 依賴的 jar 包

  • 打開中央倉庫,搜索 Servlet,點擊 Java Servlet API

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 選擇對應(yīng) Tomcat 版本的 Servlet(由于我當(dāng)前使用的是 Tomcat 8 系列,所以選擇 Servlet 3.1.0 即可)

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 將中央倉庫提供的該版本的 xml 復(fù)制到項目的 pom.xml

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 修改后的 pom.xml 文件如下

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

    一個項目中可以有多個依賴,每個依賴都是一個 <dependency> 標(biāo)簽。引入的依賴都要放在一個 <dependencies> 的標(biāo)簽中,該標(biāo)簽用于放置項目依賴的 jar 包,Maven 會自動下載該依賴到本地

  • 在拷貝的依賴中有幾個參數(shù),分別具有如下含義:

    • groupId 表示組織或者公司的 ID
    • artifactId 表示項目或者產(chǎn)品的 ID
    • version 表示版本號
    • scope 用于指定依賴的作用范圍,包含所在項目的測試、編譯、運行、打包等聲明周期。
  • 如果你想找到剛剛 Maven 下載到本地的第三方庫,路徑如下

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

2.3 創(chuàng)建目錄

Web 項目對于目錄結(jié)構(gòu)還有自己的要求,只有 Maven 的標(biāo)準(zhǔn)目錄是不夠的,需要再創(chuàng)建以下目錄并進行配置

  • 在 main 目錄下,創(chuàng)建一個 webapp 目錄

    webapp 目錄就是用于部署到 Tomcat 中的一個重要目錄,里面可以存放一些靜態(tài)資源

  • 在 webapp 目錄下,創(chuàng)建一個 WEB-INF 目錄

  • 在 WEB-INF 目錄下,創(chuàng)建一個 web.xml 文件

    Tomcat 通過找到這個 web.xml 文件才能夠正確處理 webapp 中的動態(tài)資源

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 編寫 web.xml

    Servlet 中 web.xml 中的內(nèi)容不能是空的,里面的寫法是固定的(這里的寫法專屬于 Servlet),用到的時候可以直接拷貝下面的代碼

    <!DOCTYPE web-app PUBLIC
    		"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    		"http://java.sun.com/dtd/web-app_2_3.dtd" >
    <web-app>
    	<display-name>Archetype Created Web Application</display-name>
    </web-app>
    

2.4 編寫代碼

以下編寫一個讓響應(yīng)返回一個自定義字符換的簡單代碼

  • 創(chuàng)建一個 TestServlet 類,并且讓它繼承于 HttpServlet

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

    HttpServlet 這個類來自于 pom.xml 中引入的 Servlet API 依賴的 jar 包

  • 在 TestServlet 類中重寫 doGet 方法

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

    doGet 是 HttpServlet 類中的方法,此處是在子類中重寫了父類的 doGet

  • 為了了解 doGet 方法的作用,我們可以看看它的源碼

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

    • HttpServletRequest 表示 HTTP 請求,Tomcat 按照 HTTP 請求的的格式把字符串格式的請求轉(zhuǎn)換成了一個 HttpServletRequest 對象,通過這個對象就可以獲取請求中的信息
    • HttpServletResponse 表示 HTTP 響應(yīng),通過代碼可以把響應(yīng)的對象構(gòu)造好,然后 Tomcat 將響應(yīng)返回給瀏覽器
    • 通過 doGet 的源碼我們可以大致了解,它的作用是根據(jù)收到的請求通過響應(yīng)返回一個 405 或者 400,那么我們可以重寫這個方法,根據(jù)收到的請求執(zhí)行自己的業(yè)務(wù)邏輯,把結(jié)果構(gòu)造成響應(yīng)對象
  • 在 doGet 方法中,通過 HttpServletResponse 類的 getWriter() 方法往響應(yīng)的 body 中寫入文本格式數(shù)據(jù)

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

    resp.getWriter() 會獲取到一個流對象,通過這個流對象就可以寫入一些數(shù)據(jù),寫入的數(shù)會被構(gòu)造成一個 HTTP 響應(yīng)的 body 部分,Tomcat 會把整個響應(yīng)轉(zhuǎn)成字符串,通過 Socket 寫回給瀏覽器

  • 需要給 TestServlet 加上一個特定的注解 @WebServlet("/test")

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

    上述助解表示 Tomcat 收到的請求中,URL 的 Servlet Path 路徑為 /test 的請求才會調(diào)用 TestServlet 這個類的代碼,注解中的字符串表示著 URL 的 Servlet Path

  • 到這里程序的編寫已經(jīng)完成了!但是你可能會疑惑上述代碼不是通過 main 方法作為入口的,這是因為 main 方法已經(jīng)被包含在 Tomcat 中了,我們寫的程序并不能單獨執(zhí)行,而是需要搭配 Tomcat 才能執(zhí)行起來(在 Tomcat 的偽代碼中我們具體分析了這個問題)

2.5 打包程序

在程序編寫好之后,就可以使用 Maven 進行打包

  • 首先修改 pom.xml,加入一些必要的配置(打包的類型和打包后的包名

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

    • packaging 標(biāo)簽中用于設(shè)置打包的類型(如果不修改打包類型則默認為 jar 包,jar 包是普通 Java 程序打包的結(jié)果,里面包含了一些 .class 文件;而部署在 Tomcat 中的壓縮包一般為 war 包,war 包里面是 Java Web 程序,里面除了 .class 文件之外,還包含 HTML、CSS、JavaScript、圖片等等)
    • finalName 標(biāo)簽中用于設(shè)置打包后的名字(包名很重要,它對應(yīng)著請求中 URL 的 Context Path
  • 執(zhí)行打包操作(打開 Maven 窗口,展開 Lifecycle,雙擊 package 進行打包)

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 打包成功后,可以發(fā)現(xiàn)多了個 target 目錄,該目錄下有一個 testServlet.war 的壓縮包

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

2.6 部署程序

接下來我們就可以進行程序的部署

  • 首先將打好的 war 包拷貝到 Tomcat 的 webapps 目錄下

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 啟動 Tomcat(在 Tomcat 的 bin 目錄中點擊 startup.bat

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

2.7 驗證程序

此時通過瀏覽器訪問 http://127.0.0.1:8080/testServlet/test 就可以看到程序?qū)崿F(xiàn)的結(jié)果了

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

注意:URL 中的路徑分成了兩個部分 Context Path 和 Servlet Path

  • Context Path 這個路徑表示一個 webapp,來源于打包的包名
  • Servlet Path 這個路徑表示一個 webapp 中的一個頁面,來源于對應(yīng)的 Servlet 類 @WebServlet 注解中的內(nèi)容

3. 使用 Smart Tomcat 進行部署

為了簡化上述操作流程,其實是有一些更簡單的方式

  • 對于創(chuàng)建項目、引入依賴、創(chuàng)建目錄這三個步驟,其實可以使用項目模板來快速生成,但是由于項目模板加載速度很慢,因此這里并不推薦
  • 對于打包程序和部署程序這兩個步驟,其實可以使用 Smart Tomcat 插件來快速實現(xiàn),以下將介紹它的使用方式

3.1 安裝 Smart Tomcat

  • 點擊 File → Settings

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 點擊 Plugins,在搜索欄搜索 Smart Tomcat,然后進行安裝即可

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

3.2 配置 Smart Tomcat

  • 點擊 Add Configuration

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 點擊左上角的+號,并選擇 Smart Tomcat

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 主要修改這三個參數(shù)

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

    • Name:這一欄其實可以隨便填
    • Tomcat Server:表示 Tomcat 所在的目錄
    • Deployment Directory:表示項目發(fā)布目錄
    • Context Path:表示項目路徑,默認值是項目名稱
    • Servlet Port:表示服務(wù)端口
    • Admin Port:表示管理端口
    • VM options:表示 JVM 參數(shù)
  • 配置好 Smart Tomcat 之后,Add Configuration 就會顯示成 Name 的名字,并且右邊多了個三角形運行的符號

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

3.3 使用 Smart Tomcat

  • 點擊三角形運行 Smart Tomcat,出現(xiàn)如下信息表示程序啟動成功

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 點擊藍色的連接,跳轉(zhuǎn)到項目路徑,再增加 Servlet Path 就可以顯示出該程序的結(jié)果

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

4. 訪問出錯解決方案

4.1 出現(xiàn) 404

出現(xiàn) 404 原因: 用戶訪問的資源不存在,大概率是 URL 的路徑寫的不正確

錯誤實例1: 少寫了 Context Path 或者 Context Path 寫錯了【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

錯誤實例2: 少寫了 Servlet Path 或者 Servlet Path 寫錯了

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web
錯誤實例3: web.xml 寫錯了(如清空 web.xml 中的內(nèi)容)

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

4.2 出現(xiàn) 405

出現(xiàn) 405 原因: 訪問的服務(wù)器不能支持請求中的方法或者不能使用該請求中的方法

錯誤實例1: 沒有重寫 doGet 方法

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

錯誤實例2: 重寫了 doGet 方法,但是沒有刪除父類的 doGet 方法

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

4.3 出現(xiàn) 500

出現(xiàn) 500 原因: 服務(wù)器出現(xiàn)內(nèi)部錯誤,往往是 Servlet 代碼中拋出異常導(dǎo)致的

錯誤實例: 代碼中出現(xiàn)空指針異常

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

4.4 出現(xiàn)“空白頁面”

出現(xiàn)空白頁原因: 響應(yīng)的 body 中并沒有內(nèi)容

錯誤實例:resp.getWriter().write() 操作刪除

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

4.5 出現(xiàn)“無法訪問此網(wǎng)站”

出現(xiàn)“無法訪問此網(wǎng)站”原因: 一般是不能正確訪問到 Tomcat(可能是 Tomcat 沒啟動,也可能是 IP/端口號寫錯了)

錯誤實例: 注解 @WebServlet 中少寫了 /【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

4.6 出現(xiàn)中文亂碼問題

響應(yīng)出現(xiàn)中文亂碼問題原因: 使用的編譯器的編碼方式(一般是 utf-8)和瀏覽器的編碼方式不同,瀏覽器默認跟隨系統(tǒng)編碼方式,win10 系統(tǒng)默認是 GBK 編碼

解決方式: 通過響應(yīng)對象的 setContentType() 方法來修改瀏覽器對于響應(yīng)正文的編碼格式

@WebServlet("/test")
public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().write("吞吞吐吐大魔王");
    }
}

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

5. Servlet 運行原理

在 Servlet 的代碼中,我們并沒有寫 main 方法,那么對應(yīng)的 doGet 代碼是如何被調(diào)用呢?響應(yīng)又是如何返回給瀏覽器的呢?

5.1 Servlet 的架構(gòu)

我們自己實現(xiàn)的 Servlet 是在 Tomcat 基礎(chǔ)上運行的,下圖顯示了 Servlet 在 Web 應(yīng)用程序中的位置

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

當(dāng)瀏覽器給服務(wù)器發(fā)送請求時,Tomcat 作為 HTTP 服務(wù)器,就可以接收到這個請求。Tomcat 的工作就是解析 HTTP 請求,并把請求交給 Servlet 的代碼來進行進一步的處理。Servlet 的代碼根據(jù)請求計算生成響應(yīng)對象,Tomcat 再把這個響應(yīng)對象構(gòu)造成 HTTP 響應(yīng),返回給瀏覽器。并且 Servlet 的代碼也經(jīng)常會和數(shù)據(jù)庫進行數(shù)據(jù)的傳遞。

5.2 Tomcat 的偽代碼

下面通過 Tomcat 的偽代碼的形式來描述 Tomcat 初始化和處理請求兩部分核心邏輯

  • Tomcat 的初始化流程

    class Tomcat {
    
        // 用來存儲所有的 Servlet 對象
        private List<Servlet> instanceList = new ArrayList<>();
        
        public void start() {
            // 根據(jù)約定,讀取 WEB-INF/web.xml 配置文件
            // 并解析被 @WebServlet 注解修飾的類
            
            // 假定這個數(shù)組里就包含了我們解析到的所有被 @WebServlet 注解修飾的類.
            Class<Servlet>[] allServletClasses = ...;
            
            // 這里要做的的是實例化出所有的 Servlet 對象出來;
            for (Class<Servlet> cls : allServletClasses) {
                // 這里是利用 java 中的反射特性做的
                // 實際上還得涉及一個類的加載問題,因為我們的類字節(jié)碼文件,是按照約定的
                // 方式全部在 WEB-INF/classes 文件夾下存放的,所以 tomcat 內(nèi)部是
                // 實現(xiàn)了一個自定義的類加載器(ClassLoader),用來負責(zé)這部分工作。
                
                Servlet ins = cls.newInstance();
                instanceList.add(ins);
            }
            
            // 調(diào)用每個 Servlet 對象的 init() 方法,這個方法在對象的生命中只會被調(diào)用這一次
            for (Servlet ins : instanceList) {
                ins.init();
            }
            
            // 啟動一個 HTTP 服務(wù)器,并用線程池的方式分別處理每一個 Request
            ServerSocket serverSocket = new ServerSocket(8080);
            // 實際上 tomcat 不是用的固定線程池,這里只是為了說明情況
            ExecuteService pool = Executors.newFixedThreadPool(100);
            
            while (true) {
                Socket socket = ServerSocket.accept();
                // 每個請求都是用一個線程獨立支持,這里體現(xiàn)了 Servlet 是運行在多線程環(huán)境下的
                pool.execute(new Runnable() {
                    doHttpRequest(socket);
                });
            }
            // 調(diào)用每個 Servlet 對象的 destroy() 方法,這個方法在對象的生命中只會被調(diào)用這一次
            for (Servlet ins : instanceList) {
                ins.destroy();
            }
        }
        
        public static void main(String[] args) {
        	new Tomcat().start();
        }
    }
    
    • Tomcat 的代碼內(nèi)置了 main 方法,當(dāng)我們啟動 Tomcat 的時候,就是從 Tomcat 的 main 方法開始執(zhí)行的
    • 被 @WebServlet 注解修飾的類會在 Tomcat 啟動的時候就被獲取到,并集中管理
    • Tomcat 通過反射這樣的語法機制來創(chuàng)建被 @WebServlet 注解修飾的類的實例
    • 這些實例被創(chuàng)建完之后,就會調(diào)用其中的 init 方法進行初始化
    • 這些實例被銷毀之前,就會調(diào)用其中的 destory 方法進行收尾工作
    • Tomcat 內(nèi)部也是通過 Socket API 進行網(wǎng)絡(luò)通信
    • Tomcat 為了能夠同時處理多個 HTTP 請求,采取了多線程的方式實現(xiàn),因此 Servlet 是運行在多線程環(huán)境下的
  • Tomcat 處理請求流程

    class Tomcat {
        
        void doHttpRequest(Socket socket) {
            // 參照我們之前學(xué)習(xí)的 HTTP 服務(wù)器類似的原理,進行 HTTP 協(xié)議的請求解析和響應(yīng)構(gòu)建
            HttpServletRequest req = HttpServletRequest.parse(socket);
            HttpServletRequest resp = HttpServletRequest.build(socket);
            
            // 判斷 URL 對應(yīng)的文件是否可以直接在我們的根路徑上找到對應(yīng)的文件,如果找到,就是靜態(tài)內(nèi)容
                
            // 直接使用 IO 進行內(nèi)容輸出
            if (file.exists()) {
                // 返回靜態(tài)內(nèi)容
                return;
            }
            
            // 走到這里的邏輯都是動態(tài)內(nèi)容了
            // 找到要處理本次請求的 Servlet 對象
            Servlet ins = findInstance(req.getURL());
            
            // 調(diào)用 Servlet 對象的 service 方法
            // 這里就會最終調(diào)用到我們自己寫的 HttpServlet 的子類里的方法了
            try {
            	ins.service(req, resp);
            } catch (Exception e) {
            	// 返回 500 頁面,表示服務(wù)器內(nèi)部錯誤
            }
        }
    }
    
    • Tomcat 從 Socket 中讀到的 HTTP 請求是一個字符串,然后 Tomcat 會按照 HTTP 協(xié)議的格式解析成一個 HttpServletRequest 對象
    • Tomcat 會根據(jù) URL 中的 Path 判定這個請求是請求一個靜態(tài)資源還是動態(tài)資源。如果是靜態(tài)資源,直接找到對應(yīng)的文件,把文件的內(nèi)容通過 Socket 返回;如果是動態(tài)資源,才會執(zhí)行到 Servlet 的相關(guān)邏輯
    • Tomcat 會根據(jù) URL 中的 Context Path 和 Servlet Path 確定要調(diào)用哪個 Servlet 實例的 service 方法
    • 通過 service 方法,就會進一步調(diào)用我們重寫的 doGet 或者 doPost 方法等等
  • Servlet 的 service 方法的實現(xiàn)

    class Servlet {
        public void service(HttpServletRequest req, HttpServletResponse resp) {
            String method = req.getMethod();
            if (method.equals("GET")) {
            	doGet(req, resp);
            } else if (method.equals("POST")) {
            	doPost(req, resp);
            } else if (method.equals("PUT")) {
            	doPut(req, resp);
            } else if (method.equals("DELETE")) {
            	doDelete(req, resp);
            }
            ......
        }
    }
    
    • Servlet 的 service 方法內(nèi)部會根據(jù)當(dāng)前請求的方式,決定調(diào)用其中的某個 doXXX 方法
    • 在調(diào)用 doXXX 方法的時候,會觸發(fā)多態(tài)機制,從而執(zhí)行到我們自己寫的子類的 doXXX 方法

6. Servlet API 詳解

對于 Servlet 主要介紹三個類,分別是 HttpServlet、HttpServletRequest 和 HttpServletResponse。

其中 HttpServletRequest 和 HttpServletResponse 是 Servlet 規(guī)范中規(guī)定的兩個接口,HttpServlet 中并沒有實現(xiàn)這兩個接口的成員變量,它們只是 HttpServlet 的 service 和 doXXX 等方法的參數(shù)。這兩個接口類的實例化是在 Servlet 容器中實現(xiàn)的。

6.1 HttpServlet

核心方法

方法名稱 調(diào)用時機
init 在 HttpServlet 實例化之后被調(diào)用一次
destory 在 HttpServlet 實例不再使用的時候調(diào)用一次
service 收到 HTTP 請求的時候調(diào)用
doGet 收到 GET 請求的時候調(diào)用(由 service 方法調(diào)用)
doPost 收到 POST 請求的時候調(diào)用(由 service 方法調(diào)用)
doPut/doDelete/doOptions/... 收到其它對應(yīng)請求的時候調(diào)用(由 service 方法調(diào)用)

Servlet 的生命周期: Servlet 的生命周期就是 Servlet 對象從創(chuàng)建到銷毀的過程,下面來介紹其生命周期的過程

  • Servlet 對象是由 Tomcat 來進行實例化的,并且在實例化完畢之后調(diào)用 init 方法(只調(diào)用一次
  • Tomcat 對于收到的請求,都會通過對應(yīng)的 Servlet 的 service 方法來進行處理(可以調(diào)用多次
  • Tomcat 在結(jié)束之前,會調(diào)用 Servlet 的 destory 方法來進行回收資源(最多調(diào)用一次

注意: init 和 service 能夠保證在各自的合適時機被 Tomcat 調(diào)用,但是 destory 不一定,它是否能夠被調(diào)用取決于 Tomcat 是如何結(jié)束的

  • 如果直接殺死進程,那么就來不及調(diào)用 destory
  • 如果通過 Tomcat 的管理端口(默認 8005)進行關(guān)閉,就能夠調(diào)用 destory

處理 GET 請求示例:

直接通過瀏覽器 URL 發(fā)送一個 GET 方法的請求,來對這個請求進行處理

@WebServlet("/get")
public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("get");
    }
}

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

處理 POST 請求示例:

由于通過瀏覽器 URL 發(fā)送的請求是 GET 方法的請求,因此我們需要通過其它方式來發(fā)送一個 POST 請求然后用于處理。發(fā)送 POST 請求的方式有通過 Ajax、form 表單或者 socket api 進行構(gòu)造,如果單純的用于測試就比較麻煩,這里推薦使用軟件 postman,這是一個很強大的 API 調(diào)試、Http 請求的工具。

@WebServlet("/post")
public class TestServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("post");
    }
}

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

6.2 HttpServletRequest

核心方法

方法 描述
String getProtocol() 返回協(xié)議的名稱和版本號
String getMethod() 返回請求的 HTTP 方法的名稱
String getRequestURL() 返回請求的 URL,不帶查詢字符串
String getRequestURI() 返回該請求的 URL 的一部分,不帶協(xié)議名、端口號、查詢字符串
String getContextPath() 返回指示請求 URL 中 Context Path 部分
String getServletPath() 返回指示請求 URL 中 ServletPath 部分
String getQueryString() 返回請求首行中 URL 后面的查詢字符串
Enumeration getParameterNames() 返回一個 String 對象的枚舉,包括在該請求中的參數(shù)的名稱
String getParameter(String name) 以字符串形式返回請求參數(shù)的值,如果參數(shù)不存在則返回 null
String[] getParameterValues(String name) 返回一個字符串對象的數(shù)組,包括所有給定的請求的參數(shù),如果參數(shù)不存在則返回 null
Enumeration getHeaderNames() 返回一個枚舉,包括該請求中所有的頭名
String getHeader(String name) 以字符串形式返回指定的請求頭的值
String getCharacterEncoding() 返回請求正文中使用的字符編碼的名稱
String getContentType() 返回請求正文的 MIME 類型,如果不知道類型則返回 null
int getContentLength() 以字節(jié)為單位返回請求正文的長度,并提供輸入流,如果長度未知則返回-1
InputStream getInputStream() 用于讀取請求的正文內(nèi)容,返回一個 InputStream 對象

示例1: 通過上述方法返回一個頁面是該請求的具體 HTTP 請求格式

@WebServlet("/showRequest")
public class ShowRequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 此處返回一個 HTML,在 HTML 中顯示 HttpRequestServlet 類中的一些核心方法
        // 把這些 API 的返回結(jié)果通過 StringBuilder 進行拼接
        resp.setContentType("text/html;charset=utf-8");
        StringBuilder html = new StringBuilder();
        html.append(req.getMethod());
        html.append(" ");
        html.append(req.getRequestURL());
        html.append("?");
        html.append(req.getQueryString());
        html.append(" ");
        html.append(req.getProtocol());
        html.append("</br>");
        Enumeration<String> headerNames = req.getHeaderNames();
        while(headerNames.hasMoreElements()){
            String headName = headerNames.nextElement();
            String header = req.getHeader(headName);
            html.append(headName);
            html.append(": ");
            html.append(header);
            html.append("</br>");
        }
        html.append("</br>");
        //InputStream body = req.getInputStream();
        resp.getWriter().write(html.toString());
    }
}

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

示例2: 處理 HTTP 請求的 body 中的數(shù)據(jù)格式

  • 如果 body 的內(nèi)容格式是 x-www-form-urlencoded,使用 getParameter 進行處理

    • 此處是要獲取 body 的數(shù)據(jù),由于 GET 方法一般沒有 body,這里使用 POST 方法演示
    • 約定 body 的數(shù)據(jù)格式為:x-www-form-urlencoded
    • 約定 body 的數(shù)據(jù)內(nèi)容為:username=123&passwd=456
    @WebServlet("/postParameter")
    public class PostParameterServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setContentType("text/html;charset=utf-8");
            String username = req.getParameter("username");
            String passwd = req.getParameter("passwd");
            resp.getWriter().write("username=" + username + "</br>" +"passwd=" + passwd);
    
        }
    }
    

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  • 如果 body 的內(nèi)容格式是 json,首先將整個 body 都讀取出來,再借助第三方庫的方法按照 json 的格式來進行解析,Java 標(biāo)準(zhǔn)庫沒有內(nèi)置對于 json 解析的方法)

    • 此處是要獲取 body 的數(shù)據(jù),由于 GET 方法一般沒有 body,這里使用 POST 方法演示
    • 約定 body 的數(shù)據(jù)格式為:json
    • 約定 body 的數(shù)據(jù)內(nèi)容為:
      {
      username=123,
      passwd=456
      }
    • 此處使用 jackson 第三方庫,使用之前需要去 Maven 的中央倉庫將 jackson 的依賴引入 pom.xml 中【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web
    • jackson 中的核心類是 ObjectMapper,通過這個類的 readValue(String content, Class<T> valueType) 方法,就可以將 json 字符串轉(zhuǎn)化為一個類的對象(第一個參數(shù)是 json 字符串,第二個參數(shù)是類對象),ObjectMapper 會遍歷定義的類中的每個成員的名稱,去 json 字符串的 key 中查找,如果找到了就將對應(yīng)的值返回給該成員
    // 自定義的將 json 字符串轉(zhuǎn)化的類
    class UserInfo {
        public String username;
        public String passwd;
    }
    
    @WebServlet("/jsonParameter")
    public class JsonParameterServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setContentType("text/html;charset=utf-8");
            // 1. 先將整個 body 讀取出來
            String body = readBody(req);
    
            // 2. 按照 json 格式進行解析
            ObjectMapper objectMapper = new ObjectMapper();
            UserInfo userInfo = objectMapper.readValue(body, UserInfo.class);
            resp.getWriter().write("username=" + userInfo.username + "</br>" + "passwd=" + userInfo.passwd);
        }
    
        // 定義一個方法來讀取請求中的全部 body
        private String readBody(HttpServletRequest req) throws IOException {
            // 1. 先拿到 body 的長度,單位是字節(jié)
            int contentLength = req.getContentLength();
            // 2. 準(zhǔn)備一個字節(jié)數(shù)組,來存放 body 內(nèi)容
            byte[] buffer = new byte[contentLength];
            // 3. 獲取到 InputStream 對象
            InputStream inputStream = req.getInputStream();
            // 4. 從 InputStream 對象中讀取到數(shù)據(jù),將數(shù)據(jù)放到字節(jié)數(shù)組中
            inputStream.read(buffer);
            // 5. 將存放 body 內(nèi)容的字節(jié)數(shù)組轉(zhuǎn)換成字符串
            return new String(buffer, "utf-8");
        }
    }
    

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

6.3 HttpServletResponse

核心方法

方法 描述
void setStatus(int sc) 為該響應(yīng)設(shè)置狀態(tài)碼
void setHeader(String name, String value) 設(shè)置一個帶有給定的名稱和值的 header,如果 name 已經(jīng)存在,則覆蓋舊的值
void addHeader(String name, String value) 添加一個帶有給定的名稱和值的 header,如果 name 已經(jīng)存在,不覆蓋舊的值,而是添加新的鍵值對
void setContentType(String type) 設(shè)置被發(fā)送到客戶端的響應(yīng)的內(nèi)容類型
void setCharacterEncoding(String charset) 設(shè)置被發(fā)送到客戶端的響應(yīng)的字符編碼,例如 utf-8
void sendRedirect(String location) 設(shè)置 Location 字段,實現(xiàn)重定向
PrintWriter getWriter() 用于往 body 中寫入文本格式數(shù)據(jù)
OutputStream getOutputStream() 用于往 body 中寫入二進制格式數(shù)據(jù)

示例1: 通過代碼,構(gòu)造出不同的響應(yīng)狀態(tài)碼

@WebServlet("/status")
public class StatusServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        int status = 404;
        resp.setStatus(status);
        resp.getWriter().write("status=" + status);
    }
}

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

示例2: 在響應(yīng)報頭設(shè)置一個 Refresh 字段,實現(xiàn)字段刷新程序

Refresh 的值表示每秒刷新的時間,當(dāng)程序是毫秒級刷新的時候,可能存在誤差

@WebServlet("/autoRefresh")
public class AutoRefreshServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 給響應(yīng)設(shè)置一個 Refresh 的 header,每隔 1s 鐘刷新一次
        resp.setHeader("Refresh", "1");

        // 返回一個當(dāng)前的時間,用來顯示刷新的效果
        resp.getWriter().write("timestamp=" + System.currentTimeMillis());
    }
}

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

示例3: 實現(xiàn)重定向操作

  • 方法一:在響應(yīng)報頭設(shè)置狀態(tài)碼和 Location 來實現(xiàn)重定向

    @WebServlet("/redirect")
    public class RedirectServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 將狀態(tài)碼設(shè)置為 3XX
            resp.setStatus(302);
            // 設(shè)置一個 Location,重定向到 CSDN 博客主頁
            resp.setHeader("Location", "https://blog.csdn.net/weixin_51367845?spm=1000.2115.3001.5343");
        }
    }
    
  • 方法二:直接使用 sendRedirect() 方法來實現(xiàn)重定向

    @WebServlet("/redirect")
    public class RedirectServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            resp.sendRedirect("https://blog.csdn.net/weixin_51367845?spm=1000.2115.3001.5343");
        }
    }
    

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

7. 實現(xiàn)服務(wù)器版表白墻程序

7.1 基本介紹

在之前的文章《【W(wǎng)eb 三件套】 JavaScript WebAPI》中實現(xiàn)過了一個純前端的表白墻代碼,實現(xiàn)后的效果如下。這次將會結(jié)合上述的知識,實現(xiàn)一個服務(wù)器版的表白墻程序【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

7.2 準(zhǔn)備操作

  1. 創(chuàng)建好一個 Servlet 項目

  2. 將之前寫好的純前端的表白墻代碼拷貝到 webapp 目錄下

  3. 約定好前后端交互的接口,該程序只需約定兩個接口

    • 從服務(wù)器獲取全部留言

      • 約定請求:方法為 GET,請求路徑為 /message

      • 約定響應(yīng):版本號為 HTTP/1.1,狀態(tài)碼為 200 OK,采用 JSON 數(shù)據(jù)格式

      • JSON 具體格式為:

        [
        ?	{
        ?		from: "",
        ?		to: "",
        ?		message: ""
        ?	}
        ]
        
    • 通過客戶端給服務(wù)器新增一個留言

      • 約定請求:方法為 POST,請求路徑為 /message
      • 約定響應(yīng):版本號為 HTTP/1.1,狀態(tài)碼為 200 OK,提交成功后響應(yīng)頁面顯示“提交成功”
  4. 創(chuàng)建一個 MessageServlet 類,@WebServlet 注解為 /message,對應(yīng)著約定的請求路徑,通過上方的約定完成服務(wù)器段的代碼

  5. 更改前端的代碼

7.3 代碼實現(xiàn)

后端代碼實現(xiàn):

import com.fasterxml.jackson.databind.ObjectMapper;

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.net.HttpRetryException;
import java.util.ArrayList;
import java.util.List;

// 這個類表示一條消息的詳細情況
class Message{
    public String from;
    public String to;
    public String message;
}

@WebServlet("/message")
public class MessageServlet extends HttpServlet {
    // 通過這個數(shù)組來表示所有的消息
    private List<Message> messages= new ArrayList<>();

    // 通過這個代碼來完成獲取服務(wù)器所有消息的操作
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf-8");
        // 獲取到消息列表
        // 此處要做的就是把當(dāng)前的 messages 數(shù)組轉(zhuǎn)成 json 格式返回給瀏覽器
        ObjectMapper objectMapper = new ObjectMapper();
        // 通過 ObjectMapper 的 writeValuesAsString() 方法就可以將一個對象轉(zhuǎn)換成 json 字符串
        // 由于這里的 message 是一個 List,那么得到的結(jié)果是一個 json 數(shù)組
        String jsonString = objectMapper.writeValueAsString(messages);
        resp.getWriter().write(jsonString);
    }

    // 通過這個代碼來完成新增消息的操作
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        ObjectMapper objectMapper = new ObjectMapper();
        Message message = objectMapper.readValue(req.getInputStream(), Message.class);
        messages.add(message);
        resp.getWriter().write("提交成功!");
    }
}

前端代碼實現(xiàn):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>表白墻</title>

    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        .container {
            width: 600px;
            margin: 0 auto;
        }
        h1 {
            text-align: center;
            padding: 20px 0;
            color: pink;
        }
        p {
            text-align: center;
            font-size: 15px;
            color: grey;
            padding: 5px 0;
        }
        .row {
            display: flex;
            height: 40px;
            justify-content: center;
            align-items: center;
        }
        .row span {
            width: 80px;
        }
        .row .edit {
            width: 250px;
            height: 35px;
        }
        .row .submit {
            width: 330px;
            height: 40px;
            background-color: orange;
            color: #fff;
            border: none;
        }
        .row .submit:active {
            background-color: grey;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>表白墻</h1>
        <p>輸入后點擊提交,將會把消息顯示在在墻上</p>
        <div class="row">
            <span>誰:</span>
            <input type="text" class="edit">
        </div>
        <div class="row">
            <span>對誰:</span> 
            <input type="text" class="edit">
        </div>
        <div class="row">
            <span>說什么:</span>
            <input type="text" class="edit">
        </div>
        <div class="row">
            <input type="button" value="提交"  class="submit">
        </div>
    </div>
    <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>

    <script>
        let submitButton = document.querySelector('.submit');
        submitButton.onclick = function() {
            // 1. 獲取到輸入框里的內(nèi)容
            let edits = document.querySelectorAll('.edit');
            let from = edits[0].value;
            let to = edits[1].value;
            let message = edits[2].value;
            // 2. 根據(jù)輸入框的內(nèi)容,構(gòu)造 HTML 元素,添加到頁面中
            if(from == '' || to == '' || message == '') {
                return;
            }
            let div = document.createElement('div');
            div.innerHTML = from + '對' + to + '說:' + message;
            div.className = 'row';
            let container = document.querySelector('.container');
            container.appendChild(div);
            // 3. 把上次輸入的內(nèi)容清空
            for(let i = 0; i < edits.length; i++){
                edits[i].value = '';
            }
            // 4. 把當(dāng)前新增的消息發(fā)送給服務(wù)器
            let body = {
                from: from,
                to: to,
                message: message
            };
            $.ajax ({
                url: "message",
                method: "post",
                contentType: "application/json;charset=utf8",
                // 通過 JSON.stringify 將對象轉(zhuǎn)成字符串
                data: JSON.stringify(body),
                success: function(data, status){
                    console.log(data);
                }
            })
        }


        // 服務(wù)器版本
        // 1. 在頁面加載的時候,從服務(wù)器獲取到消息列表,并顯示在網(wǎng)頁上
        function load() {
            $.ajax({
                method: "get",
                url: "message",
                success: function(data, status) {
                    // 此處得到的響應(yīng) data 其實已經(jīng)被 jquery 轉(zhuǎn)成了一個對象數(shù)組
                    // 但是這里的自動轉(zhuǎn)換有個前提,服務(wù)器響應(yīng)的 header 中 ContentType 是 json
                    let container = document.querySelector('.container');
                    for(let message of data){
                        // 遍歷每個元素,針對每個元素拆功能鍵一個 div 標(biāo)簽
                        let div = document.createElement('div');
                        div.className = 'row';
                        div.innerHTML = message.from + "對" + message.to + " 說:" + message.message;
                        container.append(div);
                    }
                }
            })
        }
        load();

    </script>
</body>
</html>

7.4 持久化存儲

通過上述修改,原本的純前端代碼就加上了服務(wù)器,只要服務(wù)器開啟后,即使刷新網(wǎng)頁,已經(jīng)添加的數(shù)據(jù)也不會消失。但是如果重啟服務(wù)器的話,原本的數(shù)據(jù)就會丟失,為了解決這個問題,就需要讓數(shù)據(jù)能夠持久化存儲。

持久化存儲: 是把數(shù)據(jù)(如內(nèi)存中的對象)保存到可永久保存的存儲設(shè)備中(如磁盤),是一種將程序數(shù)據(jù)在持久狀態(tài)和瞬時狀態(tài)間轉(zhuǎn)換的機制。

持久化存儲機制包括: JDBC文件 IO

接下來將通過增加一個數(shù)據(jù)庫來讓上述表白墻程序可以持久化存儲

  1. 先建庫建表(可以先創(chuàng)建一個文件,將要建的數(shù)據(jù)庫和表都寫好)

    drop database if exits messagewall;
    create database messagewall;
    
    use messagewall;
    
    drop table if exits message;
    create table message (
        `from` varchar(50),
        `to` varchar(50),
        `message` varchar(1024)
    );
    
  2. 在 pom.xml 文件中引入 mysql 的 jar 包【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  3. 連接數(shù)據(jù)庫,創(chuàng)建一個 DBUtil 類,用于封裝數(shù)據(jù)庫的建立連接和資源釋放操作

    import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
    
    import javax.sql.DataSource;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    // 通過這個類來封裝數(shù)據(jù)庫的建立連接操作
    public class DBUtil {
        private static final String URL = "jdbc:mysql://127.0.0.1:3306/messagewall?characterEncoding=utf8&setSSL=false";
        private static final String USERNAME = "root";
        private static final String PASSWORD = "1234";
    
        private static DataSource dataSource = new MysqlDataSource();
    
        static {
            ((MysqlDataSource)dataSource).setURL(URL);
            ((MysqlDataSource)dataSource).setUser(USERNAME);
            ((MysqlDataSource)dataSource).setPassword(PASSWORD);
        }
    
        public static Connection getConnection() throws SQLException {
            return dataSource.getConnection();
        }
    
        public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){
            if(resultSet != null){
                try {
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if(statement != null){
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if(connection != null){
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }
    
  4. 修改 MessageWall 類的代碼,主要修改的地方有兩處,將原本的 messages 數(shù)組刪除

    • 在獲取消息時,可以增加一個 getMessages() 方法,用于拿到數(shù)據(jù)庫中的所有消息

      // 從數(shù)據(jù)庫獲取到所有消息
      private List<Message> getMessages() {
          Connection connection = null;
          PreparedStatement statement = null;
          ResultSet resultSet = null;
          List<Message> messages = new ArrayList<>();
          try {
              // 1. 和數(shù)據(jù)庫建立連接
              connection = DBUtil.getConnection();
              // 2. 構(gòu)造 sql
              String sql = "select * from message";
              statement = connection.prepareStatement(sql);
              // 3. 執(zhí)行 sql
              resultSet = statement.executeQuery();
              // 4. 遍歷結(jié)果集合
              while(resultSet.next()){
                  Message message = new Message();
                  message.from = resultSet.getString("from");
                  message.to = resultSet.getString("to");
                  message.message = resultSet.getString("message");
                  messages.add(message);
              }
          } catch (SQLException throwables) {
              throwables.printStackTrace();
          } finally {
              DBUtil.close(connection, statement, resultSet);
          }
          return messages;
      }
      
    • 在新增消息是,可以新增一個 addMessage() 方法,用于往數(shù)據(jù)庫存儲一條新消息

      // 往數(shù)據(jù)庫新增一條消息
      private void addMessage(Message message) {
          Connection connection = null;
          PreparedStatement statement = null;
          try {
              // 1. 和數(shù)據(jù)庫建立連接
              connection = DBUtil.getConnection();
              // 2. 構(gòu)造 sql
              String sql = "insert into message values(?, ?, ?)";
              statement = connection.prepareStatement(sql);
              statement.setString(1, message.from);
              statement.setString(2, message.to);
              statement.setString(3, message.message);
              // 3. 執(zhí)行 sql
              statement.executeUpdate();
          } catch (SQLException throwables) {
              throwables.printStackTrace();
          } finally {
              DBUtil.close(connection, statement, null);
          }
      }
      

    到這里為止,一個完整的服務(wù)器表白程序就寫好啦!在我自己擼上面的代碼時,由于連接 MySQL 的 URL 中的端口號寫錯了,導(dǎo)致自己找了很久的 bug,所以大家如果嘗試上述代碼時遇到問題,一定要看清是不是自己哪個地方打錯了!

8. Cookie 和 Session

8.1 Cookie 介紹

在之前的文章《HTTP 協(xié)議詳解》中,就介紹過了 Cookie,可以結(jié)合本文的內(nèi)容來搭配理解。

  • Cookie 是什么?

    Cookie 是瀏覽器提供的在客戶端存儲數(shù)據(jù)的一種機制(由于瀏覽器禁止了網(wǎng)頁中的代碼直接訪問本地磁盤的文件,因此想要在網(wǎng)頁中實現(xiàn)持久化存儲,就可以通過 Cookie 這樣的機制)

  • Cookie 里面存什么?

    Cookie 存儲的數(shù)據(jù)都是程序員自定義的,存儲的數(shù)據(jù)是一個字符串,是鍵值對結(jié)構(gòu)的,鍵值對之間使用 ; 分割,鍵和值之間使用 = 分割

  • Cookie 從哪里來?

    服務(wù)器返回響應(yīng)的時候,可以把要在客戶端保存的數(shù)據(jù)以 Set-Cookie 這個 header 的方式返回給瀏覽器

  • Cookie 到哪里去?

    客戶端下次訪問服務(wù)器的時候,就會把之前保存好的 Cookie 再發(fā)送給服務(wù)器

  • Cookie 的典型應(yīng)用場景:

    可以使用 Cookie 來保存用戶的登錄信息。比如我們登錄過某個網(wǎng)站后,下次登錄時就不需要重新輸入用戶和密碼了

  • Cookie 的缺陷:

    每次請求都要把該域名下所有的 Cookie 通過 HTTP 請求傳給服務(wù)器,因此 Cookie 的存儲容量是有限的。

在了解 Cookie 以后,我們發(fā)現(xiàn) Cookie 是不能夠用于存儲和用戶相關(guān)的直接信息的,一是 Cookie 的存儲容量有限,二是發(fā)送請求時占用帶寬很多,三是不太安全。即這些數(shù)據(jù)不適合保存在客戶端,保存在服務(wù)器是更合適的,通過會話(Session)的方式就能夠保存這些數(shù)據(jù)。

8.2 Session 會話機制介紹

基本介紹:

在計算機中,尤其是在網(wǎng)絡(luò)應(yīng)用中,Session 稱為“會話控制”。Session 對象存儲特定用戶會話所需的屬性及配置信息。當(dāng)用戶在應(yīng)用程序的 Web 頁之間跳轉(zhuǎn)時,存儲在 Session 對象中的變量將不會丟失,而是在整個用戶會話中一直存在下去。當(dāng)用戶請求來自應(yīng)用程序的 Web 頁時,如果該用戶還沒有會話,則 Web 服務(wù)器將自動創(chuàng)建一個 Session 對象。當(dāng)會話過期或被放棄后,服務(wù)器將終止該會話。Session 對象最常見的一個用法就是存儲用戶的首選項。例如,如果用戶指明不喜歡查看圖形,就可以將該信息存儲在 Session 對象中。注意會話狀態(tài)僅在支持 Cookie 的瀏覽器中保留。

會話的本質(zhì):

  • 會話的本質(zhì)就是一個哈希表,其中存儲了一些鍵值對結(jié)構(gòu),key 叫做 sessionId,是一個不隨機的、不重復(fù)的、唯一的字符串,value 就是要保存的身份信息,通過 HttpSession 對象來保存。key 和 value 都是 Servlet 自動創(chuàng)建的。
  • 每個用戶登錄都會生成一個會話,服務(wù)器會以哈希表的方式將這些會話管理起來
  • 一個會話的詳細數(shù)據(jù)通過一個 HttpSession 對象來存儲,并且 HttpSession 對象中存儲的數(shù)據(jù)也是鍵值對結(jié)構(gòu),key 和 value 都是程序員自定義的

接著 Cooike 不適合用于存儲用戶相關(guān)的直接信息來講,由于客戶端不適合存儲這些數(shù)據(jù),服務(wù)器這邊可以通過 Session 會話的方式來進行保存。下面將會以用戶登錄的流程來介紹 Session 會話機制

  • 當(dāng)用戶成功登錄之后,服務(wù)器在 Session 中會生成一個新的記錄,并把 sessionId 返回給客戶端(例如 HTTP 響應(yīng)中可以通過 Set-Cookie 字段返回,其中 Cookie 的 key 為 “JSESSION”,value 為服務(wù)器生成的 sessionId 的具體的值)
  • 然后客戶端只需要保存這個 sessionId ,當(dāng)后續(xù)再給服務(wù)器發(fā)送請求時,請求中就會帶上 sessionId(例如 HTTP 請求中會帶上 Cookie 字段用于傳遞 Session)
  • 服務(wù)器收到請求后,就會根據(jù)請求中的 sessionId 在 Session 中查詢對應(yīng)用戶的身份信息,在進行后續(xù)操作

Session 會話機制的好處:

  • 使得客戶端很輕量,不用保存太多數(shù)據(jù)
  • 客戶端和服務(wù)器之間傳輸?shù)臄?shù)據(jù)量小,節(jié)省帶寬
  • 數(shù)據(jù)都在服務(wù)器存儲,即使客戶端出現(xiàn)問題,數(shù)據(jù)也不會丟失

注意: Servlet 的 Session 默認是保存在內(nèi)存中的,如果重啟服務(wù)器 Session 數(shù)據(jù)將會丟失

8.3 Cookie 和 Session 的區(qū)別

  • Cookie 是客戶端存儲數(shù)據(jù)的一種機制,可以存儲身份信息,也可以存儲其它信息,是鍵值對結(jié)構(gòu)的

  • Session 是服務(wù)器存儲數(shù)據(jù)的一種機制,主要用于存儲身份相關(guān)的信息,是鍵值對結(jié)構(gòu)的

  • Cookie 和 Session 經(jīng)常配合使用,但是不是必須的。

    • Cookie 也完全可以保存一些數(shù)據(jù)在客戶端,這些數(shù)據(jù)不一定是用戶身份信息,不一定是 sessionId
    • Session 中的 sessionId 也不需要非得通過 Cookie 和 Set-Cookie 來傳遞

8.4 Servlet 中 Cookie 和 Session 的核心方法

HttpServletRequest 類中的相關(guān)方法

方法 描述
HttpSession getSession(參數(shù)) 在服務(wù)器中獲取會話,參數(shù)如果為 true,當(dāng)不存在會話時會新建會話(包括生成一個新的 sessionId 和 HttpSession 對象),并通過 Set-Cookies 將 sessionId 返回給客戶端;參數(shù)如果為 false,當(dāng)不存在會話時會返回 null。如果存在 sessionId 且合法,就會根據(jù)這個 sessionId 找到對應(yīng)的 HttpSession 對象并返回
Cookie[] getCookies() 返回一個數(shù)組,包含客戶端發(fā)送請求時的所有 Cookie 對象,會自動把 Cookie 中的格式解析成鍵值對

HttpServletResponse 類中的相關(guān)方法

方法 描述
void addCookie(Cookie cookie) 把指定的 cookie 添加到響應(yīng)中

HttpSession 類中的相關(guān)方法

  • HttpSession是 Java平臺對 session 機制的實現(xiàn)規(guī)范,因為它僅僅是個接口,具體實現(xiàn)為每個 web 應(yīng)用服務(wù)器的提供商。
  • 服務(wù)器會為每一個用戶創(chuàng)建一個獨立的 HttpSession,表示為一個會話,并且一個 HttpSession 對象里包含了多個鍵值對,可以往 HttpSession 中存儲需要的數(shù)據(jù)
方法 描述
Object getAttribute(String name) 該方法返回在 Session 會話中具有指定名稱的對象,如果沒有指定名稱的對象,則返回 null
void setAttribute(String name, Object value) 該方法使用指定的名稱綁定一個對象到該 Session 會話中
boolean isNew() 判定當(dāng)前的會話是否是新創(chuàng)建的

Cookie 類中的相關(guān)方法

  • 這個類描述了一個 Cookie,通過 Cookie 類創(chuàng)建的對象,每個對象就是一個鍵值對
  • HTTP 的 Cookie 字段中實際上存儲的是多個鍵值對,每個鍵值對在 Servlet 中都對應(yīng)一個 Cookie 對象
方法 描述
String getName() 該方法返回 cookie 的名稱(這個值是 Set-Cookie 字段設(shè)置給瀏覽器的,創(chuàng)建之后不能改變)
String getValue() 該方法獲取與 Cookie 關(guān)聯(lián)的值
void setValue(String newValue) 該方法設(shè)置與 Cookie 關(guān)聯(lián)的值

8.5 實現(xiàn)用戶登錄功能

接下來將使用上述的 Session 和 Cookie 的相關(guān)方法來實現(xiàn)一個用戶登錄功能,并且可以記錄訪問頁面的次數(shù)

登錄功能實現(xiàn)思路:

  1. 讀取用戶提交的用戶和密碼
  2. 對用戶密碼進行校驗
  3. 判定是否登錄成功
  4. 創(chuàng)建會話,保存自定義信息
  5. 重定向到指定頁面

登錄功能實現(xiàn)流程:

  1. 先實現(xiàn)一個登錄頁面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>登錄頁面</title>
    </head>
    <body>
        <form action="login" method="post">
            <input type="text" name="username">
            <input type="password" name="password">
            <input type="submit" value="登錄">
        </form>
    </body>
    </html>
    

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

  2. 實現(xiàn)一個 Servlet 來處理上面的登錄請求

    由于這里是通過 form 表單來構(gòu)造的 post 請求,那么通過 HttpServletRequest 類中的 getParameter() 方法就能夠獲取請求正文中參數(shù)的值

    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("/login")
    public class LoginServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setContentType("text/html;charset=utf8");
            // 1. 從請求中獲取到用戶名和密碼
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            // 2. 對用戶密碼進行校驗
            if(username == null || "".equals(username) || password == null || "".equals(password)){
                resp.getWriter().write("<h3>賬號或密碼不能為空!</h3>");
                return;
            }
            // 3. 判斷是否登錄成功(假設(shè)用戶名為 admin,密碼為 1234。不過賬號密碼應(yīng)該用數(shù)據(jù)庫存儲,這里只是用來測試)
            if(!username.equals("admin") || !password.equals("1234")){
                resp.getWriter().write("<h3>賬號或密碼錯誤!</h3>");
                return;
            }
            // 4. 登錄成功,創(chuàng)建一個會話,用來記錄當(dāng)前用戶的信息
            HttpSession session = req.getSession(true);
            //    通過這個操作,就給會話中新增了一個程序員自定義的信息,訪問次數(shù)
            session.setAttribute("visitCount", 0);
            // 5. 把登錄成功的結(jié)果反饋給客戶端(這里的反饋不是簡單的提示“登錄成功”,而是直接跳轉(zhuǎn)到指定頁面)
            resp.sendRedirect("index");
        }
    }
    
  3. 通過實現(xiàn)一個 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 javax.servlet.http.HttpSession;
    import java.io.IOException;
    
    @WebServlet("/index")
    public class IndexServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setContentType("text/html;charset=utf8");
            // 只有登錄成功參數(shù)才能是 true,這里是拿參數(shù),所以要填 false
            HttpSession session = req.getSession(false);
            // 判斷當(dāng)前用戶是否登錄
            if(session == null){
                // 可以提示未登錄,也可以重定向到登錄頁面
                // resp.getWriter().write("<h3>登錄為空!</h3>");
                resp.sendRedirect("login2.html");
                return;
            }
            // 表示用戶登錄過,獲取會話中的訪問次數(shù)
            Integer visitCount = (Integer) session.getAttribute("visitCount");
            visitCount += 1;
            session.setAttribute("visitCount", visitCount);
            resp.getWriter().write("<h3>visitCount = " + visitCount + "</h3>");
        }
    }
    
  4. 到這里為止,一個簡單的用戶登錄功能就實現(xiàn)成功了。效果如下【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

9. 上傳文件操作

上傳文件是日常開發(fā)中的一類常見需求,在 Servlet 中也進行了支持

9.1 Servlet 中上傳文件的核心方法

HttpServletRequest 類中的相關(guān)方法

方法 描述
Part getPart(String name) 獲取請求中給定 name 的文件
Collection<Part> getParts() 獲取所有的文件

Part 類中的相關(guān)方法

方法 描述
String getSubmittedFileName() 獲取提交的文件名
String getContentType() 獲取提交的文件類型
long getSize() 獲取文件的大小,單位為字節(jié)
void write(String path) 把提交的文件數(shù)據(jù)寫入磁盤文件

9.2 上傳文件操作實現(xiàn)

  1. 先寫一個前端頁面,用于上傳文件

    • 上傳文件一般使用 post 請求的表單實現(xiàn)
    • 通過 form 表單構(gòu)造上傳文件,要加上一個 enctype 字段,它表示 body 中的數(shù)據(jù)格式,它的默認值為:x-www-form-urlencoded,這里要修改成:multipart/form-data,它是上傳文件或者圖片的數(shù)據(jù)格式
    • 第一個 input 中 type 的值為 file,它表示第一個輸入框為文件選擇框,name 的值與后端中通過 getPart 獲取指定文件的操作有關(guān)
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>上傳文件</title>
    </head>
    <body>
        <form action="upload" method="post" enctype="multipart/form-data">
            <input type="file" name="MyFile">
            <input type="submit" value="上傳">
        </form>
    </body>
    </html>
    
  2. 寫一個 Servlet 用于處理上傳的文件

    • 上傳文件操作還需要給 Servlet 加上一個 @MultipartConfig 注解,否則服務(wù)器代碼無法使用 getPart() 方法
    • getPart() 方法中的參數(shù)和 form 表單 input="file" 標(biāo)簽的 name 屬性對應(yīng)
    • 客戶端一次可以提交多個文件,getPart() 方法根據(jù) name 屬性來獲取不同的文件
    • 寫入磁盤文件操作的路徑之間可以使用兩個反斜杠 \\ ,也可以使用一個正斜杠 /
    • 寫入磁盤文件操作的路徑最后為保存后的文件名,包括文件后綴
    import javax.servlet.ServletException;
    import javax.servlet.annotation.MultipartConfig;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.Part;
    import java.io.IOException;
    
    @MultipartConfig
    @WebServlet("/upload")
    public class UploadServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setContentType("text/html;charset=utf8");
            // 通過 getPart 方法獲取到前端傳來的文件
            Part part = req.getPart("MyFile");
            // 獲取文件名
            String fileName = part.getSubmittedFileName();
            System.out.println("文件名為: " + fileName);
            // 獲取提交的文件類型
            String fileType = part.getContentType();
            System.out.println("文件類型為: " + fileType);
            // 獲取文件的大小
            long fileSize = part.getSize();
            System.out.println("文件大小為: " + fileSize);
    
    
            // 把文件數(shù)據(jù)寫入磁盤文件
            part.write("C:\\Users\\bbbbbge\\Desktop\\upload.jpg");
    
            resp.getWriter().write("上傳成功!");
        }
    }
    

    【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

到這里為止,一個簡單的文件上傳操作就實現(xiàn)好了,我們可以通過抓包來觀察下文件上傳操作的請求是怎樣的?

【servlet】servlet 詳解(使用+原理)-csdn博客,JavaEE,Servlet,java,java-ee,tomcat,web

通過抓包操作我們會發(fā)現(xiàn)幾點問題:文章來源地址http://www.zghlxwxcb.cn/news/detail-703017.html

  • 正文的大小和我們上傳文件的大小不同,正文的比上傳的文件的字節(jié)數(shù)略大
  • 數(shù)據(jù)類型是 multipart/form-data 沒有問題,但是后面多了一串 boundary=----WebKitFormBoundaryAl26z0nbP6JzAUGL,這個 boundary 在 body 中表示一個分隔線,第一條分割線下面是上傳的文件的屬性和文件的內(nèi)容,當(dāng)文件的內(nèi)容結(jié)束時還有第二條分割線
  • 由于有這個分割線和文件的一些屬性,因此使得請求中正文的大小比上傳的文件的內(nèi)容略大

到了這里,關(guān)于【Servlet】Servlet 詳解(使用+原理)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Servlet執(zhí)行原理和API詳解---【創(chuàng)建Servlet項目】

    Servlet執(zhí)行原理和API詳解---【創(chuàng)建Servlet項目】

    目錄 一、Servlet 是什么? 主要工作: 第一個Servlet項目: 編寫代碼 打包程序 Servlet 是一款基于HTTP協(xié)議,用來開發(fā)Java Web,運行在Tomcat里面的里的框架技術(shù)。 一種實現(xiàn)動態(tài)頁面的技術(shù) . 是一組 Tomcat 提供給程序猿的 API, 幫助程序猿簡單高效的開發(fā)一個 web app. 主要工作: 1.建立

    2024年02月10日
    瀏覽(17)
  • Servlet | Servlet原理、開發(fā)第一個帶有Java小程序Servlet

    ?作者簡介:一位材料轉(zhuǎn)碼農(nóng)的選手,希望一起努力,一起進步!? ??個人主頁:@每天都要敲代碼的個人主頁 ??系列專欄:Web后端 | Servlet 目錄 一:模擬實現(xiàn)Servlet 二:開發(fā)第一個帶有Java小程序Servlet【重點】 有了上一章節(jié)的分析,我們來模擬實現(xiàn)以下Servlet;下面先分析一

    2024年02月02日
    瀏覽(32)
  • 【JavaEE】Tomcat的安裝和使用、創(chuàng)建Mevan項目使用Servlet寫一個程序

    【JavaEE】Tomcat的安裝和使用、創(chuàng)建Mevan項目使用Servlet寫一個程序

    目錄 前言 一、Tomcat的下載和安裝 二、寫一個簡單的Servlet項目 1、創(chuàng)建一個Maven項目 2、引入依賴? 3、創(chuàng)建目錄? ?4、編寫Servlet代碼。 5、打包程序 6、將程序部署到Tomcat上 7、驗證程序運行結(jié)果 ?三、在IDEA上安裝Smart Tomcat插件 四、Servlet中的一些常見錯誤 我我們制作一個網(wǎng)站

    2024年02月17日
    瀏覽(21)
  • Servlet-搭建個人博客系統(tǒng)(MVC架構(gòu)模式簡介,maven的配置和使用)

    Servlet-搭建個人博客系統(tǒng)(MVC架構(gòu)模式簡介,maven的配置和使用)

    目錄 1. MVC架構(gòu)模式簡介 2. maven的配置和使用 3.?項目總述?? 3.1???Controller層 3.2???Model層 3.3???View層 4. 頁面的主要功能實現(xiàn)?? 4.1 ??登陸頁面(login.html) 4.2 ??博客列表頁面(blog_index.html) 4.3 ??博客詳情頁面(blog_detail.html) 4.4 ??博客編輯頁(blog_editor.html) 5.Conto

    2024年02月05日
    瀏覽(21)
  • [JAVAee]Tomcat - Servlet

    [JAVAee]Tomcat - Servlet

    目錄 Tomcat Servlet的工作 創(chuàng)建Servlet ①項目 ②依賴? ③目錄? ④代碼 ⑤打包 ⑥部署 ⑦驗證 Servlet的運行原理 Servlet API HttpServlet 方法 處理Get/POST請求? HttpServletRequest 方法 獲取請求中的信息? 獲取GET請求中的參數(shù) 獲取POST請求中的參數(shù) FORM表格形式 JSON形式 方法一: 方法二: Http

    2024年02月12日
    瀏覽(48)
  • 基于Java+MySQL+Tomcat+Servlet+Maven+JQuery+jackson+開源Markdown編輯器實現(xiàn)前后端分離個人博客系統(tǒng)

    基于Java+MySQL+Tomcat+Servlet+Maven+JQuery+jackson+開源Markdown編輯器實現(xiàn)前后端分離個人博客系統(tǒng)

    目錄 項目簡介 模塊實現(xiàn) 設(shè)計實現(xiàn)數(shù)據(jù)庫相關(guān)代碼 博客列表頁 博客詳情頁 注冊頁 登錄頁 檢測登錄狀態(tài) 顯示用戶信息 退出登錄 發(fā)布博客 刪除博客 統(tǒng)計博客數(shù)量 效果展示 部分代碼展示 小結(jié): ? ? 項目中使用了Java ,MySQL ,Tomcat ,Servlet ,Maven ,JQuery ,jackson,開源MarkDo

    2024年02月02日
    瀏覽(17)
  • 【JavaEE初階】Servlet (三)MessageWall

    【JavaEE初階】Servlet (三)MessageWall

    在我們之前博客中寫到的留言墻頁面,有很嚴重的問題:(留言墻博客) 如果刷新頁面/關(guān)閉頁面重開,之前輸入的消息就不見了. 如果一個機器上輸入了數(shù)據(jù),第二個機器上是看不到的. 針對以上問題,我們的解決思如如下: 讓服務(wù)器來存儲用戶提交的數(shù)據(jù),由服務(wù)器保存. 當(dāng)有新的瀏覽

    2024年02月14日
    瀏覽(22)
  • 【JavaEE初階】——第七節(jié).Servlet入門學(xué)習(xí)筆記

    【JavaEE初階】——第七節(jié).Servlet入門學(xué)習(xí)筆記

    作者簡介:大家好,我是未央; 博客首頁: 未央.303 系列專欄:JavaEE進階 每日一句:人的一生,可以有所作為的時機只有一次,那就是現(xiàn)在?。?! 文章目錄 前言 一、前置知識:Maven 1.1???初識Maven 1.2 ??Maven的使用 ?二、Servlet 第一個Servlet程序:hello world 方法步驟: 2.1 創(chuàng)

    2024年02月15日
    瀏覽(23)
  • 博客項目(前后端分離)(servlet實戰(zhàn)演練)

    博客項目(前后端分離)(servlet實戰(zhàn)演練)

    作者簡介:大家好,我是未央; 博客首頁: 未央.303 系列專欄:實戰(zhàn)項目 每日一句:人的一生,可以有所作為的時機只有一次,那就是現(xiàn)在!??!! 文章目錄 前言 項目介紹 一、MVC模式簡介 1.1??MVC 模式含義 1.2?MVC 的工作流程 二、項目概述 2.1?項目的幾個頁面 2.2?功能大概

    2024年02月07日
    瀏覽(25)
  • javaee idea創(chuàng)建maven項目,然后創(chuàng)建servlet

    javaee idea創(chuàng)建maven項目,然后創(chuàng)建servlet

    參考我的上一篇博客點擊查看 步驟一 引入依賴

    2024年02月11日
    瀏覽(27)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包