Servlet 學習筆記

? 本文為記錄Servlet學習時的一些筆記和代碼 課程參考黑馬程序員 對于Java Web 學習的一個復習

一 概述

server applet 運行在服務器端的小程序 本質就是一個接口 定義java類被瀏覽器訪問到(Tomcat識別)的規則

我們會自定義這樣一個類來實現復寫方法實現接口


二 快速入門

1 創建javaEE項目

2 定義一個類 實現servlet接口

3 實現接口的抽象方法

4 配置servlet

package com.ts.servletdem0.servlet;//import jakarta.servlet.*;
import jakarta.servlet.*;
import java.io.IOException;/*
*   servlet的快速入門
* */
public class ServletDemo1 implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}// 提供服務的方法@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("Hello Servlet");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}
}

?web配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"version="5.0">// 配置Servlet<servlet><servlet-name>demo1</servlet-name><servlet-class>com.ts.servletdem0.servlet.ServletDemo1</servlet-class></servlet><servlet-mapping><servlet-name>demo1</servlet-name><url-pattern>/demo1</url-pattern></servlet-mapping></web-app>

三 執行原理

1 當服務器接受到客戶端瀏覽器的請求后 會解析瀏覽器的URL路徑 獲取訪問的servlet資源

2 查找web.xml文件 是否有對應的<url-pattern>標簽體內容

3 如果有 則尋找對應的<servlet-class>全類名

4 tomcat會把字節碼文件加載進內存 并且創建對象

5 調用其方法


四 生命周期

?servlet的生命周期方法:

生命周期方法

觸發時機

執行次數

典型應用場景

init()

首次請求或服務器啟動時

1次

初始化數據庫連接、加載配置文件

service()

每次HTTP請求

多次

核心業務邏輯處理

destroy()

服務器正常關閉

1次

釋放資源、保存狀態

1.被創建:調用init方法 只執行一次

? ? 默認是第一次被訪問時創建

? ? 可以通過配置來決定執行的時機

  <servlet><servlet-name>demo1</servlet-name><servlet-class>com.ts.servletdem0.servlet.ServletDemo1</servlet-class><!-- 初始化創建的時機 --><!-- 負數為第一次被訪問時創建 0或正整數是啟動服務器的時候創建--><load-on-startup>1</load-on-startup></servlet>

? ?[一個servlet在內存中只存在一個對象 是單例的]

? ?所以多個用戶訪問時會存在線程安全問題

? ?解決方法:在servlet中盡量不定義成員變量 即使定義也不要進行修改操作

2.提供服務:調用servlet方法 可以執行多次

3.被銷毀:執行destroy方法 只執行一次 (只有服務器正常關閉時才會執行)

/*
*   servlet的方法
* */
public class ServletDemo2 implements Servlet {/**    初始化方法*    在servlet創建時執行 只會調用一次init方法* */@Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println("init...");}/**   獲取Servlet的配置對象*   返回ServletConfig對象* */@Overridepublic ServletConfig getServletConfig() {return null;}/* 提供服務的方法*  每一次servlet服務被請求時調用* */@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("service...");}/**   獲取Servlet的信息*   返回一個字符串,用來描述Servlet* */@Overridepublic String getServletInfo() {return new String("ServletDemo2");}/**   銷毀方法*   在服務器關閉時執行一次 在servlet被銷毀時調用* */@Overridepublic void destroy() {System.out.println("destroy...");}
}

五 servlet配置?

? ?XML配置??:

<servlet-mapping><servlet-name>demo</servlet-name><!-- 支持多路徑映射 --><url-pattern>/api/*</url-pattern><url-pattern>.action</url-pattern>
</servlet-mapping>

? ?注解配置技巧??:

@WebServlet(name = "AdvancedServlet",urlPatterns = {"/v1/users", "/backup"},initParams = {@WebInitParam(name="timeout", value="5000")},loadOnStartup = 1
)
public class AdvancedServlet extends HttpServlet { ... }

? servlet_3.0 支持注解配置 使用@WebServlet("資源路徑”)

@WebServlet("/test")
public class TestServlet implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println("init");}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("Servlet 3.0 啟動");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}
}

servlet --> GenericServlet --> HttpServlet 抽象類? 對Http協議的一種封裝 簡化操作為繼承該類后 復寫doGet/doPost方法?


urlpartten: Servlet訪問路徑

(一個servlet可以配置多個訪問路徑)

@WebServlet({"/t4","/tt4","/ttt4"})
public class TestServlet1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {System.out.println("Test_多路徑");}}

六 HTTP

概念:Htyper Text Transfer Protocol?傳輸協議 定義了客戶端和服務端通訊時 發送數據的格式

特點:1.基于TCP/IP的高級協議

? ? ? ? ? ?2.默認端口80

? ? ? ? ? ?3.基于請求/響應模型的:一次請求對應一次響應

? ? ? ? ? ?4.無狀態的:每次請求之間相互獨立 不能交互數據

請求方式:

常用的有兩種:

GET:1 請求參數在請求行中 在url后

? ? ? ? ? ?2 請求的url長度有限制

? ? ? ? ? ?3 不太安全

POST:1 請求參數在請求體中

? ? ? ? ? ?2 請求的url長度沒有限制的

? ? ? ? ? ?3 相對安全

請求消息數據格式:

請求報文結構??:

GET /test?name=value HTTP/1.1 ? ? ? ? ? → 請求行
Host: www.example.com ? ? ? ? ? ? ? ? ? ↗
Content-Type: text/html ? ? ? ? ? ? ? ?→ 請求頭
Accept-Language: zh-CN ? ? ? ? ? ? ? ? ↗
→ 空行
username=admin&password=123456 ? ? ? ?→ 請求體(僅POST)

? ? ? ?請求行? :請求方式 請求url 請求協議 版本

???????請求頭: 請求體名稱

???????請求空行:空行

???????請求體:正文

響應消息數據格式:


七 Request

// 獲取客戶端信息
String ip = request.getRemoteAddr();
String userAgent = request.getHeader("User-Agent");// 獲取請求參數
String username = request.getParameter("user");
String[] hobbies = request.getParameterValues("hobby");// 請求作用域傳值
request.setAttribute("currentUser", userObj);
User u = (User)request.getAttribute("currentUser");// 請求轉發
request.getRequestDispatcher("/success.jsp").forward(request, response);

八 案例

// File: src/main/java/com/example/web/UserServlet.java
package com.example.web;import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import java.io.*;
import java.sql.*;@WebServlet("/user")
public class UserServlet extends HttpServlet {private static final String DB_URL = "jdbc:mysql://localhost:3306/userdb";private static final String DB_USER = "root";private static final String DB_PASS = "password";@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String action = request.getParameter("action");if ("register".equals(action)) {registerUser(request, response);} else if ("login".equals(action)) {loginUser(request, response);}}private void registerUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");String email = request.getParameter("email");try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS)) {String sql = "INSERT INTO users (username, password, email) VALUES (?, ?, ?)";try (PreparedStatement pstmt = conn.prepareStatement(sql)) {pstmt.setString(1, username);pstmt.setString(2, password);pstmt.setString(3, email);int rows = pstmt.executeUpdate();if (rows > 0) {request.setAttribute("message", "注冊成功!請登錄");request.getRequestDispatcher("/login.jsp").forward(request, response);} else {request.setAttribute("error", "注冊失敗");request.getRequestDispatcher("/register.jsp").forward(request, response);}}} catch (SQLException e) {throw new ServletException("數據庫錯誤: " + e.getMessage());}}private void loginUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS)) {String sql = "SELECT * FROM users WHERE username = ? AND password = ?";try (PreparedStatement pstmt = conn.prepareStatement(sql)) {pstmt.setString(1, username);pstmt.setString(2, password);try (ResultSet rs = pstmt.executeQuery()) {if (rs.next()) {// 創建會話HttpSession session = request.getSession();session.setAttribute("username", username);session.setAttribute("email", rs.getString("email"));// 設置會話有效期30分鐘session.setMaxInactiveInterval(30 * 60);response.sendRedirect("profile.jsp");} else {request.setAttribute("error", "用戶名或密碼錯誤");request.getRequestDispatcher("/login.jsp").forward(request, response);}}}} catch (SQLException e) {throw new ServletException("數據庫錯誤: " + e.getMessage());}}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 注銷處理String action = request.getParameter("action");if ("logout".equals(action)) {HttpSession session = request.getSession(false);if (session != null) {session.invalidate();}response.sendRedirect("login.jsp");}}
}
<!-- File: webapp/login.jsp -->
<!DOCTYPE html>
<html>
<head><title>用戶登錄</title><style>body { font-family: Arial, sans-serif; max-width: 400px; margin: 0 auto; padding: 20px; }.form-group { margin-bottom: 15px; }label { display: block; margin-bottom: 5px; }input[type="text"], input[type="password"] { width: 100%; padding: 8px; }button { padding: 10px 20px; background: #007bff; color: white; border: none; cursor: pointer; }.error { color: red; }</style>
</head>
<body><h2>用戶登錄</h2><% if (request.getAttribute("error") != null) { %><p class="error">${error}</p><% } %><form action="user" method="post"><input type="hidden" name="action" value="login"><div class="form-group"><label>用戶名:</label><input type="text" name="username" required></div><div class="form-group"><label>密碼:</label><input type="password" name="password" required></div><button type="submit">登錄</button></form><p>還沒有賬號? <a href="register.jsp">立即注冊</a></p>
</body>
</html>
<!-- File: webapp/register.jsp -->
<!DOCTYPE html>
<html>
<head><title>用戶注冊</title><style>body { font-family: Arial, sans-serif; max-width: 400px; margin: 0 auto; padding: 20px; }.form-group { margin-bottom: 15px; }label { display: block; margin-bottom: 5px; }input { width: 100%; padding: 8px; }button { padding: 10px 20px; background: #28a745; color: white; border: none; cursor: pointer; }.error { color: red; }</style>
</head>
<body><h2>用戶注冊</h2><% if (request.getAttribute("error") != null) { %><p class="error">${error}</p><% } %><form action="user" method="post"><input type="hidden" name="action" value="register"><div class="form-group"><label>用戶名:</label><input type="text" name="username" required></div><div class="form-group"><label>密碼:</label><input type="password" name="password" required></div><div class="form-group"><label>郵箱:</label><input type="email" name="email" required></div><button type="submit">注冊</button></form><p>已有賬號? <a href="login.jsp">立即登錄</a></p>
</body>
</html>
<!-- File: webapp/profile.jsp -->
<!DOCTYPE html>
<html>
<head><title>用戶資料</title><style>body { font-family: Arial, sans-serif; max-width: 500px; margin: 0 auto; padding: 20px; }.welcome { font-size: 1.2em; margin-bottom: 20px; }.info { background: #f8f9fa; padding: 15px; border-radius: 5px; }.logout { margin-top: 20px; }</style>
</head>
<body><div class="welcome"><h2>歡迎, ${username}!</h2></div><div class="info"><p><strong>用戶名:</strong> ${username}</p><p><strong>注冊郵箱:</strong> ${email}</p></div><div class="logout"><a href="user?action=logout">注銷登錄</a></div>
</body>
</html>

?數據庫

CREATE DATABASE userdb;
USE userdb;CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL UNIQUE,password VARCHAR(100) NOT NULL,email VARCHAR(100) NOT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

項目結構?

project-root/
├── src/
│ ? └── main/
│ ? ? ? ├── java/
│ ? ? ? │ ? └── com/
│ ? ? ? │ ? ? ? └── example/
│ ? ? ? │ ? ? ? ? ? └── web/
│ ? ? ? │ ? ? ? ? ? ? ? └── UserServlet.java
│ ? ? ? └── webapp/
│ ? ? ? ? ? ├── WEB-INF/
│ ? ? ? ? ? │ ? └── web.xml
│ ? ? ? ? ? ├── login.jsp
│ ? ? ? ? ? ├── register.jsp
│ ? ? ? ? ? ├── profile.jsp
│ ? ? ? ? ? └── index.html
└── pom.xml


學習時間? 2025.05.01

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/917537.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/917537.shtml
英文地址,請注明出處:http://en.pswp.cn/news/917537.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【maven】倉庫配置

目錄 一、本地倉庫 二、私有倉庫 三、阿里云倉庫 一、本地倉庫 針對無外網、無maven私服&#xff0c;只有本地倉庫&#xff0c;進行maven項目開發。在maven的settings.xml中設置三項&#xff1a; 1、本地倉庫地址 默認在當前系統用戶下創建目錄&#xff1a;.m2/repository…

信息系統架構設計的系統性解析

一、信息系統架構設計??概念定義??&#xff1a;信息系統架構&#xff08;ISA&#xff09;是對系統組件、交互關系及環境約束的結構化抽象&#xff0c;確保業務目標與技術實現對齊。核心要素包括業務邏輯層、數據層、應用層和基礎設施層。??設計方法??&#xff1a;??T…

編譯舊版本的electron內核

我們的軟件產品使用的electron框架&#xff0c;electron框架是不斷更新的&#xff0c;但是我們的軟件太過龐大復雜&#xff0c;不敢輕易升級electron框架。Electron舊版本存在一些BUG和不合理的地方&#xff0c;需要去修復BUG或者不合理的地方。修復完BUG后&#xff0c;要對ele…

Elastic 9.1/8.19:默認啟用 BBQ,ES|QL 支持跨集群搜索(CCS)正式版,JOINS 正式版,集成 Azure AI Foundry

作者&#xff1a;來自 Elastic Mark Doncov 今天&#xff0c;我們很高興宣布 Elastic 9.1 和 8.19 正式發布&#xff01; 是的&#xff0c;又有好消息 —— 我們將 8.x 系列最終延長到 8.19&#xff0c;這樣那些還在等待升級到 9.x 的用戶也能享受到許多新功能。 Elastic 9.1…

Redis面試精講 Day 8:Stream消息隊列設計與實現

【Redis面試精講 Day 8】Stream消息隊列設計與實現 文章標簽 Redis,消息隊列,Stream,面試技巧,分布式系統,后端開發 文章簡述 本文是"Redis面試精講"系列第8天&#xff0c;聚焦Redis 5.0引入的Stream消息隊列。文章深入解析Stream的核心概念與實現原理&#xff0…

【01】大恒相機SDK C++開發 —— 初始化相機,采集第一幀圖像、回調采集、關閉相機

文章目錄1 初始化相機&#xff0c;采集第一幀圖像2 回調方式采集圖像3 視頻教程1 初始化相機&#xff0c;采集第一幀圖像 #include <iostream> #include <GalaxyIncludes.h> using namespace std;int main() {//首先&#xff0c;對相機資源進行初始化IGXFactory::…

Windows下定位Mingw編譯的Qt程序崩潰堆棧

一、dump和pdb是什么 在Windows系統下&#xff0c;當我們寫的程序跑在客戶的機器上&#xff0c;因為一個bug&#xff0c;導致程序崩潰&#xff0c;我們該如何定位并修復這個bug呢&#xff1f; 有人會說記錄日志&#xff0c;即便有日志&#xff0c;也是不好定位的&#xff0c;因…

.net依賴注入框架 Autofac和MEF的對比

Autofac 默認需要顯式注冊每個類型&#xff0c;這是它與MEF在模塊化設計上的主要區別。以下是具體對比說明&#xff1a;1. Autofac 的基本注冊方式 Autofac 必須通過代碼明確注冊每個需要注入的類型&#xff08;除非使用特殊掃描機制&#xff09;&#xff1a; var builder new…

Python 使用 asyncio 包處理并 發(使用asyncio包編寫服務器)

使用asyncio包編寫服務器 演示 TCP 服務器時通常使用回顯服務器。我們要構建更好玩一點的示 例服務器&#xff0c;用于查找 Unicode 字符&#xff0c;分別使用簡單的 TCP 協議和 HTTP 協議實現。這兩個服務器的作用是&#xff0c;讓客戶端使用 4.8 節討論過的 unicodedata 模塊…

Node.js (Express) + MySQL + Redis構建項目流程

以下是使用 Node.js (Express) MySQL Redis 構建完整項目的詳細流程&#xff0c;涵蓋環境搭建、架構設計、核心代碼實現和部署優化&#xff1a;一、項目初始化 1. 創建項目目錄 mkdir my-project cd my-project npm init -y2. 安裝基礎依賴 npm install express mysql2 redis…

Python3 中使用zipfile進行文件(夾)的壓縮、解壓縮

一、文件壓縮與解壓縮模塊 zipfile簡介 zipfile 是 Python 標準庫中用于處理 ZIP 壓縮文件的模塊&#xff0c;提供了創建、讀取、寫入、解壓 ZIP 文件的完整功能。它支持多種壓縮算法&#xff0c;無需安裝額外依賴&#xff0c;是處理 ZIP 格式的首選工具。 核心功能與常用類 zi…

在Java客戶端使用Redis

目錄 第一步&#xff1a;開放Redis外部連接配置 第二步&#xff1a;配置端口轉發 第三步&#xff1a;在IDEA中導入依賴 第四步&#xff1a;編寫代碼命令 連接環境&#xff1a;Java客戶端為本地IDEA&#xff0c;Redis服務器安裝在云服務器Ubuntu系統中。 第一步&#xff1a;開…

【MySQL】MySQL索引—B樹/B+樹

目錄 1. 數據庫索引 1.1 索引的概念 1.2 索引的特點 1.3 索引查詢對比普通的查詢 1.4 索引的操作 1.5 索引的原理 1.6 B樹 1.7 B樹 1.8 B樹的優點 1. 數據庫索引 1.1 索引的概念 數據庫的索引是一種特殊的數據結構&#xff0c;里面包含著數據表中所有記錄的引用&…

jQuery Mobile 面板詳解

jQuery Mobile 面板詳解 引言 隨著移動設備的普及,移動網頁開發變得越來越重要。jQuery Mobile 是一個基于 jQuery 的移動網頁開發框架,它提供了一套豐富的 UI 組件和主題,使得開發者可以快速構建出美觀、響應式的移動網頁。在 jQuery Mobile 中,面板(Panel)是一個非常…

Python中的import和from...import有什么區別?

文章目錄 前言 一、import導入模塊 導入模塊并給它一個別名 語法格式 二、from...import導入特定項 1.導入模塊中的特定項 2.導入模塊中的所有項 2.1 命名空間核污染 2.2 性能影響 總結 前言 在Python編程中,模塊和包的導入機制是編寫可維護、可擴展代碼的核心。深入理解Pyth…

vscode提示“無法使用 compilerPath 解析配置”解決辦法

0 問題描述 使用vscode的Remote-SSH插件連接安裝在虛擬機上的Windows10進行遠程開發時&#xff0c;出現如下提示&#xff1a;無法使用 compilerPath 解析配置:“D:\mingw64\bin\gcc.exe” 所有包含C庫頭文件的文件都被標紅提示錯誤&#xff1a;1 問題原因 vscode沒有設置正確的…

信噪比(Signal-to-Noise Ratio, SNR)詳細介紹

信噪比&#xff08;Signal-to-Noise Ratio, SNR&#xff09;信噪比&#xff08;Signal-to-Noise Ratio&#xff0c;SNR&#xff09;是衡量信號質量的重要參數&#xff0c;表示有用信號的功率與背景噪聲功率的比值。SNR在通信、音頻處理、視頻處理以及其他電子信號處理領域中具有…

Nginx 相關實驗(1)

nginx源碼編譯 本實驗采用nginx源碼編譯的安裝方式&#xff0c;需要準備一個tar包&#xff0c;可從nginx官網上下載。 下載地址&#xff1a;nginx: downloadhttps://nginx.org/en/download.html 將下載好的壓縮包傳到虛擬機中的自定義目錄下 [rootwebserver ~]# ls anacond…

【選型】HK32L088 與 STM32F0/L0 系列 MCU 參數對比與選型建議(ST 原廠 vs 國產芯片)(單片機選型主要考慮的參數與因素)

國產 vs ST 單片機在工業控制中的性能對比分析 HK32L088 與 STM32F0/L0 系列 MCU 參數對比與選型建議 工業控制領域 MCU 選型:國產航順 HK32 與 ST 原廠芯片深入比較 國產 MCU 是否可替代 ST?基于發電機控制應用的深入評估 從數據手冊看 MCU 制造工藝差異:HK32L088 vs S…

LLM Prompt與開源模型資源(1)提示詞工程介紹

學習材料&#xff1a;https://www.hiascend.com/developer/courses/detail/1935520434893606913學習時長&#xff1a; 預計 30 分鐘學習目的&#xff1a; 了解提示工程的定義與作用 熟悉提示工程的關鍵技術相關概念 掌握基于昇騰適配的大模型提示工程的入門及進階指南 提示…