JavaWeb 核心知识整合笔记
本文档为 JavaWeb 入门学习笔记,整合了从网络编程基础到 Servlet/JSP、再到过滤器与监听器的核心知识,力求通俗易懂,适合零基础入门。
目录
- 网络编程基础
- [Tomcat 服务器](#Tomcat 服务器)
- [Servlet 核心](#Servlet 核心)
- [JSP 与 EL 表达式](#JSP 与 EL 表达式)
- [Web 组件交互技术](#Web 组件交互技术)
- [Servlet 三大作用域](#Servlet 三大作用域)
- [JSTL 标签库](#JSTL 标签库)
- 三层架构开发模式
- 会话跟踪技术
- 过滤器与监听器
一、网络编程基础
1.1 软件开发架构
目前主流的开发架构有三种:
| 架构 | 全称 | 特点 | 优缺点 |
|---|---|---|---|
| B/S 架构 | Browser/Server(浏览器/服务器) | 通过浏览器访问 | ✅ 节省内存、维护成本低 ❌ 用户体验一般、服务器压力大 |
| C/S 架构 | Client/Server(客户端/服务器) | 需要安装客户端软件 | ✅ 用户体验好、安全性高 ❌ 维护成本高、跨平台性差 |
| 新 B/S 架构 | 两者结合 | 将简单业务交给浏览器处理 | 目前二阶段主流模式 |
1.2 网络传输三要素
网络传输需要三个基本要素:
| 要素 | 作用 | 示例 |
|---|---|---|
| IP 地址 | 找到网络中的目标设备 | 192.168.1.1(本机:127.0.0.1 / localhost) |
| 端口号 | 找到设备上的具体应用 | MySQL:3306、Tomcat:8080 |
| 通讯协议 | 规范数据传输的规则 | TCP / UDP |
1.3 TCP 与 UDP 的区别
| 比较项 | UDP | TCP |
|---|---|---|
| 连接方式 | 面向无连接 | 面向连接(三次握手) |
| 传输速度 | 较快 | 较慢 |
| 安全性 | 不安全 | 安全 |
| 数据量 | 受限(约64K) | 理论不限 |
TCP 三次握手 :建立连接时的三次确认过程;四次挥手:断开连接时的四次确认过程。
1.4 HTTP 协议常见状态码
| 状态码 | 含义 | 解决办法 |
|---|---|---|
| 200 | 请求成功 | 无需处理 |
| 404 | 资源未找到 | 检查请求路径是否正确 |
| 500 | 服务器内部错误 | 检查 Servlet/DAO/Service 层代码 |
二、Tomcat 服务器
2.1 什么是 Web 资源
| 类型 | 组成 | 解析方 |
|---|---|---|
| 静态 Web 资源 | HTML + CSS + JS | 浏览器 |
| 动态 Web 资源 | Servlet + JSP | 服务器 |
2.2 Tomcat 简介
- 开发商:Apache 公司
- 作用:运行 JavaWeb 程序的服务器软件
- 默认端口:8080
2.3 在 IDEA 中配置 Tomcat(简要步骤)
- 创建普通 Java 项目
- 添加 Web 框架支持(右键项目 → Add Framework Support → Web Application)
- 配置 Tomcat 运行环境
- 部署项目并启动
三、Servlet 核心
3.1 什么是 Servlet?
Servlet 是一个运行在服务器上的 Java 程序,用于接收浏览器请求、处理数据并返回响应结果。它是生成动态 Web 资源的核心技术。
3.2 创建 Servlet 的两种方式
方式一:实现 Servlet 接口(原始方式)
java
public class MyServlet implements Servlet {
// 需要实现所有抽象方法
}
方式二:继承 HttpServlet 类
java
@WebServlet("/myServlet") // 注解配置请求地址
public class MyServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) {
// 1. 获取请求参数
// 2. 调用业务层处理数据
// 3. 响应结果给浏览器
}
}
3.3 Servlet 配置方式
方式一:注解配置
java
@WebServlet("/请求地址")
方式二:web.xml 文件配置
xml
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>cn.langtutu.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myServlet</servlet-name>
<url-pattern>/请求地址</url-pattern>
</servlet-mapping>
3.4 Servlet 生命周期
服务器启动 → 未创建 Servlet
↓
第一次请求 → 创建对象 → 初始化(init) → 处理请求(service)
↓
再次请求 → 只调用 service(不再创建)
↓
服务器关闭/重启 → 销毁(destroy)
总结:
- 由谁创建:服务器
- 何时创建:第一次发送请求时
- 以什么方式:单例模式(只创建一个实例)
四、JSP 与 EL 表达式
4.1 什么是 JSP?
JSP(Java Server Page) 是服务器端的动态 Web 资源,可以理解为"简化的 Servlet",它允许在 HTML 中嵌入 Java 代码。
4.2 JSP 基础语法
jsp
<%-- JSP 注释 --%>
<% Java代码; %> <%-- Java小脚本 --%>
<%= 打印内容 %> <%-- 输出到浏览器 --%>
4.3 EL 表达式
作用:在 JSP 页面中从 Servlet 作用域获取数据并显示。
格式 :${对象名}
示例:
jsp
<%-- 从请求域中获取 user 对象的 name 属性 --%>
<p>用户名:${user.name}</p>
注意:EL 表达式底层调用的是 JavaBean 的 getter 方法。
五、Web 组件交互技术
实现 Servlet 与 JSP 之间的数据跳转和共享。
5.1 请求转发(Forward)
特点:
- 发生在服务器端
- 浏览器地址栏不变
- 只发送 1 次请求
- 多个 Servlet 之间可以共享数据
- 可以访问
WEB-INF下的资源
代码:
java
req.getRequestDispatcher("/目标地址").forward(req, resp);
5.2 重定向(Redirect)
特点:
- 发生在浏览器端
- 地址栏会改变
- 发送 2 次请求
- 多个 Servlet 之间不能共享数据
- 不能 访问
WEB-INF下的资源 - 可以访问服务器外部资源
代码:
java
resp.sendRedirect("/目标地址");
六、Servlet 三大作用域
作用域是在服务器内部开辟的"存储空间",用于在多个组件之间共享数据。底层原理是 Map<String, Object> 集合。
6.1 三大作用域对比
| 作用域 | Java 类 | 作用范围 | 获取方式 |
|---|---|---|---|
| 请求域 | HttpServletRequest | 同一次请求 | 直接用 req |
| 会话域 | HttpSession | 浏览器开启到关闭 | req.getSession() |
| 上下文域 | ServletContext | 服务器开启到关闭 | req.getServletContext() |
使用原则:能用小的就不用大的(能用请求域就不用会话域)。
6.2 作用域的核心方法
java
// 存储数据
作用域对象.setAttribute("作用域名", 数据);
// 获取数据
作用域对象.getAttribute("作用域名");
6.3 代码示例
存储数据(OneServlet):
java
// 请求域
req.setAttribute("msg", "请求域数据");
// 会话域
req.getSession().setAttribute("user", user);
// 上下文域
req.getServletContext().setAttribute("appName", "我的项目");
获取数据(TwoServlet):
java
String msg = (String) req.getAttribute("msg");
User user = (User) req.getSession().getAttribute("user");
String appName = (String) req.getServletContext().getAttribute("appName");
七、JSTL 标签库
解决 EL 表达式对数组/集合遍历不友好的问题,让前端人员不用写 Java 代码。
7.1 使用前准备
- 导入 JSTL 依赖 jar 包
- 在 JSP 页面引入标签库:
jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
7.2 常用标签
① c:if(条件判断)
jsp
<c:if test="${user != null}">
<p>欢迎:${user.name}</p>
</c:if>
② c:choose(多条件分支)
jsp
<c:choose>
<c:when test="${score >= 90}">优秀</c:when>
<c:when test="${score >= 60}">及格</c:when>
<c:otherwise>不及格</c:otherwise>
</c:choose>
③ c:forEach(循环遍历)
jsp
<c:forEach var="product" items="${productList}">
<tr>
<td>${product.id}</td>
<td>${product.name}</td>
<td>${product.price}</td>
</tr>
</c:forEach>
④ fmt:formatDate(日期格式化)
jsp
<fmt:formatDate value="${product.createTime}" pattern="yyyy-MM-dd HH:mm:ss"/>
八、三层架构开发模式
8.1 什么是三层架构
将 JavaWeb 项目划分为三个层次,各司其职:
| 层级 | 名称 | 作用 | 对应组件 |
|---|---|---|---|
| 表示层 | View/Controller | 展示数据、接收请求 | JSP + Servlet |
| 业务层 | Service | 处理业务逻辑、简化 DAO 调用 | Service 接口 + 实现类 |
| 持久层 | DAO | 操作数据库 | DAO 接口 + Mapper + MyBatis |
8.2 使用三层架构的好处
- 明确责任:每层只做自己的事
- 提高工作效率:分层开发,并行工作
- 高内聚、低耦合:同一模块内联系紧密,不同模块互不影响
8.3 标准项目结构
src/
├── cn.langtutu.web/ # 表示层
│ ├── servlet/ # Servlet 控制器
│ └── jsp/ # JSP 视图
├── cn.langtutu.service/ # 业务层
│ ├── IXxxService.java # 业务接口
│ └── impl/
│ └── XxxServiceImpl # 业务实现
├── cn.langtutu.dao/ # 持久层
│ ├── IXxxDAO.java # DAO 接口
│ └── impl/
│ └── XxxDAOImpl # DAO 实现
├── cn.langtutu.domain/ # JavaBean(实体类)
├── cn.langtutu.util/ # 工具类
├── resource/ # 配置文件
│ ├── db.properties # 数据库配置
│ ├── log4j.properties # 日志配置
│ └── mybatis-config.xml # MyBatis 主配置
└── webapp/ # Web 资源
├── WEB-INF/
│ └── lib/ # 依赖 jar 包
└── *.jsp / *.html # 页面文件
8.4 三层架构数据交互流程
浏览器 → Servlet(接收请求)
↓
Service(处理业务)
↓
DAO(操作数据库)
↓
返回数据给 Servlet
↓
JSP 展示数据 → 浏览器
九、会话跟踪技术
9.1 HTTP 无状态问题
HTTP 协议本身"没有记忆",每次请求都是独立的。比如登录后,再次请求时服务器不知道你是谁。
解决方案:Cookie 和 Session
9.2 Cookie
Cookie 是服务器创建、存储在浏览器端的"小纸条",用于记录用户信息。
核心方法:
java
// 创建 Cookie
Cookie cookie = new Cookie("username", "zhangsan");
// 设置存活时间(秒),0 表示立即删除,正数表示持久化存储
cookie.setMaxAge(60 * 60 * 24); // 1天
// 响应给浏览器
resp.addCookie(cookie);
在 JSP 中获取 Cookie:
jsp
${cookie.username.value}
9.3 Session
Session 是服务器端的"记忆空间",用于在浏览器会话期间保存用户数据。
核心方法:
java
// 获取 Session 对象
HttpSession session = req.getSession();
// 存储数据
session.setAttribute("user", user);
// 获取数据
User user = (User) session.getAttribute("user");
// 移除指定数据
session.removeAttribute("user");
// 销毁整个 Session
session.invalidate();
9.4 Session 与 Cookie 的区别
| 比较项 | Cookie | Session |
|---|---|---|
| 数据存储位置 | 浏览器端 | 服务器端 |
| 共享数据类型 | String | Object |
| 共享数据个数 | 1个 | 多个 |
| 安全性 | 较低(数据在浏览器) | 较高(数据在服务器) |
内在联系:Session 底层依赖于 Cookie(通过 JSESSIONID 标识用户)。
十、过滤器与监听器
10.1 JavaWeb 三大核心组件
| 组件 | 名称 | 作用 |
|---|---|---|
| Servlet | 控制器 | 接收请求、处理请求、响应请求 |
| Filter | 过滤器 | 过滤请求和响应(如登录校验、编码设置) |
| Listener | 监听器 | 监听作用域及属性的变化 |
10.2 过滤器(Filter)
什么是过滤器:在请求到达 Servlet 之前和响应离开 Servlet 之后,进行"拦截"和"放行"。
生命周期:
服务器启动 → 创建过滤器 → 初始化(init)
↓
每次请求 → 调用 doFilter(执行过滤逻辑)
↓
服务器关闭/重启 → 销毁(destroy)
过滤器应用场景:
- ✅ 登录校验
- ✅ 统一编码设置
- ✅ 敏感词过滤
登录校验过滤器示例:
java
@WebFilter("/*") // 过滤所有请求
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
// 获取 Session 中的用户
User user = (User) request.getSession().getAttribute("user");
if (user == null) {
// 未登录,跳转到登录页
response.sendRedirect("/login.jsp");
} else {
// 已登录,放行请求
chain.doFilter(req, resp);
}
}
}
统一编码过滤器示例:
java
@WebFilter("/*")
public class CharacterFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
chain.doFilter(req, resp);
}
}
10.3 监听器(Listener)
作用:监听 Servlet 作用域的创建/销毁,以及作用域中数据的增删改。
常见分类:
- 监听作用域创建/销毁:
ServletContextListener、HttpSessionListener - 监听作用域属性变化:
ServletContextAttributeListener、HttpSessionAttributeListener
应用场景:系统启动时创建初始账户、统计在线人数等。