第一章:JSP 与 Web 技术概论
1. Web 应用基本原理
- B/S 架构(Browser/Server):用户通过浏览器访问服务器上的 Web 应用,无需安装客户端。
- HTTP 请求/响应模型:
- 客户端(浏览器)发送 HTTP 请求(GET/POST 等);
- 服务器接收请求,处理后返回 HTTP 响应(HTML 页面、JSON 等);
详细解析了 JSP 核心考点,涵盖 Web 应用原理、B/S 架构及 MVC 模式。介绍了 JSP 开发环境配置、基本语法(脚本、指令、动作)、九大内置对象及其作用域管理。深入讲解了 Cookie 与 Session 的会话追踪机制、JavaBean 规范、文件操作及 JDBC 数据库连接与防注入技术。同时阐述了 Servlet 生命周期、过滤器与监听器的工作原理,以及 JSTL 标签库和 EL 表达式的使用。最后提供了复习建议,帮助读者掌握 JSP 开发关键技能。
| 模式 | 结构 | 缺点 | 适用场景 |
|---|---|---|---|
| 纯 JSP | 所有逻辑写在 JSP 中 | 代码混乱,难维护 | 小型演示 |
| Model 1(JSP + JavaBean) | JSP 负责显示 + 控制,JavaBean 封装数据 | 控制逻辑仍在 JSP,耦合度高 | 简单应用 |
| Model 2 / MVC | Servlet(Controller)+ JavaBean(Model)+ JSP(View) | 结构清晰,职责分离 | 主流开发模式 |
✅ 常考点解析:
MVC 中各角色作用:
📌 答题模板:
'MVC 模式将程序分为三部分:Model 处理数据,View 展示界面,Controller 协调两者。优点是解耦、易维护、便于团队分工。'
| 目录 | 作用 |
|---|---|
webapps | 存放所有 Web 应用(每个应用一个文件夹) |
WEB-INF | 受保护目录,客户端无法直接访问 |
WEB-INF/classes | 存放编译后的 .class 文件 |
WEB-INF/lib | 存放项目依赖的 .jar 包 |
WEB-INF/web.xml | 部署描述符,可配置欢迎页、错误页、Servlet 映射等 |
✅ 常考点解析:
为什么 WEB-INF 下的文件不能被客户端直接访问?
→ 出于安全考虑,防止用户直接下载敏感文件(如 .class、配置文件)。所有对 WEB-INF 的直接 URL 请求都会被 Tomcat 拒绝(返回 404)。
📌 答题关键:安全机制 + 受保护资源
| 语法 | 名称 | 作用 | 注意事项 |
|---|---|---|---|
<%-- 注释 --%> | 隐藏注释 | 仅在 JSP 源码中可见,不会发送到客户端 | 安全注释方式 |
<%! ... %> | 声明 | 定义成员变量或方法(属于生成的 Servlet 类) | 多用户共享,慎用 |
<% ... %> | 脚本片段 | 写 Java 语句(if/for/赋值) | 插入到 _jspService() 方法中 |
<%= 表达式 %> | 表达式 | 输出值(自动调用 out.print()) | 不能加分号! |
<%@ ... %>)include 指令:静态包含
<%@ include file="header.html" %>
→ 编译时合并源码,生成一个 Servlet
page 指令:设置页面属性
<%@ page contentType="text/html;charset=UTF-8" import="java.util.*" errorPage="error.jsp" %>
<jsp:xxx>)<jsp:forward>:请求转发(地址栏不变)
<jsp:forward page="result.jsp" />
<jsp:include>:动态包含
<jsp:include page="menu.jsp"> <jsp:param name="user" value="Tom" /> </jsp:include>
→ 运行时执行被包含页,再合并输出
✅ 常考点解析:
<%@ include %> 与 <jsp:include> 的区别:
| 对比项 | <%@ include %> | <jsp:include> |
|---|---|---|
| 包含时机 | 编译时 | 运行时 |
| 生成 Servlet 数量 | 1 个 | 多个 |
| 能否传参 | ❌ | ✅(用 <jsp:param>) |
| 效率 | 高(一次编译) | 略低(多次执行) |
| 适用场景 | 静态内容(页头/页脚) | 动态内容(权限菜单) |
📌 答题模板:
'静态包含在翻译阶段合并代码,效率高但不能传参;动态包含在运行时执行,可传递参数,适合动态内容。'
| 对象 | 类型 | 主要用途 | 常用方法 |
|---|---|---|---|
| request | HttpServletRequest | 获取客户端请求数据 | getParameter(), setAttribute(), getAttribute() |
| response | HttpServletResponse | 发送响应 | sendRedirect(), setContentType() |
| session | HttpSession | 会话管理 | setAttribute(), getAttribute(), invalidate() |
| application | ServletContext | 全局上下文 | setAttribute(), getInitParameter() |
| out | JspWriter | 页面输出 | print(), println() |
| pageContext | PageContext | 获取其他对象 | getRequest(), getSession() |
| config | ServletConfig | Servlet 配置 | getInitParameter() |
| page | Object | 当前 Servlet 实例 | 等价于 this |
| exception | Throwable | 异常对象 | 仅在 isErrorPage="true" 的页面可用 |
| 作用域 | 对应对象 | 生命周期 | 典型应用 |
|---|---|---|---|
| page | pageContext | 当前 JSP 页面执行期间 | 临时变量 |
| request | request | 一次请求(含 forward) | Servlet 转发数据给 JSP |
| session | session | 一次会话(创建 → 超时/销毁) | 用户登录状态、购物车 |
| application | application | Web 应用启动 → 停止 | 全局计数器、数据库连接池 |
✅ 常考点解析:
xxx.setAttribute("key", value) 和 xxx.getAttribute("key")。forward 后 request 数据还在吗? → 在!(同一请求)redirect 后 request 数据还在吗? → 不在!(新请求)📌 必背口诀:
'page 页内,request 转发,session 会话,application 全局。'
读取:
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie ck : cookies){
if("name".equals(ck.getName())){/* ... */}
}
}
创建与发送:
Cookie c = new Cookie("name","value");
c.setMaxAge(3600); // 有效期 1 小时(秒),0=删除
response.addCookie(c);
JSESSIONID),若 Cookie 禁用则用 URL 重写(response.encodeURL(url))创建与使用:
HttpSession session = request.getSession(); // 自动创建或获取 session
session.setAttribute("user","Tom");
session.invalidate(); // 销毁会话
;jsessionid=xxx)<input type="hidden" name="sessionid" value="xxx">)✅ 常考点解析:
Cookie 与 Session 的区别:
| 对比项 | Cookie | Session |
|---|---|---|
| 存储位置 | 客户端 | 服务器 |
| 安全性 | 低(可篡改) | 高 |
| 大小限制 | ≤ 4KB | 无严格限制 |
| 生命周期 | 可设过期时间 | 默认 30 分钟(可配置) |
| 依赖 | 依赖浏览器启用 Cookie | 默认依赖 Cookie,可 URL 重写 |
📌 应用题:
'用 Session 实现购物车' → 将商品列表存入session.setAttribute("cart", list),后续页面从 session 取出即可。
public class)private)getXxx(), setXxx())<!-- 创建或查找 Bean -->
<jsp:useBean scope="session" />
<!-- 批量赋值(表单 name 必须 = Bean 属性名) -->
<jsp:setProperty name="user" property="*" />
<!-- 单独赋值 -->
<jsp:setProperty name="user" property="name" param="username" />
<!-- 取值 -->
<jsp:getProperty name="user" property="name" />
✅ 常考点解析:
<jsp:setProperty property="*"> 的使用条件:
→ HTML 表单中的 name 属性必须与 JavaBean 的属性名完全一致(包括大小写)。
📌 示例:
表单<input name="email">→ Bean 必须有setEmail(String email)方法。
exists():判断文件/目录是否存在createNewFile():创建新文件mkdirs():创建多级目录delete():删除文件/空目录FileInputStream / FileOutputStream(处理二进制)FileReader / FileWriter(处理文本,注意编码)enctype="multipart/form-data"DiskFileItemFactory, ServletFileUpload✅ 常考点解析:
文件上传表单的关键属性:
→ method="post" + enctype="multipart/form-data"
📌 错误示例:
若忘记enctype,request.getParameter()将无法获取文件内容。
// 1. Class.forName("com.mysql.jdbc.Driver"); // 加载驱动
// 2. Connection conn = DriverManager.getConnection(url, user, pwd);
// 3. Statement stmt = conn.createStatement();
// 4. ResultSet rs = stmt.executeQuery("SELECT * FROM users");
// 5. while(rs.next()){ /* 处理结果 */ }
// 6. rs.close(); stmt.close(); conn.close(); // 关闭资源
使用 PreparedStatement 替代 Statement:
String sql = "SELECT * FROM users WHERE name = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name); // 自动转义
✅ 常考点解析:
为什么用 PreparedStatement 能防注入?
→ 因为它将 SQL 语句和参数分开编译,参数被视为纯数据而非 SQL 代码。
init():初始化(Web 应用启动时或首次请求时调用,仅一次)service():处理请求(每次 HTTP 请求都调用,内部调用 doGet/doPost)destroy():销毁(Web 应用停止时调用,仅一次)HttpServlet 的类。注解(Servlet 3.0+):
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
...
}
web.xml(传统):
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<url-pattern>/login</url-pattern>
</servlet-mapping>
✅ 常考点解析:
doGet 与 doPost 的区别:
→ 分别处理 GET 和 POST 请求,开发者需重写对应方法。
request.setCharacterEncoding("UTF-8")核心方法:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
// 前处理
chain.doFilter(req, res);
// 放行
// 后处理
}
ServletContextListener:监听应用启动/销毁(可用于初始化全局资源)HttpSessionListener:监听会话创建/销毁(可用于统计在线人数)✅ 常考点解析:
doFilter 中设置 request.setCharacterEncoding("UTF-8")。sessionCreated 中计数 +1,sessionDestroyed 中 -1。<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- 条件判断 -->
<c:if test="${age > 18}">成年人</c:if>
<!-- 循环 -->
<c:forEach items="${list}" var="item" varStatus="status">
${status.index}: ${item}
</c:forEach>
<!-- 安全输出(防 XSS) -->
<c:out value="${userInput}" />
${}${作用域。属性名} 或 ${属性名}(自动按 page→request→session→application 查找)${user.name} 等价于 <%= ((User)session.getAttribute("user")).getName() %>✅ 常考点解析:
<c:forEach> 的 varStatus 属性:
→ 提供循环状态信息,如 index(从 0 开始)、count(从 1 开始)。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online