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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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; 了解提示工程的定义与作用 熟悉提示工程的关键技术相关概念 掌握基于昇腾适配的大模型提示工程的入门及进阶指南 提示…