Servlet小结
视频链接:黑马servlet视频全套视频教程,快速入门servlet原理+servlet实战
什么是Servlet?
菜鸟教程:Java Servlet
servlet: server applet
Servlet是一个运行在Web服务器(如Tomcat、Jetty)或应用服务器(如WebLogic、WildFly)中的Java类,用于扩展服务器功能,通过请求-响应模型与客户端交互(如浏览器)。
- 它实现了javax.servlet.Servlet接口或继承HttpServlet类,处理HTTP请求(GET、POST等)并生成动态响应(HTML、JSON、图片等)。
- 与JSP(JavaServer Pages)结合使用时,Servlet负责业务逻辑处理,JSP负责页面渲染。
Servlet其实就是一个接口,它定义了Java类被浏览器访问到(tomcat识别到)的规则,只要实现了这个接口的Java类就是一个Servlet
快速入门
1.创建项目
2.编写Servlet类
2.1 实现Servlet接口
public class ServletDemo1 implements Servlet
2.2 继承HttpServlet类
public class ServletDemo2 extends HttpServlet
其实这个底层也是实现Servlet接口
3.实现Servlet或重写HttpServlet里面的方法
servlet里面最重要的方法:service方法
HttpServlet里面最重要的方法: doGet doPost
public interface Servlet {// 初始化void init(ServletConfig var1) throws ServletException;// 获得配置ServletConfig getServletConfig();// 提供服务void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;// 获得信息String getServletInfo();// 销毁前执行void destroy();
}
4.配置Servlet
4.1 基于web.xml配置
<servlet><servlet-name>servlet的名字</servlet-name><servlet-class>servlet的全类名</servlet-class>
</servlet>
<servlet-mapping><servlet-name>servlet的名字</servlet-name><url-pattern>servlet的请求路径</url-pattern>
</servlet-mapping>
eg:
<?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"><!-- 配置ServletDemo1 --><servlet><servlet-name>servlet1</servlet-name><servlet-class>com.itcast.servlet.ServletDemo1</servlet-class></servlet><servlet-mapping><servlet-name>servlet1</servlet-name><url-pattern>/servlet1</url-pattern></servlet-mapping><!-- 配置ServletDemo2 --><servlet><servlet-name>servlet2</servlet-name><servlet-class>com.itcast.servlet.ServletDemo2</servlet-class></servlet><servlet-mapping><servlet-name>servlet2</servlet-name><url-pattern>/servlet2</url-pattern></servlet-mapping></web-app>
4.2 基于@WebServlet注解配置
@WebServlet("/servlet1")
public class Servlet1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("servlet1 doGet");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("servlet1 doPost");}
}
@WebServlet
注解会自动把当前类注册为Servlet并且请求路径为/servlet1
相当于
<!-- 配置ServletDemo1 -->
<servlet><servlet-name>servlet1</servlet-name><servlet-class>com.itcast.servlet.ServletDemo1</servlet-class>
</servlet>
<servlet-mapping><servlet-name>servlet1</servlet-name><url-pattern>/servlet1</url-pattern>
</servlet-mapping>
执行流程
1.客户端请求
浏览器输入URL http://localhost:8080/servlet1,发送HTTP请求。
2.Tomcat接收请求
Connector组件(如 Coyote)监听端口 8080,接收请求。
解析请求:提取URL路径 /servlet1,并封装为HttpServletRequest对象。
3.URL到Servlet的映射
Tomcat在启动时已加载所有Servlet配置(包括web.xml和@WebServlet注解),建立URL到Servlet类的映射表。
匹配路径:Tomcat检查请求的URL /servlet1
是否与已注册的Servlet路径匹配。
如果匹配,找到对应的Servlet类(如 ServletDemo1)。
4.Servlet类加载与实例化(单次行为)
4.1 类加载:
Tomcat使用Web应用类加载器加载Servlet类的字节码(如 ServletDemo1.class)。
类路径通常为 WEB-INF/classes 或 WEB-INF/lib 中的JAR包。
4.2 实例化:
Tomcat通过反射机制创建Servlet类的实例(ServletDemo1 instance = new ServletDemo1())。
4.3 初始化:
调用Servlet的init()方法,完成初始化(如加载配置、数据库连接等)。
5.处理请求
调用service()方法:
Tomcat根据请求方法(如GET/POST),调用Servlet的service()方法。
service()方法会进一步分发到doGet()或doPost()等具体方法。
6.响应客户端
构建响应:Servlet通过HttpServletResponse对象生成响应内容(如HTML、JSON等)。
返回结果:Tomcat通过Connector将响应结果返回给浏览器。
Http协议
特点
- 无状态(Stateless)
定义:协议本身不保存请求与响应之间的通信状态,每次请求都是独立的。
意义:简化了服务器的实现,提高了可扩展性,但需要客户端在每次请求中携带必要的状态信息(如通过Cookie、Session等)。- 无连接(Connectionless)
定义:客户端与服务器在每次请求完成后断开连接(HTTP/1.0默认),但HTTP/1.1引入了持久连接(Keep-Alive)。
早期版本:HTTP/0.9和HTTP/1.0每次请求均建立新连接,效率低;HTTP/1.1通过持久连接复用TCP连接,减少开销。- 面向对象(Object-Oriented)
定义:通过统一资源标识符(URI)定位互联网上的资源(如HTML、图片、视频等),支持对资源的增删改查操作。
方法:GET(获取资源)、POST(提交数据)、PUT(更新资源)、DELETE(删除资源)等。- 短连接(Short-lived)
早期行为:HTTP/0.9和1.0采用短连接,请求完成后立即断开,导致频繁的TCP握手开销。
改进:HTTP/1.1引入持久连接(Keep-Alive),允许复用TCP连接,提升性能。- 可缓存(Cachable)
机制:通过Cache-Control、ETag、Last-Modified等头部字段,客户端或代理服务器可缓存响应内容,减少重复请求。
优势:降低服务器负载,加快响应速度。- 灵活扩展
头部信息:通过请求头和响应头(如Content-Type、User-Agent)传递元数据,支持功能扩展。
方法扩展:HTTP/1.1新增PUT、DELETE等方法,HTTP/2支持服务器推送(Server Push)。
请求消息
POST /login HTTP/1.1
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 27
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID=ED583FB162E9D2E951D951B649C4DEBA
Host: localhost:8080
Origin: http://localhost:8080
Referer: http://localhost:8080/
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36
sec-ch-ua: "Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"username=admin&password=123
1.请求行
POST /login HTTP/1.1
- 方法(Method):POST(向服务器提交数据,通常用于表单提交)。
- 路径(URI):
/login
(请求的目标资源路径)。 - 协议版本(Protocol):HTTP/1.1(使用的HTTP协议版本)。
2.请求头
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 27
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID=ED583FB162E9D2E951D951B649C4DEBA
Host: localhost:8080
Origin: http://localhost:8080
Referer: http://localhost:8080/
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36
sec-ch-ua: "Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
1.User-Agent: 浏览器的版本信息
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36
2.Refer: 告诉服务器,请求来源页面
Referer: http://localhost:8080/
3.Cookie:客户端携带的Cookie
Cookie: JSESSIONID=ED583FB162E9D2E951D951B649C4DEBA
4.Origin:请求的来源域
Origin: http://localhost:8080
5.Accept:浏览器可接受的响应内容
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
3.请求空行
请求头结束后必须有一个空行(即两个换行符 \r\n\r\n),表示请求头结束,请求体开始。
4.请求体
username=admin&password=123
ServletRequest 接口
public interface ServletRequest {// 获取请求中指定名称的属性值。Object getAttribute(String var1);// 返回请求中所有属性名称的枚举Enumeration<String> getAttributeNames();// 获取请求的字符编码String getCharacterEncoding();// 设置请求的字符编码(需确保编码有效,否则抛出异常)。void setCharacterEncoding(String var1) throws UnsupportedEncodingException;// 获取请求体的长度(字节),若未知返回 -1int getContentLength();// 以 long 类型返回请求体长度,避免 int 溢出long getContentLengthLong();// 获取请求体的 MIME 类型String getContentType();// 获取请求体的二进制输入流(用于读取二进制数据)。ServletInputStream getInputStream() throws IOException;// 获取指定名称的请求参数的第一个值(若参数有多个值)String getParameter(String var1);// 返回所有请求参数名称的枚举Enumeration<String> getParameterNames();// 获取指定名称的请求参数的所有值(如多选框)String[] getParameterValues(String var1);//返回所有请求参数的映射(键为参数名,值为参数值数组)Map<String, String[]> getParameterMap();// 获取请求使用的协议及版本(如 HTTP/1.1)String getProtocol();// 获取请求的协议名称(如 http、https)String getScheme();// 获取服务器的主机名(如 localhost)String getServerName();// 获取服务器的端口号(如 8080)int getServerPort();// 获取请求体的字符流(用于文本数据,如表单提交)。BufferedReader getReader() throws IOException;// 获取客户端的IP地址。String getRemoteAddr();// 获取客户端的端口号(如浏览器使用的临时端口)。String getRemoteHost();// 设置请求属性,名称为 name,值为 value。void setAttribute(String var1, Object var2);// 移除指定名称的请求属性。void removeAttribute(String var1);// 获取客户端支持的所有语言环境。Locale getLocale();// 获取客户端支持的所有语言环境。Enumeration<Locale> getLocales();// 判断请求是否通过安全通道(HTTPS)传输。boolean isSecure();// 获取用于请求转发或包含的 RequestDispatcher 对象。RequestDispatcher getRequestDispatcher(String var1);}
ServletResponse 接口
public interface ServletResponse {// 获取响应的字符编码(如 UTF-8)String getCharacterEncoding();// 获取响应的 MIME 类型(如 text/html)String getContentType();// 获取二进制输出流(用于发送二进制数据,如图片)ServletOutputStream getOutputStream() throws IOException;// 获取字符输出流(用于发送文本数据,如 HTML)PrintWriter getWriter() throws IOException;// 设置响应的字符编码(如 UTF-8)void setCharacterEncoding(String var1);// 设置响应体的长度(字节,使用 int 类型)void setContentLength(int var1);// 设置响应体的长度(字节,使用 long 类型,避免溢出)void setContentLengthLong(long var1);// 设置响应的 MIME 类型(如 text/html)void setContentType(String var1);// 设置响应缓冲区的大小(单位:字节)void setBufferSize(int var1);// 获取当前缓冲区的大小(单位:字节)int getBufferSize();// 强制刷新缓冲区,将数据立即发送到客户端void flushBuffer() throws IOException;// 重置缓冲区内容,但保留已提交的响应状态void resetBuffer();// 判断响应是否已提交(即已发送到客户端)boolean isCommitted();// 重置响应,清除缓冲区内容和状态(仅在未提交时有效)void reset();// 设置响应的区域设置(如 Locale.CHINA)void setLocale(Locale var1);// 获取当前响应的区域设置Locale getLocale();
}
HttpRequest 的核心方法
1. 请求参数获取
-
getParameter(String name)
获取指定名称的请求参数的第一个值(如表单提交或 URL 参数)。
示例:String username = request.getParameter("username");
-
getParameterValues(String name)
获取指定名称的请求参数的所有值(如多选框的多个值)。
示例:String[] hobbies = request.getParameterValues("hobby");
-
getParameterMap()
返回所有请求参数的Map
(键为参数名,值为参数值数组)。
示例:Map<String, String[]> paramMap = request.getParameterMap();
2. 请求头与元数据
-
getMethod()
获取请求方法(如GET
、POST
)。
示例:String method = request.getMethod();
-
getHeader(String name)
获取指定名称的请求头值(如User-Agent
、Content-Type
)。
示例:String userAgent = request.getHeader("User-Agent");
-
getHeaders(String name)
获取指定名称的所有请求头值(若存在多个值)。
示例:Enumeration<String> acceptTypes = request.getHeaders("Accept");
3. 请求路径与来源
-
getRequestURI()
获取请求的资源路径(不包含主机名和端口)。
示例:/api/user
(返回路径部分)。 -
getRequestURL()
获取完整的请求 URL(包含协议、主机和端口)。
示例:http://localhost:8080/api/user
。 -
getRemoteAddr()
获取客户端的 IP 地址。
示例:String clientIP = request.getRemoteAddr();
4. 会话与 Cookie
-
getSession()
获取与当前请求关联的HttpSession
对象(若不存在则新建)。
示例:HttpSession session = request.getSession();
-
getCookies()
获取客户端发送的 Cookie 集合。
示例:Cookie[] cookies = request.getCookies();
5. 其他重要方法
-
getInputStream()
获取请求体的二进制输入流(用于文件上传或二进制数据)。
示例:ServletInputStream inputStream = request.getInputStream();
-
getPart(String name)
获取上传的文件或表单字段(用于处理多部分表单数据)。
示例:Part filePart = request.getPart("file");
HttpResponse 的核心方法
1. 响应头与状态码设置
-
setStatus(int sc)
或sendError(int sc)
设置 HTTP 状态码(如200
成功、404
未找到、500
服务器错误)。
示例:response.setStatus(HttpServletResponse.SC_OK);
-
setHeader(String name, String value)
设置指定名称的响应头(如Content-Type
、Cache-Control
)。
示例:response.setHeader("Content-Type", "application/json");
2. 响应内容输出
-
getOutputStream()
获取二进制输出流(用于发送文件或二进制数据)。
示例:ServletOutputStream os = response.getOutputStream();
-
getWriter()
获取字符输出流(用于发送文本内容,如 JSON、HTML)。
示例:PrintWriter writer = response.getWriter();
3. 重定向与会话管理
-
sendRedirect(String location)
发送重定向响应(客户端会发起新请求到指定 URL)。
示例:response.sendRedirect("/login.html");
-
addCookie(Cookie cookie)
添加一个 Cookie 到响应中(用于客户端存储数据)。
示例:Cookie sessionCookie = new Cookie("session", "123456"); response.addCookie(sessionCookie);
4. 缓冲区与提交控制
-
flushBuffer()
强制刷新缓冲区,立即发送响应内容到客户端。
示例:response.flushBuffer();
-
reset()
重置响应(清除缓冲区和状态,需在响应提交前调用)。
示例:response.reset();
5. 其他重要方法
-
setContentType(String type)
设置响应的 MIME 类型(如text/html
、application/json
)。
示例:response.setContentType("application/json");
-
setCharacterEncoding(String charset)
设置响应的字符编码(如UTF-8
)。
示例:response.setCharacterEncoding("UTF-8");
关键注意事项
-
getInputStream()
和getWriter()
的冲突- 在
HttpServletRequest
中,二者不能同时使用,否则抛出IllegalStateException
。
- 在
-
响应提交后的限制
- 一旦响应提交(通过
flushBuffer()
或客户端接收),无法修改响应头或状态码。
- 一旦响应提交(通过
-
字符编码设置时机
- 应在调用
getWriter()
或getOutputStream()
之前设置字符编码。
- 应在调用
-
会话与 Cookie 的安全性
- 敏感数据(如密码)应避免通过 Cookie 传输,需使用
HttpOnly
和Secure
标志。
- 敏感数据(如密码)应避免通过 Cookie 传输,需使用
登录案例
项目结构:
index.jsp:
<%--Created by IntelliJ IDEA.User: xuanDate: 2025/4/24Time: 20:05To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<form action="/login" method="post">用户名:<input type="text" name="username"><br>密码:<input type="password" name="password"><br><input type="submit" value="登录"/>
</form>
</body>
</html>
pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.itcast</groupId><artifactId>login-test</artifactId><version>1.0-SNAPSHOT</version><name>login-test</name><packaging>war</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.target>1.8</maven.compiler.target><maven.compiler.source>1.8</maven.compiler.source><junit.version>5.9.2</junit.version></properties><dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>${junit.version}</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>${junit.version}</version><scope>test</scope></dependency><!-- Druid 连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.6</version></dependency><!-- MySQL 8.0 驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.20</version></dependency><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>1.9.4</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>3.3.2</version></plugin></plugins></build>
</project>
1.创建数据库,创建user表
create database servlet;create table user
(id int auto_incrementprimary key,username varchar(50) not null comment '用户名',password varchar(12) not null
);
2.编写数据库配置文件
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/servlet
username=root
password=root
initialSize=5
maxActive=20
maxWait=60000
3.编写数据库工具类
package com.itcast.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;public class JDBCUtils {private static DataSource dataSource;static {try {Properties properties = new Properties();InputStream resource = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");properties.load(resource);dataSource = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();System.err.println("数据库加载出错");}}public static DataSource getDataSource(){return dataSource;}public Connection getConnection() throws Exception{return dataSource.getConnection();}
}
4.编写User实体类,封装用户数据
package com.itcast.dao;public class User {private String username;private String password;public User() {}public User(String username, String password) {this.username = username;this.password = password;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}
5.编写LoginDao.class
package com.itcast.domain;import com.itcast.dao.User;
import com.itcast.utils.JDBCUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;public class UserDao {private JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());/*** 登录* @param loginUser* @return*/public User login(User loginUser) {try {String sql = "select * from user where username = ? and password = ?";User user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class),loginUser.getUsername(), loginUser.getPassword());return user;} catch (DataAccessException e) {System.out.println("用户"+loginUser.getUsername()+"登录失败");return null;}}
}
6.编写servlet
LoginServlet.class:
package com.itcast.servlet;import com.itcast.dao.User;
import com.itcast.domain.UserDao;
import org.apache.commons.beanutils.BeanUtils;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.lang.reflect.InvocationTargetException;
import java.util.Map;@WebServlet("/login")
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");Map<String, String[]> map = req.getParameterMap();User userDTO = new User();try {BeanUtils.populate(userDTO, map);} catch (Exception e) {e.printStackTrace();System.out.println("复制失败");}UserDao userDao = new UserDao();User user = userDao.login(userDTO);if (user == null) {// 登录失败req.setAttribute("msg", "用户名或密码错误");req.getRequestDispatcher("/fail").forward(req, resp);}else {req.getRequestDispatcher("/success").forward(req, resp);}}
}
FailServlet.class:
package com.itcast.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;@WebServlet("/fail")
public class FailServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");resp.getWriter().write("登录失败");}
}
SuccessServlet.class:
package com.itcast.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;@WebServlet("/success")
public class SuccessServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");String username = req.getParameter("username");resp.getWriter().write(username + "登录成功");}
}
— Xuan
相关文章:
Servlet小结
视频链接:黑马servlet视频全套视频教程,快速入门servlet原理servlet实战 什么是Servlet? 菜鸟教程:Java Servlet servlet: server applet Servlet是一个运行在Web服务器(如Tomcat、Jetty)或应用…...
C语言面试高频题——define 和typedef 的区别?
1. 基本概念 (1) #define 定义:#define 是预处理指令,用于定义宏。作用:在编译之前进行文本替换。语法:#define 宏名 替换内容示例:#define PI 3.14159 #define SQUARE(x) ((x) * (x))(2) typedef 定义:…...
计算机组成原理:指令系统
计算机组成原理:指令集系统 指令集体系结构(ISA)ISA定义ISA包含的内容举个栗子指令的基本组成(操作码+地址码)指令分类:地址码的个数定长操作码变长操作码变长操作码的原则变长操作码的设计指令寻址寻址方式的目的寻址方式分类有效地址直接在指令中给出有效地址间接给出有效地…...
自动清空 maven 项目临时文件,vue 的 node_modules 文件
echo off setlocal enabledelayedexpansion :: vue 的 node_modules 太大 :: maven 打包后的 target 文件也很大, :: 有些项目日志文件也很大,导致磁盘空间不足了, :: 所以写了个脚本,只要配置一下各项目目录, :: 双击…...
服务网格助力云原生后端系统升级:原理、实践与案例剖析
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:微服务的“通信焦虑”与服务网格的出现 云原生架构的兴起推动了微服务的大规模落地,系统拆分为成百上千个小服务,这些服务之间需要频繁通信。然而,通信带来的问题也开始显现: 如何确保服务间…...
基于DrissionPage的表情包爬虫实现与解析(含源码)
目录 编辑 一、环境配置与技术选型 1.1 环境要求 1.2 DrissionPage优势 二、爬虫实现代码 三、代码解析 3.1 类结构设计 3.2 目录创建方法 3.3 图片链接获取 3.4 图片下载方法 四、技术升级对比 4.1 代码复杂度对比 4.2 性能测试数据 五、扩展优化建议 5.1 并…...
Spring Cloud Gateway 如何将请求分发到各个服务
前言 在微服务架构中,API 网关(API Gateway)扮演着非常重要的角色。它负责接收客户端请求,并根据预定义的规则将请求路由到对应的后端服务。Spring Cloud Gateway 是 Spring 官方推出的一款高性能网关,支持动态路由、…...
【深度强化学习 DRL 快速实践】Value-based 方法总结
强化学习中的 Value-based 方法总结 在强化学习(Reinforcement Learning, RL)中,Value-based 方法主要是学习一个价值函数(Value Function),然后基于价值函数来决策。常见的 Value-based 方法包括…...
【计算机视觉】CV实战项目 - 基于YOLOv5的人脸检测与关键点定位系统深度解析
基于YOLOv5的人脸检测与关键点定位系统深度解析 1. 技术背景与项目意义传统方案的局限性YOLOv5多任务方案的优势 2. 核心算法原理网络架构改进关键点回归分支损失函数设计 3. 实战指南:从环境搭建到模型应用环境配置数据准备数据格式要求数据目录结构 模型训练配置文…...
git版本回退 | 远程仓库的回退 (附实战Demo)
目录 前言1. 基本知识2. Demo3. 彩蛋 前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 爬虫神器,无代码爬取,就来:bright.cn 本身暂存区有多个文件,但手快了&…...
【KWDB 创作者计划】_深度学习篇---数据获取
文章目录 前言一、公开数据集资源库1. 综合型数据集平台Kaggle Datasets (https://www.kaggle.com/datasets)Google Dataset Search (https://datasetsearch.research.google.com)UCI Machine Learning Repository (https://archive.ics.uci.edu/ml) 2. 计算机视觉专用ImageNet…...
DeepSeek本地部署手册
版本:v1.0 适用对象:零基础开发者 一、部署前准备 1.1 硬件要求 组件最低配置推荐配置说明CPUIntel i5 8代Xeon Gold 6230需支持AVX指令集内存16GB64GB模型越大需求越高GPUNVIDIA GTX 1060 (6GB)RTX 3090 (24GB)需CUDA 11.7+存储50GB可用空间1TB NVMe SSD建议预留2倍模型大小…...
OpenCV中的SIFT特征提取
文章目录 引言一、SIFT算法概述二、OpenCV中的SIFT实现2.1 基本使用2.1.1 导入库2.1.2 图片预处理2.1.3 创建SIFT检测器2.1.4 检测关键点并计算描述符2.1.5 检测关键点并计算描述符并对关键点可视化2.1.6 印关键点和描述符的形状信息 2.2 参数调优 三、SIFT的优缺点分析3.1 优点…...
Kubernetes in action-初相识
初相识Kubernetes 1、构建、运行以及共享镜像1.1 运行镜像1.2 构建镜像1.3 推送镜像 2、Kubernetes初相识2.1 介绍Pod2.2 从构建到运行整体流程2.3 kubectl命令行工具 如有侵权,请联系~ 如有错误,也欢迎批评指正~ 本篇文章大部分是…...
九、小白如何用Pygame制作一款跑酷类游戏(添加前进小动物作为动态障碍物)
九、小白如何用Pygame制作一款跑酷类游戏(添加前进小动物作为动态障碍物) 文章目录 九、小白如何用Pygame制作一款跑酷类游戏(添加前进小动物作为动态障碍物)前言一、添加小动物素材1. 在根目录的图片文件夹下新建两个目录分别存放…...
Unity3D IK解算器技术分析
前言 在Unity3D中,逆向运动学(IK Solver)是实现角色动画自然交互的核心技术之一。以下是Unity中常见的IK解算器及其特点的综合分析,结合了原生功能、第三方插件与开源方案的对比: 对惹,这里有一个游戏开发…...
7.11 Python CLI开发实战:API集成与异步处理核心技术解析
Python CLI开发实战:API集成与异步处理核心技术解析 #mermaid-svg-fXGFud0phX2N2iZj {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-fXGFud0phX2N2iZj .error-icon{fill:#552222;}#mermaid-svg-fXGFud0phX2N2iZj .…...
百度Create2025 AI开发者大会:模型与应用的未来已来
今日,2025百度AI开发者大会(Create2025)在武汉体育中心盛大开幕。这场以“模型的世界,应用的天下”为主题的盛会,不仅汇聚了李彦宏、王海峰、沈抖等百度高层及行业领袖,更以多项重磅技术发布、前沿议题探讨…...
Java实现HTML转PDF(deepSeekAi->html->pdf)
Java实现HTML转PDF,主要为了解决将ai返回的html文本数据转为PDF文件方便用户下载查看。 一、deepSeek-AI提问词 基于以上个人数据。总结个人身体信息,分析个人身体指标信息。再按一个月为维度,详细列举一个月内训练计划,维度详细至每周每天…...
区间和数量统计 之 前缀和+哈希表
文章目录 1512.好数对的数目2845.统计趣味子数组的数目1371.每个元音包含偶数次的最长子字符串 区间和的数量统计是一类十分典型的问题:记录左边,枚举右边策略前置题目:统计nums[j]nums[i]的对数进阶版本:统计子数组和%modulo k的…...
【服务器操作指南】从 Hugging Face 上下载文件 | 从某一个网址上下载文件到 Linux 服务器的指定目录
引言 在服务器操作中,下载和管理文件是常见且重要的任务。从 Hugging Face 平台获取模型资源,或从特定网址下载文件至 Linux 服务器并进行解压,都需要明确的操作步骤。本指南旨在为您提供清晰的操作流程,帮助您快速上手相关任务并…...
PyCharm 中 FREECAD 二次开发:从基础建模到深度定制
一、引言 在当今的三维建模与设计领域,FREECAD 以其开源、参数化设计的强大特性,成为众多工程师、设计师和开发者的首选工具。然而,面对日益复杂和多样化的设计需求,仅仅依靠 FREECAD 的原生功能往往难以满足。此时,二…...
C++入侵检测与网络攻防之网络嗅探以及ARP攻击
目录 1.tcpdump基本使用 2.tcpdump条件过滤 3.wireshark介绍 4.wireshark的介绍 5.tcp握手挥手分析 6.telnet服务的介绍和部署 7.复习 8.telnet服务的报文嗅探 9.网络嗅探基础 10.arp协议的解析 11.arp攻击原理以及试验环境 12.arp实验以及防御方式 1.tcpdump基本使…...
Integer[]::new方法引用
Integer[]::new 这种写法是 Java 中方法引用的一种具体应用,它遵循 Java 方法引用的语法规则。 方法引用概述 方法引用是 Java 8 引入的一种简化 Lambda 表达式的语法糖,它允许你通过方法的名称直接引用已有的方法或构造函数。方法引用可以使代码更加简…...
Pycharm(三):梯度下降法
梯度下降算法(Gradient Descent Algorithm)是深度学习中常用的更新权重的方法,它采用的贪心法的思想,每次都往函数值下降最快的方向去更新,梯度方向是增长最快的方向,负梯度方向是下降最快的方向。 一、梯…...
系统测试的技术要求
文章目录 一、系统测试的概念二、测试对象三、测试目的四、进入条件五、内容要求1、基于需求的考核要求2、基于任务的考核要求 六、测试环境 一、系统测试的概念 系统测试(System Testing),主要是对多个软件组成的系统进行的整体测试。系统测…...
升级Ubuntu 20.04 LTS到22.04 LTS
按照 Ubuntu发布周期 每2年会发布一个 "长期支持版" (LTS, Long Term Support)。具体来说,就是每2年的4月份会发布一个支持周期长达5年的稳定版本,如: 20.04 和 22.04 分别代表 2020年4月 和 2022年4月 发布的长期支持版本. 当前(2022年9月)&a…...
【神经网络与深度学习】训练集与验证集的功能解析与差异探究
引言 在深度学习模型的训练过程中,训练集和验证集是两个关键组成部分,它们在模型性能的提升和评估中扮演着不可替代的角色。通过分析这两者的区别和作用,可以帮助我们深入理解模型的学习过程和泛化能力,同时为防止过拟合及优化超…...
单精度浮点运算/定点运算下 MATLAB (VS) VIVADO
VIVADO中单精度浮点数IP核计算结果与MATLAB单精度浮点数计算结果的对比 MATLAB定点运算仿真,对比VIVADO计算的结果 目录 前言 一、VIVADO与MATLAB单精度浮点数运算结果对比 二、MATLAB定点运算仿真 总结 前言 本文介绍了怎么在MATLAB中使用单精度浮点数进行运算…...
如何让 HTML 文件嵌入另一个 HTML 文件:详解与实践
目录 一、为什么需要在HTML中嵌入其他HTML文件? 二、常用的方法概览 三、利用 1. 基本原理 2. 使用场景 3. 优缺点 4. 实践示例 5. 适用建议 四、利用JavaScript动态加载内容 1. 原理简介 2. 实现步骤 示例代码 3. 优缺点分析 4. 应用场景 5. 实践建…...
7.10 GitHub Sentinel CLI开发实战:Python构建企业级监控工具的5大核心技巧
GitHub Sentinel CLI开发实战:Python构建企业级监控工具的5大核心技巧 GitHub Sentinel Agent 用户界面设计与实现:命令行工具开发实战 关键词:命令行工具开发、Python argparse、API 集成、错误处理、测试覆盖率 设计并实现基本的命令行工具 命令行界面(CLI)是企业级工…...
将AAB转APK的两种好用方法AAB to APK Converter
文章目录 第一种方法:Unity工具转换第二种方法:Python转换参数填写 第一种方法:Unity工具转换 适用人群: 策划,程序等装Unity的人 需要安装: Unity 下载AAB-to-APK-Converter 导入unity,点…...
netcore8.0项目部署到windows服务器中(或个人windows电脑),利用nginx反向代理
1、发布netcore项目,默认即可 1.1、前提,需在appsettings添加Kestrel代理 配置如下: {"Kestrel": {"Endpoints": {"http": {"Url": "http://localhost:7022"},"Https": {&qu…...
Python数据分析案例73——基于多种异常值监测算法探查内幕交易信息
背景 之前有监督模型案例都做烂了,现在来做一下无监督的模型吧,异常检测模型。 其实这个案例主要目的是为了展示这些异常值的无监督算法怎么使用的,本文是一个无监督算法的总结大全。只是恰巧有同学需要做这个内幕交易的数据,因…...
电商数据中台架构:淘宝 API 实时采集与多源数据融合技术拆解
引言 在当今竞争激烈的电商领域,数据已成为企业决策和业务发展的核心驱动力。电商数据中台能够整合和管理企业内外部的各种数据,为业务提供有力支持。其中,淘宝 API 实时采集与多源数据融合技术是数据中台架构中的关键部分。本文将深入探讨这…...
【C语言】动态经典试题练习
前言: 在上一章节讲解了动态的常见错误,在上上章节讲解了动态内存的概念。 古人云: 习题一 请大家看下面的习题,试着分析输出结果 / 找出代码错误的地方。 #include <stdio.h>void GetMemory(char* p) {p (char*)mall…...
Memcached 主主复制架构搭建与 Keepalived 高可用实现
实验目的 掌握基于 repcached 的 Memcached 主主复制配置 实现通过 Keepalived 的 VIP 高可用机制 验证数据双向同步及故障自动切换能力 实验环境 角色IP 地址主机名虚拟 IP (VIP)主节点10.1.1.78server-a10.1.1.80备节点10.1.1.79server-b10.1.1.80 操作系统: CentOS 7 软…...
详解 Servlet 处理表单数据
Servlet 处理表单数据 1. 什么是 Servlet?2. 表单数据如何发送到 Servlet?2.1 GET 方法2.2 POST 方法 3. Servlet 如何接收表单数据?3.1 获取单个参数:getParameter()示例: 3.2 获取多个参数:getParameterV…...
八大排序——冒泡排序/归并排序
八大排序——冒泡排序/归并排序 一、冒泡排序 1.1 冒泡排序 1.2 冒泡排序优化 二、归并排序 1.1 归并排序(递归) 1.2 递归排序(非递归) 一、冒泡排序 1.1 冒泡排序 比较相邻的元素。如果第一个比第二个大,就交换…...
高等数学第三章---微分中值定理与导数的应用(3.1微分中值定理3.2洛必达法则)
3.1 微分中值定理 一、罗尔(Rolle)中值定理 1. 费马(Fermat)引理 定义: 设函数 y f ( x ) y f(x) yf(x) 满足以下条件: 在点 x 0 x_0 x0 的某邻域 U ( x 0 ) U(x_0) U(x0) 内有定义࿱…...
AI超级智能体项目教程(二)---后端项目初始化(设计knif4j接口文档的使用)
文章目录 1.选择JDK的版本和相关配置2.添加依赖信息2.1指定lombok版本信息2.2引入hutool工具类2.3了解knif4j依赖2.4引入knif4j依赖 3.contrller测试3.1完成yml文件配置3.2修改默认扫描路径3.3controller具体的内容3.4配置接口和访问路径3.5如何访问3.6调试接口3.6调试接口 1.选…...
C++面试复习日记(8)2025.4.25,malloc,free和new,delete的区别
1,malloc,free和new,delete的区别 答:malloc和free是c语言中库函数; new和delete是c的操作符; 分配内存:malloc和new 区别: malloc:需要手动计算存储空间 new&#…...
14.ArkUI Radio的介绍和使用
ArkUI Radio 组件介绍与使用指南 什么是 Radio 组件? Radio(单选框)是 ArkUI 中的单选按钮组件,允许用户从一组互斥的选项中选择一个选项。它通常用于表单、设置界面等需要用户做出单一选择的场景。 Radio 的核心特性 单选功能…...
数据结构------C语言经典题目(7)
1.系统栈和数据结构中的栈有什么区别? 1.本质: 系统栈:由程序运行时由操作系统自动分配的一块连续内存区域,用于存储函数调用过程中的临时数据(参数、局部变量、返回地址),是程序运行的底层机制…...
Python教程(一)——Python速览
目录 1. 引言2. Python用作计算器2.1 数字2.2 文本2.3 列表 3. 走向编程的第一步参考 1. 引言 本系列的目的主要是重新回顾Python的语法,以供阅读由Python编写的源码。 在安装完Python后,在命令行中输入python就可以进入交互模式。下文代码段中以>…...
跟我学C++中级篇——处理对象的复制
一、对象的传递 在应用程序中,经常会遇到不同线程或不同模块间需要进行对象的传递,本来传递不是什么多大的事。但问题是,如果对象的值大到一定的程度后,传递不是问题可对象值的处理反而成了问题了。举一个现实世界的例子…...
基于PyQt5实现仿QQ-第二章-用户登录
基于PyQt5实现仿QQ-第二章-用户登录 Author: Daydreamer 项目简介 本项目基于PyQt5仿照目前流行的即时通信软件QQ,实现了新用户注册、用户登录、自动登录、记住多用户账号、用户搜索、添加好友、好友间聊天(消息持久化、同步化)等功能。 …...
[OS_8] 终端和 UNIX Shell | 会话和进程组 | sigaction | dash
我们已经知道如何用 “文件描述符” 相关的系统调用访问操作系统中的对象:open, read, write, lseek, close。操作系统也提供了 mount, pipe, mkfifo 这些系统调用能 “创建” 操作系统中的对象。 当然,我们也知道操作系统中的对象远不止于此࿰…...
IP查询专业版:支持IPv4/IPv6自动识别并切换解析的API接口使用指南
以下是根据您提供的网页内容编辑的符合CSDN内容发布要求的Markdown格式文本: 一、API概述 在开发过程中,我们常常需要对IP地址进行查询,以获取其详细信息,如地理位置、运营商等。万维易源的“IP查询专业版”API接口能够提供丰富…...
ESG跨境电商如何为国内的跨境电商企业打开国外的市场
现在不管是国内还是国外,做电商的企业都非常的多,那么既然有这么多大电商公司,就要有为这些电商公司提供服务的公司,这就是ESG,它是专门为跨境电商服务的公司,那么这家公司的主要业务是什么呢?它…...