Q01
Servlet 完整的生命周期有哪些阶段?
Servlet 生命周期分 三个核心阶段:
- 初始化(init):容器创建实例后,仅执行一次
init()方法。 - 服务(service):客户端请求到来,反复调用
service()(内部分发doGet/doPost)处理请求。 - 销毁(destroy):服务器关闭 / 项目移除前,执行一次
destroy()释放资源。
Q02
JSP 的三个内置对象的作用域区别
作用域 = 数据存活范围、共享范围。四作用域完整排序:
page<
request<
session<
application
| 作用域 | 对应对象 | 范围 | 生命周期 | 常见场景 |
|---|---|---|---|---|
| page | pageContext | 当前页面有效 | 仅当前 JSP 页面 | 页面内临时数据 |
| request | request | 一次客户端请求 | 请求 → 响应结束 | 表单提交、页面间单次传参 |
| session | session | 同一个浏览器会话 | 浏览器打开 → 会话结束 | 登录用户信息、个人会话数据 |
| application | application | 整个 Web 项目全局 | 服务器启动 → 关闭 | 网站全局配置、在线人数 |
核心速记
page 仅当前页;request 一次请求内(forward 可共享,刷新就没了);session 整个浏览器会话(关浏览器消失);application 全体用户共享(停服才销毁)。
Q03
HTTP 请求转发和重定向的区别
| 维度 | 转发 forward | 重定向 redirect |
|---|---|---|
| 请求次数 | 1 次请求 | 2 次请求 |
| 地址栏变化 | 不变,显示原 URL | 更新为新 URL |
| 数据共享 | 共享 request 数据 | 不共享,原 request 销毁 |
| 跳转位置 | 服务器内部完成 | 客户端重新发起请求 |
| 跳转范围 | 仅限当前项目内 | 内部 / 外部网址均可 |
| 状态码 | 200(正常响应) | 302(临时重定向) |
语法对比
// 转发(服务器内部跳转)
request.getRequestDispatcher("目标地址").forward(request, response);
// 重定向(客户端二次请求)
response.sendRedirect("目标地址");
速记口诀
一次请求地址不变,转发共享数据;两次请求地址改变,重定向跨站可行。
Q04
Session 工作原理以及失效的常见原因
一、工作原理
- 客户端首次访问,服务器创建 Session,生成唯一
SessionID。 - 服务器把
SessionID以 Cookie 形式发给浏览器(默认名JSESSIONID)。 - 浏览器每次请求,自动携带 JSESSIONID 发给服务器。
- 服务器根据
SessionID找到对应 Session,实现同一用户跨页面共享数据。
核心
依靠 Cookie 传递 SessionID 来识别同一个会话。Cookie 禁用时,自动使用 URL 重写(地址栏拼接 ;jsessionid=xxx)。
二、常见失效原因
| 原因 | 说明 |
|---|---|
| 会话超时(最常见) | Tomcat 默认 30 分钟无请求自动销毁 |
| 手动销毁 | session.invalidate() 立即销毁 |
| 关闭浏览器 | 临时 Cookie 丢失,再次打开为新会话 |
| 清除 Cookie | JSESSIONID 丢失,会话失效 |
| 服务器重启 | 内存 Session 全部清空(除非持久化) |
| 跨浏览器/隐身模式 | Cookie 隔离,视为不同会话 |
Q05
Cookie 从创建到客户端再次请求的完整工作流程
整体分为服务端创建响应 → 客户端保存 → 下次请求自动携带三大阶段。
完整流程
- 客户端首次发起 HTTP 请求:此时请求头不携带 Cookie。
- 服务端创建 Cookie:
Cookie cookie = new Cookie("username", "test"); cookie.setMaxAge(60 * 60); // 有效期 1 小时 cookie.setPath("/"); response.addCookie(cookie); - 服务器返回响应:响应头携带
Set-Cookie字段。Set-Cookie: username=test; Max-Age=3600; Path=/ - 浏览器接收并存储:
- 会话 Cookie(未设置 MaxAge / 负值):存于浏览器内存,关闭即销毁。
- 持久 Cookie(MaxAge > 0):写入本地磁盘,到期自动删除。
- 客户端再次请求同域名:浏览器自动筛选匹配的 Cookie。
- Cookie 放入请求头发送:
Cookie: username=test - 服务器读取 Cookie:
Cookie[] cookies = request.getCookies(); for (Cookie c : cookies) { if ("username".equals(c.getName())) { ... } }
Max-Age 取值说明
- 正数:持久化,指定存活秒数
- 负数(默认):会话 Cookie,浏览器关闭即失效
- 0:立即删除对应 Cookie
Q06
Servlet 和 JSP 的关系和区别
核心关系
JSP 本质就是 Servlet。JSP 页面运行时,服务器先翻译成 Servlet 源代码,再编译成 class 执行。
执行流程:
.jsp→
Servlet .java→
.class→
容器运行
| 维度 | Servlet | JSP |
|---|---|---|
| 写法与侧重点 | 纯 Java 类,Java 代码为主 | HTML 为主,内嵌 Java 代码 |
| 职责分工 | 控制器(Controller) | 视图(View) |
| 运行方式 | 需手动配置映射路径 | 容器自动识别,直接访问 |
| 内置对象 | 无,需手动获取 | 自带 9 大内置对象 |
一句话总结
JSP = 披着 HTML 外衣的 Servlet;Servlet 做控制,JSP 做展示,二者配合实现 JavaWeb 开发。
Q07
JDBC 操作 MySQL 数据库的完整步骤
六步核心流程
- 导入驱动包(mysql-connector-java)
- 加载数据库驱动
Class.forName("com.mysql.cj.jdbc.Driver"); - 建立数据库连接
String url = "jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC"; Connection conn = DriverManager.getConnection(url, "root", "123456"); - 创建 SQL 执行对象
// Statement(不推荐,易 SQL 注入) Statement stmt = conn.createStatement(); // PreparedStatement(推荐) String sql = "select * from user where id = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setInt(1, 1); - 执行 SQL、处理结果
executeQuery():执行查询,返回ResultSetexecuteUpdate():执行增删改,返回受影响行数
- 关闭资源(逆序关闭)
if (rs != null) rs.close(); if (pstmt != null) pstmt.close(); if (conn != null) conn.close();
关键注意
资源关闭写在 finally 中,保证一定执行;MySQL 8 必须加 serverTimezone=UTC。
Q08
连接池的作用
传统 JDBC 问题:每次操作数据库都要 创建连接 → 使用 → 关闭连接,开销大、耗时高。
连接池本质:提前初始化一批数据库连接,放入容器统一管理、重复复用。
核心作用
- 减少资源开销:连接只创建一次,循环复用,避免频繁创建、销毁的损耗。
- 提升响应速度:直接从池中获取连接,无需等待创建。
- 控制最大并发数:限制最大连接数量,防止数据库被压垮。
- 统一管理连接:自动回收空闲、超时、异常连接。
常见连接池
DBCP(Apache 经典)
C3P0(自动重连)
Druid 德鲁伊(阿里,企业主流)
HikariCP(性能最高,SpringBoot 默认)
一句话速记
连接池就是数据库连接的 "缓存池",复用连接、提性能、控并发、护数据库。
Q09
PreparedStatement 和 Statement 的区别
| 维度 | Statement | PreparedStatement |
|---|---|---|
| 编译机制 | 每次执行重新编译,效率低 | SQL 预编译一次,重复执行效率高 |
| SQL 注入风险 | 极易注入,不安全 | 彻底防 SQL 注入(重点考点) |
| 传参方式 | 字符串拼接,繁琐易出错 | 占位符 ? + setXxx() 赋值 |
| 批量操作 | 批量处理能力弱 | 原生支持批量添加/更新 |
| 数据类型处理 | 手动转换、拼接引号 | 自动匹配类型 |
传参示例对比
// Statement:字符串拼接(危险!)
String sql = "select * from user where name='" + name + "'";
// PreparedStatement:占位符(安全)
String sql = "select * from user where name=?";
pstmt.setString(1, name);
SQL 注入示例
恶意输入:' or '1'='1Statement 拼接后 SQL 逻辑恒成立,泄露全部数据;PreparedStatement 会把整段内容当作普通参数,避免攻击。
Q10
AJAX 异步请求的完整流程(基于 XMLHttpRequest)
前端完整流程(7 步)
- 创建 XMLHttpRequest 对象
let xhr = new XMLHttpRequest(); - 绑定状态监听事件
xhr.onreadystatechange = function() { if (xhr.readyState === 4 &&& xhr.status === 200) { let res = xhr.responseText; console.log(res); } };readyState:0 未初始化 → 1 连接已建立 → 2 请求已接收 → 3 正在接收 → 4 请求完成 - 初始化请求 open()
xhr.open("POST", "/ajaxServlet", true); // true = 异步 - POST 设置请求头
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - 发送请求 send()
xhr.send("name=zhangsan&age=20"); - 后端处理并返回响应
- 前端回调渲染页面
后端处理要点(Servlet)
- 接收参数:
request.getParameter("name") - 设置编码:
request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); - 禁止页面跳转:AJAX 场景不能使用 forward / redirect
- 返回数据:JSON 为主流格式
GET vs POST(前端)
- GET:参数拼在 URL 后,受长度限制,会被缓存
- POST:参数放请求体,无长度限制,需手动设置 Content-Type
Q11
过滤器的使用原理及其场景
核心原理(链式过滤)
- 客户端发起请求访问 Servlet/JSP。
- 请求先经过匹配路径的 Filter,执行
doFilter()。 chain.doFilter(request, response)放行请求:- 放行前:对请求预处理
- 放行后:资源处理完毕,对响应后处理
- 多个过滤器按注册顺序形成 过滤器链(FilterChain),依次执行。
- 所有过滤器放行后,才执行目标 Servlet/JSP。
- 响应原路倒序经过过滤器,最终返回浏览器。
三大生命周期方法
init():服务器启动时只执行一次doFilter():每次匹配请求都执行,核心方法destroy():项目停止时执行一次
常用使用场景
| 场景 | 作用 |
|---|---|
| 统一编码设置 | 拦截所有请求,统一设置 UTF-8,解决全站中文乱码 |
| 登录权限校验 | 未登录用户禁止访问后台,无登录则重定向 |
| URL 资源权限控制 | 区分普通用户/管理员,校验角色权限 |
| 过滤敏感词汇 | 替换评论、留言中的违规词 |
| 请求日志记录 | 记录访问 IP、地址、时间、参数 |
| 跨域统一处理 | 统一添加跨域响应头 |
| 压缩响应数据 | 减小传输体积,提升速度 |
| 静态资源防盗链 | 校验 Referer,拦截非法盗链 |
JavaWeb 完整业务闭环
flowchart TD
A[浏览器客户端] -->|1.发起HTTP请求
携带Cookie/JSESSIONID| B[Filter过滤器链]
B -->|预处理:编码/登录校验/跨域/日志| C{chain.doFilter
放行?}
C -->|不放行:重定向/直接返回| Z[响应返回浏览器]
C -->|放行| D[Servlet控制器]
D -->|分支1:普通页面跳转| E[JSP视图]
D -->|分支2:AJAX异步请求| F[处理业务,返回JSON文本]
E -->|页面渲染完成| Z
F -->|输出流返回数据| Z
D --> G[业务Service]
G --> H[数据库连接池]
H --> I[Connection连接]
I --> J[PreparedStatement预编译SQL]
J --> K[MySQL数据库]
K -->|查询/增删改结果| I
I -->|归还连接到池| H
D -.->|读取/写入session域数据| L[Session会话]
L -.->|依靠Cookie存储JSESSIONID| A
D -.->|response.addCookie设置Cookie| A
E & F --> B
B -->|后置处理:压缩、敏感词过滤| Z
Q12
Maven 的优势和作用
Maven 是 Java 项目 项目构建 + 依赖管理工具,通过 pom.xml 统一管理项目。
核心作用
- 依赖管理(最核心):自动导入 jar 包,只需写坐标(groupId、artifactId、version),自动处理依赖传递、版本冲突。
- 标准化项目目录结构:
src/main/java:业务代码src/main/resources:配置文件src/test/java:测试代码webapp:存放页面
- 统一项目构建生命周期:
clean compile test package install deploy
- 仓库机制统一管理 jar:本地仓库 → 私服仓库 → 中央仓库,jar 只下载一次,多个项目共用。
- 多模块项目拆分管理:大型项目拆分子模块,统一父工程管理版本。
- 插件扩展:内置编译、测试、打包插件,可自定义实现代码生成、热部署等。
速记总结
- 管 jar:依赖自动下载、解决冲突
- 管目录:统一标准项目结构
- 管构建:一键编译测试打包部署
- 管仓库:本地/私服/中央三级仓库复用 jar
- 管多模块:大型项目拆分、统一版本管理