📖前言
Servlet 是 JavaEE 最重要的底层规范,是 JavaWeb 动态开发的基石。浏览器发送请求到 Tomcat 服务器,由 Servlet Java 程序接收请求、执行业务逻辑、给浏览器返回响应结果。
学习前置:掌握 HTML、CSS、JDBC 数据库操作;运行环境:Tomcat 服务器。
一、网络应用体系结构 C/S vs B/S
1.1 C/S 客户端‑服务器模式(Client‑Server)
代表软件:QQ、微信桌面端、游戏客户端
- ✅交互特点:需要下载、安装专用客户端软件才可以使用系统。
- ✅优点:客户端本地渲染,图形界面效果炫酷,交互体验好。
- ❌缺点:服务端版本升级之后,所有用户的客户端必须同步升级,维护成本很高。
1.2 B/S 浏览器‑服务器模式(Browser‑Server)
代表:网页网站、后台管理系统,浏览器就是客户端,不需要额外安装软件。
- ✅交互特点:只需要 PC 设备拥有浏览器,即可访问系统。
- ✅优点:服务端升级更新,客户端浏览器不需要做任何安装升级,维护成本低。
- ❌缺点:网页浏览器能力有限,界面交互效果相比原生客户端会受限。
💡现在企业 Web 项目绝大多数使用 B/S 架构,Servlet 就是 B/S 架构 Java 后端技术。
二、静态 Web 应用 vs 动态 Web 应用
2.1 静态 Web 应用
静态 Web 资源:html、css、js、图片。 浏览器请求,Tomcat 直接把已经写好的 html 文件原样返回给浏览器。
✅工作流程:
❌静态网页三大缺陷:
2.2 动态 Web 应用
动态 Web:请求不再直接访问静态 html,而是访问后端 Java 程序(Servlet)。 Java 程序执行业务逻辑,可以操作数据库,动态拼接输出网页内容,再返回给浏览器。
✅工作流程:
核心区别:静态返回现成文件;动态是程序运行生成响应内容。
三、Servlet 简介
🔔注意:Servlet 代码不能直接 main 方法运行,必须交给 Tomcat 服务器来调用执行。
四、手工开发第一个 Servlet(无 IDE,理解底层原理)
手工开发目的:搞懂 Tomcat 如何加载 Servlet,理解 web.xml 部署描述符作用。实际工作不会手写,都是 IDE 工具开发。
4.1 步骤 1:编写实现 Servlet 接口的 Java 类
核心方法:service(ServletRequest request,ServletResponse response)
- request:封装浏览器发来的全部请求信息
- response:用于向浏览器输出响应数据
import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
public class ShowTime implements Servlet {
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
//1 设置响应MIME类型和编码,告诉浏览器返回的是html网页,编码GBK
response.setContentType("text/html");
response.setCharacterEncoding("GBK");
//2 获取输出打印流,向浏览器输出网页内容
PrintWriter out = response.getWriter();
//3 输出html页面内容,动态输出当前系统时间
out.println("<html>");
out.println("<body>");
out.println("<h1>服务器当前时间:"+ new Date() +"</h1>");
out.println("</body>");
out.println("</html>");
out.flush();
// 输出流不需要手动close,请求响应结束Tomcat自动关闭流
}
//剩下init、getServletConfig、getServletInfo、destroy方法省略实现
@Override public void init(ServletConfig servletConfig) throws ServletException {}
@Override public ServletConfig getServletConfig() { return null; }
@Override public String getServletInfo() { return null; }
@Override public void destroy() {}
}
4.2 编译 Java 文件
编译依赖 Tomcat 提供servlet-api.jar包,需要配置 CLASSPATH 环境变量指向tomcat/lib/servlet-api.jar,否则编译报类找不到。
4.3 部署 class 字节码文件
把编译得到的.class字节码文件,放入 web 项目WEB‑INF/classes目录,必须保留完整包目录结构。
4.4 编写 web.xml 部署描述符
web.xml 告诉 Tomcat:哪个类是 Servlet,浏览器访问什么 URL 可以调用这个 Servlet。
<?xml version="1.0" encoding="UTF-8"?>
<web‑app>
<!– 1.注册Servlet –>
<servlet>
<!– servlet别名,项目内全局唯一 –>
<servlet‑name>showTime</servlet‑name>
<!– Servlet类完整全限定类名:包名.类名 –>
<servlet‑class>com.baizhi.servlet.ShowTime</servlet‑class>
</servlet>
<!– 2.Servlet映射:绑定访问URL路径 –>
<servlet‑mapping>
<!– 必须和上面servlet‑name名字完全一致 –>
<servlet‑name>showTime</servlet‑name>
<!– url‑pattern访问路径,必须以 / 开头 –>
<url‑pattern>/suibian</url‑pattern>
</servlet‑mapping>
</web‑app>
访问地址格式: http://localhost:端口号/项目名/url‑pattern 示例:http://localhost:8989/servletWeb/suibian
4.5 启动 Tomcat,浏览器访问
运行tomcat/bin/startup.bat启动服务器,浏览器输入上面地址访问。
⚠️重要注意点:修改 Servlet 源代码 或者修改 web.xml 配置,需要重新编译、重新部署项目才会生效!
4.6 请求‑响应完整执行流程
五、MyEclipse 工具开发 Servlet(实际开发方式)
手工写 Servlet 只是理解原理,企业开发全部使用 IDE 工具,自动处理编译、部署、依赖包。
步骤 1:配置 MyEclipse 绑定本地 Tomcat
Window → Preferences → Servers → Tomcat 7.x
步骤 2:新建 JavaEE Web Project
步骤 3:编写 Servlet 代码
在 src 源码包创建 Servlet Java 类。
步骤 4:部署项目到 Tomcat
黄色感叹号代表项目变更,点击Redeploy重新部署。提示Successfully deployed代表部署成功。
步骤 5:启动 Tomcat 服务器,浏览器访问测试。
六、Servlet 生命周期【面试高频考点】
Servlet 完整生命周期分为 3 个阶段:初始化 init () → 服务 service () → 销毁 destroy ()
- 默认时机:第一次浏览器请求访问 Servlet 的时候,Tomcat 才创建 Servlet 对象,执行 init () 初始化(懒加载)。
- 可选配置:web.xml 中配置<load‑on‑startup>数字</load‑on‑startup>,服务器启动就创建 Servlet 对象。
提供服务 service () 每一次浏览器发送请求,Tomcat 调用 service 方法处理请求。
⚠️Servlet 是单例对象:整个 Tomcat 里面一个 Servlet 类只会创建一个实例对象,多个用户并发请求,多线程共用这一个 Servlet 对象。
🚨重点坑:Servlet 单例,多线程并发访问属于临界资源,不要在 Servlet 里面定义成员变量! 多个线程同时读写成员变量,会出现线程安全问题。临时数据请定义在 service 方法内部局部变量。
七、Servlet 三种实现方式
表格
| 实现Servlet接口 | 全部方法需要自己重写 | 学习底层原理,开发几乎不用 |
| 继承GenericServlet抽象类 | 已经实现 Servlet 接口,大部分空实现 | 不区分 http 协议,极少使用 |
| 继承HttpServlet抽象类【开发首选】 | 专门针对 HTTP 协议封装,继承 GenericServlet | 实际项目 100% 使用! |
HttpServlet 示例代码:
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
public class HttpShowDate extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
response.setCharacterEncoding("GBK");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1 style='color:red;'>"+new Date()+"</h1>");
out.println("</body></html>");
out.flush();
}
}
八、URL、URI、url‑pattern 概念区分
示例:http://localhost:8080/servlet_day/suibian
示例:/servlet_day/suibian
九、访问 Servlet 的三种请求方式
<a href="/servletWeb/suibian">访问Servlet</a>
<form action="/servlet_day/ParamServlet" method="POST">
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="submit" value="提交">
</form>
十、获取客户端请求参数
核心 API:request.getParameter("参数name属性值"),返回 String 字符串。
示例:表单提交获取用户名密码
Servlet 代码:
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
//获取表单提交参数,参数名和表单input的name一一对应
String username = request.getParameter("username");
String password = request.getParameter("password");
//后台控制台打印
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
response.setContentType("text/html");
response.setCharacterEncoding("GBK");
PrintWriter out = response.getWriter();
out.println("接收用户:"+username);
}
💡注意:getParameter()接收的是表单标签name属性,不是 id!没有写 name 属性,后台拿不到参数。
十一、请求中文乱码解决方案
POST 请求乱码
在获取参数之前设置 request 编码
request.setCharacterEncoding("GBK");
GET 请求乱码
GET 请求参数放在 URL 地址栏,上面的 setCharacterEncoding 无效。 修改 tomcat 配置文件 conf/server.xml,给 Connector 节点增加属性:
<Connector port="8080" URIEncoding="GBK" />
URIEncoding指定 GET 请求 URL 参数的解码字符集。
十二、Servlet 整合 JDBC
Servlet 业务中需要操作数据库,步骤:
不建议在 Servlet 直接写大量 JDBC 代码,后续会抽离 DAO 层。
十三、Servlet 开发常见错误码排查【面试 & 排错必看】
表格
| 404 | 资源找不到 | 1. 访问 URL 路径写错;2. 项目没有部署成功;3.web.xml 的 url‑pattern 配置错误;大小写敏感 |
| 500 | 服务器内部代码异常 | Java 代码运行抛出异常,看 Tomcat 控制台堆栈报错日志,定位代码 bug |
| 405 | 方法不允许 | 1. 没有正确继承 HttpServlet;2.service 方法重写签名写错;3. 请求方式不匹配 |
📝知识点小结
✨课后练习:
📢 以上为本篇 Servlet 学习笔记,若有更好的建议,欢迎评论区商讨交流,欢迎各位大佬指正、补充不同实现思路。
💡学习提示:Servlet 是 JavaWeb 底层,理解请求与响应模型,对后续学习 Filter、Listener、SpringMVC 非常重要。



