概述 JavaWeb 用途 JavaWeb 技术广泛应用于构建各种类型的 Web 应用程序, 从简单的个人博客到复杂的企业级系统。 主要用于以下几个核心领域:
企业级管理系统: 这是 JavaWeb 最传统也是最重要的应用领域。 包括 ERP( 企业资源计划) 、 CRM( 客户关系管理) 、 OA( 办公自动化) 等系统。 凭借其稳定性、 安全性和强大的事务处理能力, Java 成为大型企业信息系统的首选技术。
电子商务平台: 大型电商平台如淘宝、 京东的后台系统大量使用 JavaWeb 技术。 其高并发处理能力和分布式架构支持, 能够应对海量用户访问和交易处理。
金融银行系统: 银行核心交易系统、 支付网关、 证券交易平台等对安全性和可靠性要求极高的系统, 几乎都采用 JavaWeb 技术构建。
社交网络平台: 微博、 LinkedIn 等社交平台的后端服务, 需要处理海量用户数据和实时交互, JavaWeb 提供了强大的技术支持。
云计算与微服务: 现代云原生应用、 微服务架构中, Spring Cloud 等 JavaWeb 框架成为主流选择, 支持服务的快速开发、 部署和扩展。
API 服务与后端接口: 为移动端、 前端应用提供 RESTful API 接口, JavaWeb 以其成熟的生态系统和优秀的性能表现, 成为后端服务开发的主流技术。
JavaWeb 历史 🌱 起源: Servlet 与 JSP 时代 (1997-2000) JavaWeb 的发展始于 Sun 公司推出的一系列 Web 技术标准。
Servlet 诞生: 1997 年, Sun 发布了 Servlet 1.0 规范, 这是 Java 用于 Web 开发的第一个标准。 Servlet 运行在服务器端, 负责处理 HTTP 请求并生成响应。
JSP 出现: 1999 年, JSP( JavaServer Pages) 1.0 发布。 JSP 允许在 HTML 中嵌入 Java 代码, 简化了动态网页的开发。
早期局限: 这一时期的 JavaWeb 开发较为繁琐, 需要手动配置大量的 XML 文件, 且 Servlet 和 JSP 的职责划分不够清晰。
🚀 发展: Struts 与 MVC 模式 (2000-2005) 随着 Web 应用复杂度的增加, MVC( Model-View-Controller) 设计模式被引入 JavaWeb 开发。
Struts 框架: 2000 年, Apache Struts 1.0 发布, 成为第一个广泛使用的 JavaWeb MVC 框架。 它将业务逻辑、 数据展示和控制流程分离, 提高了代码的可维护性。
Hibernate ORM: 2001 年, Hibernate 出现, 解决了 Java 对象与关系数据库之间的映射问题( ORM) , 简化了数据库操作。
Spring 框架萌芽: 2002 年, Rod Johnson 出版《 Expert One-on-One J2EE Design and Development》 , 提出了轻量级容器概念, 为 Spring 框架的诞生奠定基础。
💎 成熟: Spring 时代 (2005-2013) Spring 框架的出现彻底改变了 JavaWeb 开发的格局。
Spring 1.0: 2004 年正式发布, 引入了依赖注入( DI) 和面向切面编程( AOP) 等核心概念, 极大地简化了企业级应用开发。
Spring MVC: 2005 年, Spring 2.0 引入了 Spring MVC 框架, 提供了比 Struts 更优雅、 更灵活的 Web 层解决方案。
SSH 组合: Struts + Spring + Hibernate 成为当时最流行的 JavaWeb 技术栈, 被称为”SSH 三大框架”。
注解驱动: Spring 2.5 开始支持注解配置, 减少了 XML 配置的复杂度。
🌟 革新: Spring Boot 与微服务 (2014-至今) 随着云计算和微服务架构的兴起, JavaWeb 进入了快速开发和自动化配置的时代。
Spring Boot: 2014 年, Spring Boot 1.0 发布, 提出了”约定优于配置”的理念, 实现了零配置启动和自动装配, 极大降低了 JavaWeb 项目的搭建门槛。
微服务架构: Spring Cloud 基于 Spring Boot, 提供了一整套微服务解决方案, 包括服务发现、 配置中心、 负载均衡、 熔断器等。
响应式编程: Spring 5.0 引入了 WebFlux, 支持响应式编程模型, 能够以非阻塞的方式处理高并发请求。
云原生时代: JavaWeb 技术与 Docker、 Kubernetes 等云原生技术深度融合, 成为构建现代化云应用的重要技术栈。
JavaWeb 特点 ⭐⭐ 核心优势
跨平台性与可移植性 JavaWeb 应用运行在 JVM 上, 继承了 Java “一次编写, 到处运行”的特性。 无论是 Linux、 Windows 还是 macOS 服务器, 只要安装了合适的 JDK 和 Web 容器( 如 Tomcat) , 应用就能正常运行。 这大大降低了部署和维护的成本。
成熟的生态系统 JavaWeb 拥有极其丰富的开源框架和工具库。 从 Web 层的 Spring MVC、 Struts, 到业务层的 Spring Framework, 再到持久层的 Hibernate、 MyBatis, 开发者可以根据需求选择合适的技术组合。 此外, 还有大量的第三方库支持日志、 安全、 缓存、 消息队列等功能。
强大的企业级支持 JavaWeb 技术规范( Java EE / Jakarta EE) 定义了一整套企业级应用标准, 包括事务管理、 安全性、 分布式计算、 消息服务等。 这些标准确保了不同厂商的实现具有兼容性, 为企业级应用提供了可靠的技术保障。
⭐⭐ 稳健与安全
类型安全与编译检查: Java 是强类型语言, 编译器会在编译阶段捕获大部分类型错误, 减少了运行时异常的发生。
内存管理: JVM 的自动垃圾回收机制避免了内存泄漏和悬空指针等问题。
安全机制: Java 提供了完善的安全 API, 支持加密、 认证、 授权等功能。 Spring Security 等框架进一步简化了 Web 应用的安全实现。
异常处理: 完善的异常处理机制使得程序能够在遇到错误时优雅降级, 而不是直接崩溃。
高性能与可扩展性 虽然 Java 常被误解为性能较低, 但现代 JVM 通过 JIT( 即时编译) 技术已经能够达到接近原生代码的性能。 更重要的是, JavaWeb 应用具有优秀的水平扩展能力:
多线程支持: Java 原生支持多线程, 能够充分利用多核 CPU 资源。
集群部署: JavaWeb 应用可以轻松部署在集群环境中, 通过负载均衡实现高可用和高并发。
异步处理: Servlet 3.0+ 和 Spring WebFlux 支持异步非阻塞处理, 显著提升了系统的吞吐量。
⭐⭐ 生态与扩展
前后端分离支持 现代 JavaWeb 开发普遍采用前后端分离架构。 后端专注于提供 RESTful API 或 GraphQL 接口, 前端使用 Vue、 React、 Angular 等框架构建用户界面。 这种架构使得前后端可以独立开发、 测试和部署, 提高了开发效率。
微服务与云原生 JavaWeb 技术与微服务架构天然契合。 Spring Cloud 提供了一站式微服务解决方案, 包括:
服务注册与发现( Eureka、 Nacos)
配置中心( Config Server、 Nacos Config)
负载均衡( Ribbon、 LoadBalancer)
熔断器( Hystrix、 Sentinel)
网关( Zuul、 Gateway)
持续集成与 DevOps JavaWeb 项目与 Maven、 Gradle 等构建工具完美集成, 支持自动化构建、 测试和部署。 结合 Jenkins、 GitLab CI 等 CI/CD 工具, 可以实现高效的 DevOps 流程。
JavaWeb 运行机制 JavaWeb 应用的运行机制基于客户端-服务器( C/S) 架构, 通过 HTTP 协议进行通信。 其核心组件包括 Web 服务器、 Servlet 容器和应用服务器。
⭐⭐ 核心组件: Web 服务器、 Servlet 容器与应用服务器
Web 服务器: 如 Apache HTTP Server、 Nginx, 主要负责处理静态资源( HTML、 CSS、 JS、 图片等) 的请求, 并可以将动态请求转发给后端的 Servlet 容器。 Servlet 容器: 如 Tomcat、 Jetty、 Undertow, 是 JavaWeb 应用的核心运行环境。 它负责加载、 管理和执行 Servlet, 处理 HTTP 请求和响应。 应用服务器: 如 WildFly、 WebLogic、 WebSphere, 除了包含 Servlet 容器外, 还提供了完整的 Java EE 规范实现, 包括 EJB、 JMS、 JTA 等企业级功能。
⭐⭐ 请求处理流程 这是 JavaWeb 应用运行的核心流程, 发生在用户访问网站时。
客户端发起请求: 用户在浏览器中输入 URL 或点击链接, 浏览器发送 HTTP 请求到服务器。
Web 服务器接收: Nginx 或 Apache 接收到请求, 如果是静态资源则直接返回, 如果是动态请求则转发给 Tomcat。
Servlet 容器处理: Tomcat 根据 URL 映射找到对应的 Servlet, 创建或复用 Servlet 实例。
业务逻辑执行: Servlet 调用 Service 层处理业务, Service 层通过 DAO 层访问数据库。
生成响应: 处理结果封装成 HTTP 响应( JSON、 HTML 等) , 返回给客户端。
浏览器渲染: 浏览器接收响应并渲染页面或处理数据。
⭐⭐ 生命周期管理 Servlet 容器负责管理 Servlet 的生命周期:
加载与实例化: 容器启动时或首次请求时加载 Servlet 类并创建实例。
初始化: 调用 init() 方法进行初始化配置。
服务: 每次请求到来时, 调用 service() 方法处理请求。
销毁: 容器关闭时, 调用 destroy() 方法释放资源。
Web 基础 HTTP 协议 HTTP( HyperText Transfer Protocol) 是 Web 应用的基础协议, 定义了客户端和服务器之间通信的规则。
HTTP 特点
特性
说明
无状态
服务器不保存客户端的状态信息, 每次请求都是独立的
无连接
HTTP/1.0 每次请求后断开连接; HTTP/1.1+ 支持持久连接
简单快速
请求方法少( GET、 POST 等) , 通信效率高
灵活
可以传输任意类型的数据, 通过 Content-Type 标识
HTTP 请求 HTTP 请求由请求行、 请求头和请求体三部分组成。
⭐⭐ 请求行 1 GET /index.html HTTP/1.1
请求方法: GET、 POST、 PUT、 DELETE、 PATCH 等
请求路径: URL 的路径部分
HTTP 版本: HTTP/1.1、 HTTP/2、 HTTP/3
⭐⭐ 请求头 1 2 3 4 5 Host : www.example.comUser-Agent : Mozilla/5.0Accept : text/html,application/jsonContent-Type : application/jsonAuthorization : Bearer token123
常见请求头:
Host: 目标主机
User-Agent: 客户端信息
Accept: 可接受的内容类型
Content-Type: 请求体的数据类型
Authorization: 认证信息
Cookie: 携带的 Cookie 数据
⭐⭐ 请求体 POST、 PUT 等方法可以携带请求体, 包含提交的数据。
1 2 3 4 { "username" : "admin" , "password" : "123456" }
HTTP 响应 HTTP 响应由状态行、 响应头和响应体三部分组成。
⭐⭐ 状态行
HTTP 版本
状态码: 200、 404、 500 等
状态描述: OK、 Not Found、 Internal Server Error 等
⭐⭐ 常见状态码
状态码
含义
说明
200
OK
请求成功
201
Created
资源创建成功
301
Moved Permanently
永久重定向
302
Found
临时重定向
304
Not Modified
资源未修改( 缓存命中)
400
Bad Request
请求参数错误
401
Unauthorized
未授权, 需要认证
403
Forbidden
禁止访问
404
Not Found
资源不存在
500
Internal Server Error
服务器内部错误
502
Bad Gateway
网关错误
503
Service Unavailable
服务不可用
⭐⭐ 响应头 1 2 3 4 Content-Type : application/json; charset=utf-8Content-Length : 1234Set-Cookie : sessionId=abc123; Path=/; HttpOnlyCache-Control : max-age=3600
⭐⭐ 响应体 服务器返回的实际内容, 可以是 HTML、 JSON、 XML、 图片等。
1 2 3 4 5 6 7 8 { "code" : 200 , "message" : "success" , "data" : { "id" : 1 , "name" : "张三" } }
HTTP 方法
方法
用途
是否幂等
是否有请求体
GET
获取资源
✓
✗
POST
创建资源
✗
✓
PUT
更新资源( 全量)
✓
✓
PATCH
更新资源( 部分)
✗
✓
DELETE
删除资源
✓
✗
HEAD
获取响应头
✓
✗
OPTIONS
查询支持的方法
✓
✗
Session 与 Cookie 由于 HTTP 是无状态协议, 为了保持用户的登录状态等信息, 需要使用 Session 和 Cookie 技术。
Cookie Cookie 是服务器发送到浏览器并保存在本地的一小段数据, 浏览器会在后续请求中自动携带。
⭐⭐ Cookie 特点
存储在客户端( 浏览器)
大小限制: 通常不超过 4KB
数量限制: 每个域名最多 20-50 个 Cookie
安全性较低: 可以被用户查看和修改
可以设置过期时间
⭐⭐ Cookie 操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Cookie cookie = new Cookie ("username" , "admin" );cookie.setMaxAge(7 * 24 * 60 * 60 ); cookie.setPath("/" ); cookie.setHttpOnly(true ); response.addCookie(cookie); Cookie[] cookies = request.getCookies(); if (cookies != null ) { for (Cookie c : cookies) { if ("username" .equals(c.getName())) { String value = c.getValue(); } } } Cookie cookie = new Cookie ("username" , null );cookie.setMaxAge(0 ); cookie.setPath("/" ); response.addCookie(cookie);
Session Session 是服务器端存储的用户会话数据, 通过 Session ID 与客户端关联。
⭐⭐ Session 特点
存储在服务器端
大小无限制( 受服务器内存限制)
安全性较高: 数据不暴露在客户端
依赖 Cookie 或 URL 重写传递 Session ID
可以设置超时时间
⭐⭐ Session 操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 HttpSession session = request.getSession();HttpSession session = request.getSession(false );session.setAttribute("user" , userObject); session.setAttribute("loginTime" , new Date ()); User user = (User) session.getAttribute("user" );Date loginTime = (Date) session.getAttribute("loginTime" );session.removeAttribute("user" ); session.invalidate(); session.setMaxInactiveInterval(30 * 60 );
⭐⭐ Session 工作原理 1 2 3 4 5 1. 客户端首次访问服务器 2. 服务器创建 Session, 生成唯一的 Session ID 3. 服务器将 Session ID 通过 Cookie 发送给客户端 4. 客户端后续请求自动携带 Session ID 5. 服务器根据 Session ID 找到对应的 Session 数据
Token 认证 现代 Web 应用更倾向于使用 Token( 如 JWT) 进行认证, 替代传统的 Session-Cookie 机制。
⭐⭐ JWT( JSON Web Token) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 String token = Jwts.builder() .setSubject(user.getId().toString()) .claim("username" , user.getUsername()) .setIssuedAt(new Date ()) .setExpiration(new Date (System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000 )) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); Claims claims = Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody(); String userId = claims.getSubject();String username = claims.get("username" , String.class);
Servlet 技术 Servlet 简介 Servlet 是 JavaWeb 的核心技术, 它是一个运行在服务器端的 Java 程序, 负责处理 HTTP 请求并生成响应。
Servlet 生命周期 Servlet 的生命周期由 Servlet 容器管理, 包括三个阶段:
⭐⭐ 初始化阶段 1 2 3 4 5 6 7 8 9 public class MyServlet extends HttpServlet { @Override public void init (ServletConfig config) throws ServletException { super .init(config); System.out.println("Servlet 初始化" ); } }
⭐⭐ 服务阶段 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Override protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8" ); PrintWriter out = response.getWriter(); out.println("<h1>Hello Servlet</h1>" ); } @Override protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8" ); String username = request.getParameter("username" ); }
⭐⭐ 销毁阶段 1 2 3 4 5 @Override public void destroy () { System.out.println("Servlet 销毁" ); }
Servlet 配置 ⭐⭐ web.xml 配置( 传统方式) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <servlet > <servlet-name > MyServlet</servlet-name > <servlet-class > com.example.MyServlet</servlet-class > <init-param > <param-name > encoding</param-name > <param-value > UTF-8</param-value > </init-param > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > MyServlet</servlet-name > <url-pattern > /hello</url-pattern > </servlet-mapping >
⭐⭐ 注解配置( 推荐) 1 2 3 4 5 6 7 8 9 10 11 @WebServlet( name = "MyServlet", urlPatterns = "/hello", loadOnStartup = 1, initParams = { @WebInitParam(name = "encoding", value = "UTF-8") } ) public class MyServlet extends HttpServlet { }
HttpServletRequest HttpServletRequest 对象封装了客户端发送的 HTTP 请求信息。
获取请求参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 String username = request.getParameter("username" );String password = request.getParameter("password" );String[] hobbies = request.getParameterValues("hobby" ); Enumeration<String> paramNames = request.getParameterNames(); while (paramNames.hasMoreElements()) { String name = paramNames.nextElement(); String value = request.getParameter(name); } BufferedReader reader = request.getReader();StringBuilder sb = new StringBuilder ();String line; while ((line = reader.readLine()) != null ) { sb.append(line); } String jsonBody = sb.toString();
获取请求头 1 2 3 4 5 6 7 8 9 10 String userAgent = request.getHeader("User-Agent" );String contentType = request.getHeader("Content-Type" );Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String name = headerNames.nextElement(); String value = request.getHeader(name); }
获取其他信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 String method = request.getMethod(); String uri = request.getRequestURI(); StringBuffer url = request.getRequestURL(); String queryString = request.getQueryString(); String ip = request.getRemoteAddr();String contextPath = request.getContextPath();
HttpServletResponse HttpServletResponse 对象用于向客户端发送 HTTP 响应。
设置响应头 1 2 3 4 5 6 7 8 9 10 11 12 13 14 response.setContentType("text/html;charset=utf-8" ); response.setContentType("application/json;charset=utf-8" ); response.setHeader("Cache-Control" , "no-cache" ); response.setHeader("Access-Control-Allow-Origin" , "*" ); Cookie cookie = new Cookie ("sessionId" , "abc123" );response.addCookie(cookie); response.sendRedirect("/login" );
输出响应内容 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 PrintWriter out = response.getWriter();out.println("<h1>Hello World</h1>" ); response.setContentType("application/json;charset=utf-8" ); PrintWriter out = response.getWriter();out.println("{\"code\":200,\"message\":\"success\"}" ); ServletOutputStream outputStream = response.getOutputStream();FileInputStream fis = new FileInputStream (file);byte [] buffer = new byte [1024 ];int len;while ((len = fis.read(buffer)) != -1 ) { outputStream.write(buffer, 0 , len); } fis.close(); outputStream.flush();
状态码 1 2 3 4 response.setStatus(200 ); response.setStatus(404 ); response.sendError(404 , "页面不存在" );
JSP 技术 JSP 简介 JSP( JavaServer Pages) 是一种动态网页技术, 允许在 HTML 中嵌入 Java 代码。 虽然现在前后端分离架构中 JSP 使用较少, 但理解 JSP 有助于深入理解 JavaWeb。
JSP 执行原理 1 2 3 4 5 1. 客户端请求 JSP 页面 2. JSP 引擎将 JSP 翻译成 Servlet 源代码 3. 编译 Servlet 为 class 文件 4. 加载并执行 Servlet 5. 生成 HTML 响应返回给客户端
JSP 基本语法 ⭐⭐ JSP 表达式 1 2 3 <!-- 输出变量值 --> <p>用户名: <%= username %></p> <p>当前时间: <%= new java .util.Date() %></p>
⭐⭐ JSP 脚本片段 1 2 3 4 5 6 7 8 9 <% String name = request.getParameter("name" ); if (name != null ) { out.println("你好, " + name); } else { out.println("请输入姓名" ); } %>
⭐⭐ JSP 声明 1 2 3 4 5 6 7 8 <%! private int count = 0 ; public int getCount () { return ++count; } %>
⭐⭐ JSP 指令 1 2 3 4 5 6 7 8 <!-- page 指令 --> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <!-- include 指令 --> <%@ include file="header.jsp" %> <!-- taglib 指令 --> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
JSP 内置对象 JSP 提供了 9 个内置对象, 无需声明即可直接使用。
对象
类型
说明
request
HttpServletRequest
请求对象
response
HttpServletResponse
响应对象
session
HttpSession
会话对象
application
ServletContext
应用上下文
out
JspWriter
输出流
pageContext
PageContext
页面上下文
config
ServletConfig
配置对象
page
Object
当前页面对象( this)
exception
Throwable
异常对象( 仅在错误页面可用)
JSTL 与 EL 表达式 EL 表达式 EL( Expression Language) 简化了 JSP 中的数据访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <!-- 访问作用域中的属性 --> ${username} ${user.name} ${user.address.city} <!-- 运算 --> ${1 + 2 } ${a > b ? "大于" : "小于" } <!-- 隐式对象 --> ${param.username} <!-- 请求参数 --> ${header.User-Agent} <!-- 请求头 --> ${cookie.sessionId.value} <!-- Cookie --> ${sessionScope.user} <!-- Session 属性 --> ${requestScope.message} <!-- Request 属性 -->
JSTL 标签库 JSTL( JSP Standard Tag Library) 提供了常用的标签, 减少 JSP 中的 Java 代码。
⭐⭐ 核心标签 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!-- 条件判断 --> <c:if test="${user.age >= 18}" > <p>成年人</p> </c:if > <c:choose> <c:when test="${score >= 90}" >优秀</c:when> <c:when test="${score >= 60}" >及格</c:when> <c:otherwise>不及格</c:otherwise> </c:choose> <!-- 循环遍历 --> <c:forEach items="${userList}" var ="user" varStatus="status" > <p>${status.index + 1 }. ${user.name} - ${user.age}</p> </c:forEach> <!-- 设置变量 --> <c:set var ="count" value="0" scope="session" /> <!-- 移除变量 --> <c:remove var ="count" /> <!-- URL 处理 --> <c:url value="/user/detail" var ="url" > <c:param name="id" value="${user.id}" /> </c:url> <a href="${url}" >详情</a>
⭐⭐ 格式化标签 1 2 3 4 5 6 7 8 9 10 <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <!-- 日期格式化 --> <fmt:formatDate value="${user.createTime}" pattern="yyyy-MM-dd HH:mm:ss" /> <!-- 数字格式化 --> <fmt:formatNumber value="${price}" pattern="#,##0.00" /> <!-- 国际化 --> <fmt:message key="welcome.message" />
Filter 与 Listener Filter( 过滤器) Filter 用于在请求到达 Servlet 之前或响应返回客户端之前进行预处理或后处理。
Filter 生命周期 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @WebFilter("/*") public class EncodingFilter implements Filter { @Override public void init (FilterConfig filterConfig) throws ServletException { } @Override public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("UTF-8" ); response.setCharacterEncoding("UTF-8" ); chain.doFilter(request, response); } @Override public void destroy () { } }
常见应用场景
字符编码统一处理
登录权限验证
XSS 攻击防护
敏感词过滤
请求日志记录
GZIP 压缩
Filter 链 多个 Filter 可以组成一个 Filter 链, 按照配置顺序依次执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <filter > <filter-name > EncodingFilter</filter-name > <filter-class > com.example.EncodingFilter</filter-class > </filter > <filter > <filter-name > AuthFilter</filter-name > <filter-class > com.example.AuthFilter</filter-class > </filter > <filter-mapping > <filter-name > EncodingFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > <filter-mapping > <filter-name > AuthFilter</filter-name > <url-pattern > /admin/*</url-pattern > </filter-mapping >
Listener( 监听器) Listener 用于监听 Web 应用中的各种事件, 如上下文创建、 Session 创建、 属性变化等。
常见监听器 ⭐⭐ ServletContextListener 监听应用启动和关闭。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @WebListener public class AppListener implements ServletContextListener { @Override public void contextInitialized (ServletContextEvent sce) { System.out.println("应用启动" ); } @Override public void contextDestroyed (ServletContextEvent sce) { System.out.println("应用关闭" ); } }
⭐⭐ HttpSessionListener 监听 Session 创建和销毁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @WebListener public class SessionListener implements HttpSessionListener { @Override public void sessionCreated (HttpSessionEvent se) { System.out.println("Session 创建: " + se.getSession().getId()); } @Override public void sessionDestroyed (HttpSessionEvent se) { System.out.println("Session 销毁: " + se.getSession().getId()); } }
⭐⭐ ServletRequestListener 监听请求创建和销毁。
1 2 3 4 5 6 7 8 9 10 11 12 13 @WebListener public class RequestListener implements ServletRequestListener { @Override public void requestInitialized (ServletRequestEvent sre) { } @Override public void requestDestroyed (ServletRequestEvent sre) { } }
Spring MVC Spring MVC 简介 Spring MVC 是 Spring 框架提供的 Web 层框架, 基于 MVC 设计模式, 实现了请求处理的解耦。
MVC 架构
层次
职责
示例
Model( 模型)
业务逻辑和数据
Service、 DAO、 Entity
View( 视图)
数据展示
JSP、 Thymeleaf、 JSON
Controller( 控制器)
请求处理和路由
@Controller 类
工作流程 1 2 3 4 5 6 1. 客户端发送请求 2. DispatcherServlet 接收请求 3. HandlerMapping 找到对应的 Controller 4. Controller 处理业务, 返回 ModelAndView 5. ViewResolver 解析视图 6. 渲染视图并返回响应
Controller 基本用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 @Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @GetMapping("/list") public String list (Model model) { List<User> users = userService.findAll(); model.addAttribute("users" , users); return "user/list" ; } @GetMapping("/{id}") public String detail (@PathVariable Integer id, Model model) { User user = userService.findById(id); model.addAttribute("user" , user); return "user/detail" ; } @PostMapping("/add") public String add (User user) { userService.save(user); return "redirect:/user/list" ; } @PostMapping("/update") public String update (User user) { userService.update(user); return "redirect:/user/list" ; } @GetMapping("/delete/{id}") public String delete (@PathVariable Integer id) { userService.delete(id); return "redirect:/user/list" ; } }
RESTful API 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 @RestController @RequestMapping("/api/user") public class UserApiController { @Autowired private UserService userService; @GetMapping public ResponseEntity<List<User>> list () { List<User> users = userService.findAll(); return ResponseEntity.ok(users); } @GetMapping("/{id}") public ResponseEntity<User> detail (@PathVariable Integer id) { User user = userService.findById(id); return ResponseEntity.ok(user); } @PostMapping public ResponseEntity<User> add (@RequestBody User user) { userService.save(user); return ResponseEntity.status(HttpStatus.CREATED).body(user); } @PutMapping("/{id}") public ResponseEntity<Void> update (@PathVariable Integer id, @RequestBody User user) { user.setId(id); userService.update(user); return ResponseEntity.noContent().build(); } @DeleteMapping("/{id}") public ResponseEntity<Void> delete (@PathVariable Integer id) { userService.delete(id); return ResponseEntity.noContent().build(); } }
参数绑定 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @GetMapping("/search") public String search ( @RequestParam String keyword, @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int size, @RequestParam(required = false) String sort, Model model ) { List<User> users = userService.search(keyword, page, size, sort); model.addAttribute("users" , users); return "user/list" ; } @PostMapping("/upload") public String upload ( @RequestParam("file") MultipartFile file, @RequestParam String description ) { if (!file.isEmpty()) { } return "success" ; }
数据验证 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @PostMapping("/add") public String add (@Valid User user, BindingResult result, Model model) { if (result.hasErrors()) { model.addAttribute("errors" , result.getAllErrors()); return "user/form" ; } userService.save(user); return "redirect:/user/list" ; } public class User { @NotBlank(message = "用户名不能为空") @Size(min = 2, max = 20, message = "用户名长度必须在2-20之间") private String username; @Email(message = "邮箱格式不正确") private String email; @Min(value = 18, message = "年龄必须大于等于18") @Max(value = 100, message = "年龄必须小于等于100") private Integer age; }
拦截器 拦截器类似于 Filter, 但更加灵活, 可以针对特定的 Controller 或方法。
自定义拦截器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @Component public class AuthInterceptor implements HandlerInterceptor { @Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); User user = (User) session.getAttribute("user" ); if (user == null ) { response.sendRedirect("/login" ); return false ; } return true ; } @Override public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
配置拦截器 1 2 3 4 5 6 7 8 9 10 11 12 13 @Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private AuthInterceptor authInterceptor; @Override public void addInterceptors (InterceptorRegistry registry) { registry.addInterceptor(authInterceptor) .addPathPatterns("/admin/**" ) .excludePathPatterns("/admin/login" ); } }
Spring Boot Spring Boot 简介 Spring Boot 基于”约定优于配置”的理念, 简化了 Spring 应用的初始搭建和开发过程。
核心特性
自动配置: 根据 classpath 中的依赖自动配置 Spring 应用
起步依赖: 提供一组便捷的依赖描述符
内嵌服务器: 内置 Tomcat、 Jetty 或 Undertow, 无需部署 WAR 文件
生产就绪: 提供监控、 健康检查、 外部化配置等功能
无代码生成: 不需要 XML 配置或代码生成
快速开始 项目结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 myproject/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/example/myproject/ │ │ │ ├── MyProjectApplication.java # 启动类 │ │ │ ├── controller/ # 控制器 │ │ │ ├── service/ # 业务层 │ │ │ ├── mapper/ # 数据访问层 │ │ │ ├── entity/ # 实体类 │ │ │ └── config/ # 配置类 │ │ └── resources/ │ │ ├── application.yml # 配置文件 │ │ ├── static/ # 静态资源 │ │ └── templates/ # 模板文件 │ └── test/ └── pom.xml
启动类 1 2 3 4 5 6 7 @SpringBootApplication public class MyProjectApplication { public static void main (String[] args) { SpringApplication.run(MyProjectApplication.class, args); } }
配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 server: port: 8080 servlet: context-path: /api spring: datasource: url: jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.entity configuration: map-underscore-to-camel-case: true
常用注解
注解
作用
示例
@SpringBootApplication
标记启动类
主类上使用
@RestController
RESTful 控制器
@RestController
@RequestMapping
请求映射
@RequestMapping("/user")
@GetMapping
GET 请求映射
@GetMapping("/list")
@PostMapping
POST 请求映射
@PostMapping("/add")
@PutMapping
PUT 请求映射
@PutMapping("/{id}")
@DeleteMapping
DELETE 请求映射
@DeleteMapping("/{id}")
@RequestBody
绑定请求体
@RequestBody User user
@PathVariable
绑定路径变量
@PathVariable Integer id
@RequestParam
绑定请求参数
@RequestParam String name
@Autowired
依赖注入
@Autowired UserService userService
@Service
服务层组件
@Service
@Repository
数据访问层组件
@Repository
@Configuration
配置类
@Configuration
@Bean
定义 Bean
@Bean public DataSource dataSource()
最佳实践 项目结构规范 1 2 3 4 5 6 7 8 9 10 11 12 13 14 com.example.project/ ├── common/ # 通用模块 │ ├── constant/ # 常量定义 │ ├── exception/ # 异常定义 │ ├── result/ # 统一返回结果 │ └── utils/ # 工具类 ├── config/ # 配置类 ├── controller/ # 控制层 ├── service/ # 业务层 │ ├── impl/ # 业务实现 │ └── dto/ # 数据传输对象 ├── mapper/ # 数据访问层 ├── entity/ # 实体类 └── ProjectApplication.java # 启动类
统一返回结果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Data @AllArgsConstructor @NoArgsConstructor public class Result <T> { private Integer code; private String message; private T data; public static <T> Result<T> success (T data) { return new Result <>(200 , "success" , data); } public static <T> Result<T> error (Integer code, String message) { return new Result <>(code, message, null ); } }
全局异常处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(BusinessException.class) public Result<Void> handleBusinessException (BusinessException e) { return Result.error(e.getCode(), e.getMessage()); } @ExceptionHandler(Exception.class) public Result<Void> handleException (Exception e) { log.error("系统异常" , e); return Result.error(500 , "系统异常, 请联系管理员" ); } }
日志规范 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Slf4j @Service public class UserService { public User findById (Integer id) { log.info("查询用户, ID: {}" , id); try { User user = userMapper.findById(id); log.debug("查询结果: {}" , user); return user; } catch (Exception e) { log.error("查询用户失败, ID: {}" , id, e); throw new BusinessException ("查询用户失败" ); } } }
常见问题 中文乱码问题 1 2 3 4 5 6 7 8 9 问题: 请求或响应中的中文显示为乱码 解决方案: 1. 配置过滤器统一编码 2. Spring Boot 配置: server.servlet.encoding.charset=UTF-8 server.servlet.encoding.enabled=true server.servlet.encoding.force=true 3. 数据库连接 URL 添加: characterEncoding=utf8
跨域问题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 问题: 前端访问后端接口时出现 CORS 错误 解决方案: 1. 使用 @CrossOrigin 注解 @CrossOrigin(origins = "*") 2. 配置全局跨域 @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("*"); } }
报错处理 💗💗 404 Not Found 1 2 3 4 5 6 7 8 9 10 11 12 错误信息: Whitelabel Error Page - This application has no explicit mapping for /error 错误原因: 1. 请求路径错误 2. Controller 未正确配置 3. 包扫描范围不对 解决方案: 1. 检查 @RequestMapping 路径 2. 确认 Controller 类上有 @Controller 或 @RestController 3. 确保 Controller 在启动类的子包下
💗💗 500 Internal Server Error 1 2 3 4 5 6 7 8 9 10 11 12 错误信息: There was an unexpected error (type=Internal Server Error, status=500) 错误原因: 1. 代码逻辑错误 2. 数据库连接失败 3. 依赖注入失败 解决方案: 1. 查看控制台日志定位具体错误 2. 检查数据库配置和连接 3. 确认 @Autowired 注入的 Bean 存在
💗💗 Bean 注入失败 1 2 3 4 5 6 7 8 9 10 11 12 错误信息: Field xxx required a bean of type 'xxx' that could not be found 错误原因: 1. 缺少 @Component、 @Service 等注解 2. 包扫描范围不包含该类 3. 循环依赖 解决方案: 1. 添加相应的组件注解 2. 调整 @ComponentScan 范围 3. 使用 @Lazy 解决循环依赖
学习资源
视频
尚硅谷 JavaWeb 教程: https://www.bilibili.com/video/BV1UN411x7xe
官方文档
Spring 官方文档: https://spring.io/projects/spring-framework
Spring Boot 官方文档: https://spring.io/projects/spring-boot
Jakarta EE 规范: https://jakarta.ee/specifications/
书籍
《 深入理解 Java Web》 : 杨开振著
《 Spring Boot 实战》 : Craig Walls 著
《 Spring 揭秘》 : 王福强著
教程
Spring 官方指南: https://spring.io/guides
Baeldung Spring 教程: https://www.baeldung.com/category/spring/
工具
Postman: API 测试工具
Swagger/OpenAPI: API 文档生成
JMeter: 压力测试工具
社区
Stack Overflow: https://stackoverflow.com/questions/tagged/spring
Spring 中文社区: https://spring.io/projects