很多刚学完 Java SE 的朋友跑来问我:Java Web 到底是什么?在他们眼里,Java 就是写控制台程序、Swing 窗口、算法题用的,突然听说还要学 Tomcat、Servlet、Spring Boot,整个人就愣住了。我当年也一样,抱着《Java Web 程序设计》教材,对着一个 Hello World 想了半天:这玩意儿跟public static void main(String[] args)到底有什么关系?
这篇文章就是为这种状态准备的。我会从 Java Web 最核心的概念讲起,不堆术语,把一个请求从浏览器走到数据库再回来的完整链路拆开,然后带你手动创建一个能跑的 Java Web 项目。同时把 Servlet、JSP、Filter、Session 这些老地基讲清楚,再说说为什么现在企业开发都转向 Spring Boot,最后附上安全、面试、避坑的实战经验。无论你是刚入门的 Java 学习者,还是准备跳槽的初级开发,第一章的这些东西都值得你花一晚上好好消化。
1. Java Web 不是“Java”加“Web”这么简单
1.1 你写的 Java 程序到底跑在哪里
搞清楚这个,后面所有技术都不糊涂。
普通 JavaSE 程序跑在本地电脑的 JVM 里,main方法启动,从上往下执行,执行完就退出。Java Web 程序则跑在一台服务器上——可能是云主机、物理机,也可能就是你自己的电脑。但它不是“主动执行”的,而是“被动等请求”:浏览器发来一个 HTTP 请求,Web 服务器接受请求,转交给对应的 Java 代码处理,处理完返回一段 HTML 或 JSON,浏览器再渲染成页面。这个“服务器 + 容器 + 后台代码 + 数据库”的组合,才是完整的 Java Web。
很多新手最大的误区,是以为写 Web 程序就是写网页。其实 Java Web 的核心是写“服务器端逻辑”,页面只是最终呈现的一部分。早期 JSP 允许在页面里写 Java 代码,给人造成了“Java Web 就是写页面”的错觉,后来这种写法坑惨了一代人。现在的主流做法是后端只提供数据接口,页面交给 Vue、React 这类前端框架处理。
1.2 一条主线贯穿所有 Java Web 技术
不管是 Servlet 还是 Spring Boot,核心链路永远是这样:
浏览器发起 HTTP 请求 -> Web 服务器(如 Tomcat)定位到处理类 -> 调用业务层 -> 操作数据库 -> 把结果封装成响应 -> 返回浏览器渲染。
这条线就是 Java Web 的骨架。Servlet 是最原始的处理类,JSP 是模板引擎,Spring MVC 是更高级的 Servlet 封装,Spring Boot 则把前面这些组装变成了自动化配置。你学的时候只要时刻问自己“我现在学的东西在这条链路的哪个位置”,就不会迷失方向。
1.3 为什么 Java 在 Web 领域能活这么多年
你看看招聘网站上的 Java 岗位就知道,Java Web 在电商、金融、政务、企业 ERP 这些领域里存量非常大。为什么大家都用它?原因很现实:Java 跨平台能力强,强类型体系让大型项目更好维护,生态里围绕 Java 的中间件——比如消息队列、搜索服务、分布式协调工具——几乎都能用 Java 客户端操作。再加上大量存量系统跑在 Java 上,新项目为了对接老系统,继续选 Java 也很自然。
虽然有人抱怨 Java 太重,但“重”往往也意味着稳定、有规范。新手学 Java Web 绝对不是白学,这套“请求、响应、容器、框架、持久化”的思想,换到其他语言同样通用。这也是我建议你认真对待第一章的原因:地基打不牢,后面盖多少层楼都心虚。
2. 环境准备:版本、IDE、构建工具和服务器怎么选
2.1 JDK 版本:别一上来就装最新版
很多新手直接装最新 JDK,结果和 IDE、框架版本不兼容,莫名其妙报一堆错。我的建议是:
- 新手学习优先选 JDK 17 或 JDK 21,都是长期支持版本,生态兼容性好。
- 如果之后要接手老项目,JDK 8 依然很常见,很多 Spring Boot 2.x 和 SSM 项目都跑在 8 上。
- 不要安装 alpha、beta 或非 LTS 版本,除非你真的想折腾。
安装后记得配置JAVA_HOME环境变量,把bin目录加入PATH,然后在命令行敲java -version验证。只要能看到版本号,第一步就过了。
2.2 IDE:IDEA 2024 社区版够用吗
IDEA 社区版完全支持 Java、Maven、Tomcat 配置,学习用足够了。但要注意:社区版的 New Project 模板里,Web 项目的向导没有旗舰版全。我自己的做法是直接用 Maven 骨架创建,后面需要什么目录再手动补,并不影响学习。
如果你有学生身份,可以免费申请 JetBrains 全家桶,旗舰版确实省事。Eclipse 目前只能说是怀旧了,除非公司强制要求,不建议新入坑的人选它。工具选择这件事,不要纠结太久,能用、顺手、有社区教程就行。
2.3 构建工具:先学 Maven,别一上来碰 Gradle
Java Web 项目的依赖管理一定得靠工具,绝不能手动去网上下载 jar 包再拷进项目。Maven 是教科书、面试题、公司老项目最常用的标准,配置文件是pom.xml,通过中央仓库自动下载依赖。
你只需要理解三个东西:groupId(组织标识)、artifactId(项目标识)、version(版本号),这三个坐标定位了一个依赖。构建顺序可以以后再深究,先记住clean、compile、package、install基本够了。Gradle 配置更简洁、构建速度也快,但入门阶段不用急。
2.4 应用服务器:Tomcat 是理解 Java Web 最好的道具
Java Web 程序必须运行在 Web 容器里。Tomcat 是最经典的 Servlet 容器,也是大多数人第一个接触的服务器。有了 Tomcat,你写的 Servlet 才能接住 HTTP 请求。
Spring Boot 内置了 Tomcat,不少人现在根本不直接碰它,但我不建议跳过去。第一章至少要手动把项目部署到 Tomcat 一次,知道 war 包怎么打、应用怎么发布、端口怎么改,后面遇到生产环境的问题才知道从哪下手。
数据库方面,最常用 MySQL。JDBC 是 Java 访问数据库的底层接口,后来出现了连接池(HikariCP、Druid)和 ORM(MyBatis、JPA)。初学者可以先掌握 JDBC 和 MyBatis,再慢慢理解 JPA,这个顺序容错率最高。
3. 手把手:用 IDEA 2024 创建一个能跑的 Java Web 项目
3.1 项目结构:别再傻傻选 Empty Project
IDEA 里新建项目有很多入口。如果你直接点 “New Project” 然后选 Java,生成的是一个普通 Java 模块,根本没有src/main/webapp这种 Web 目录。创建标准 Web 项目,我推荐用 Maven 原型:
在 New Project 弹窗里选择 Maven,勾选 “Create from archetype”,然后选org.apache.maven.archetypes:maven-archetype-webapp。IDEA 会帮你生成带src/main/webapp和WEB-INF的标准目录,这个结构才符合 Web 应用规范。
如果列表里找不到这个 archetype,通常是网络问题。建议先给 Maven 配置阿里云镜像,或者干脆先建普通 Maven 项目,手动补目录:
src/main/java src/main/resources src/main/webapp/WEB-INF反正目录结构是死的,IDE 只是帮你省事。
3.2 pom.xml 里加什么依赖
最简单的 Servlet 项目,只需要引入 Servlet API,并且scope设为provided。因为 Tomcat 本身已经带这些类,打 war 包时不要重复包含。
<dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <scope>provided</scope> </dependency>这里有个大坑:如果你用的 Tomcat 版本是 9.x 及以下,包名是javax.servlet;Tomcat 10 之后才切换成jakarta.servlet。新手经常把 Tomcat 10 配javax的代码,结果编译不过。选择依赖版本前,先确认你的 Tomcat 版本。
3.3 写第一个 Servlet:HTTP 请求是怎么被接住的
在src/main/java下建一个类,继承HttpServlet,重写doGet方法,并用@WebServlet("/hello")注解映射访问路径。Servlet 3.0 以后支持注解,不需要再写web.xml。
import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/hello") public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=UTF-8"); resp.getWriter().write("<h1>Hello Java Web</h1>"); } }这一小段代码背后有三个关键点:
@WebServlet("/hello")决定了访问路径,启动后访问http://localhost:8080/项目上下文/hello。- 浏览器用 GET 请求就会进入
doGet,表单提交用 POST 则进入doPost。 - 响应的内容通过
resp.getWriter()输出,这是最早期的“返回给浏览器”的方式。
3.4 配置 Tomcat 并解决端口问题
点击 IDEA 工具栏的 “Add Configuration”,选择 Tomcat Server -> Local,指定 Tomcat 安装目录。然后在 Deployment 选项卡里选择 war exploded,Application context 可以设为/或/demo。运行后控制台会输出启动日志。
新手最常见的报错就两个:
- 端口被占用:
java.net.BindException: Address already in use。Windows 下用netstat -ano | findstr 8080找到占用进程,结束它,或者改 Tomcat 的端口。 - 404:大概率是 Application context 和访问路径不一致,或者 artifact 没有部署成功。
提示:第一次部署时,IDEA 需要把项目编译打包到指定的输出目录,耐心等它构建完。如果改了代码没生效,试试重新部署而不是只刷新页面。
4. Servlet、JSP、Filter、Listener:绕不开的老地基
很多人觉得“我现在学 Spring Boot,不用管 Servlet 了”,这是误解。Spring MVC 核心的 DispatcherServlet 本身就是一个 Servlet;过滤器、监听器、会话机制到了 Spring Boot 里依然存在,只是换了写法。第一章把地基看明白,后面才不会被概念绕晕。
4.1 Servlet 的完整生命周期
Servlet 从创建到销毁有三个阶段:
init():Servlet 第一次被请求时初始化一次,常用来加载配置。service():每个请求都会执行,doGet和doPost本质是 service 按请求方法分发的。destroy():服务器关闭或应用卸载时执行,释放资源。
面试经常问“Servlet 是单例还是多例”,答案是默认单例多线程。也就是说一个 Servlet 实例会被多个请求同时用,这时候如果成员变量被修改,就会出现线程安全问题。所以不要在 Servlet 里用可变的成员变量存业务数据,这就是并发问题的一个经典考点。
4.2 JSP:曾经的王者,现在你少碰为好
JSP 全称 Java Server Pages,允许在 HTML 中嵌入 Java 代码,容器会把 JSP 编译成 Servlet。早期大量项目用 JSP 做动态页面,比如写<% out.println("hi"); %>。问题是页面和逻辑耦合太深,前端后端没法分离,调试也痛苦。
现在的企业级开发,页面更多交给 Vue/React,后端只返回 JSON 数据,JSP 逐渐退居二线。我建议把 JSP 当历史知识了解一下,能看懂老项目就行,重点放在前后端分离的接口开发模式上。
4.3 Filter 与 Listener:横切逻辑的挂载点
Filter 过滤器可以在请求到达 Servlet 之前做处理,也能在响应返回之前做处理。典型场景:登录校验、统一编码、日志记录。写法是实现Filter接口,在doFilter方法里调用chain.doFilter()放行。
Listener 监听器则用来监听 Web 应用的生命周期事件,比如应用启动关闭、Session 创建销毁、请求到达等。很多框架的启动加载逻辑,就是依赖ServletContextListener完成的。
记住一句话:Filter 是“请求进来前/响应出去前”的拦截点,Listener 是“某个事件发生时”的触发器。面试能把这个区别讲清楚,比背十个概念都管用。
4.4 Cookie 与 Session:登录状态到底怎么维持
HTTP 协议本身是无状态的。服务器怎么知道下一次请求还是同一个人?靠会话机制:
- Cookie:服务器通过响应头下发一段小数据,浏览器保存,后续请求自动带上。
- Session:服务器端保存用户数据,分配一个唯一的 Session ID,通常通过 Cookie 传回。
登录成功后的标准做法是:
HttpSession session = req.getSession(); session.setAttribute("user", user);后续请求从 Session 中取出用户,如果没登录访问受保护资源,就重定向到登录页。Cookie 可以设过期时间,Session 默认在关闭浏览器或超过 30 分钟后失效。
很多实际功能,比如“记住登录状态”“行级权限控制”,底层都依赖会话里保存的用户身份。能把这个机制讲明白,Java Web 的第一章你就掌握了一大半。
5. 从原生 Servlet 到 Spring Boot:企业级 Java Web 的进化逻辑
5.1 一个 Servlet 项目的痛,写三个接口你就懂了
原生 Servlet 适合理解原理,但写多了真的痛苦:
- 每个接口都要手动解析参数、校验、拼 JSON。
- 业务方法里到处
new Service()、new Dao(),对象之间耦合严重。 - 事务控制要手动开启、提交、回滚,漏一步就出错。
- 配置繁琐,代码量大。
于是 Spring 框架出来了。它用 IoC 容器管理对象,你需要什么就声明什么,容器帮你注入;AOP 把事务、日志这些横切逻辑抽离出来。后来 Spring Boot 又把依赖、配置、内嵌服务器全部自动化,才有了现在“几秒钟启动一个 Web 项目”的体验。
5.2 Spring Boot 是如何接管 Web 开发的
用 Spring Initializr 创建项目,引入一个spring-boot-starter-web依赖,它会自动传入 Spring MVC、Tomcat、Jackson 等组件。写接口变成这样:
@RestController @RequestMapping("/api") public class UserController { @GetMapping("/hello") public Map<String, String> hello() { return Map.of("message", "Hello Java Web"); } }不需要打 war 包部署 Tomcat,直接运行main方法,内置 Tomcat 就启动了。Spring Boot 的自动配置会根据 classpath 环境自动装配 Bean。这也是现在“IDEA 创建 Web 项目”更常见的姿势:直接建 Spring Boot 工程,而不是手动配 Servlet。
5.3 Spring MVC 的请求处理路径
理解 Spring MVC,一定抓住 DispatcherServlet 这个核心。所有请求先到达 DispatcherServlet,它再根据 HandlerMapping 找到对应的 Controller 方法,调用后返回数据,异常交给 HandlerExceptionResolver 处理。这套机制本质是“前端控制器模式”。
学习的时候可以对照 Servlet 的生命周期来理解:DispatcherServlet 也继承了 HttpServlet,所以它本质上还是一个 Servlet,只是做了更多分发工作。
5.4 持久层选择:MyBatis 还是 JPA
企业级 Java Web 离不开数据库操作。
MyBatis 的核心是 SQL 映射,灵活可控,国内互联网项目用得多,配合 MyBatis-Plus 效率很高。JPA/Hibernate 是典型 ORM,用对象操作代替 SQL,写起来快但优化空间小。搜索“spring boot + mybatis 开源商城源码”这种东西的人,基本都在用 MyBatis。新人建议先熟练掌握 MyBatis,再了解 JPA,遇到项目要求再补。
6. Web 安全:Java Web 项目上线前必须过的一关
很多教材不讲安全,可是“web 服务器安全”“web 安全”恰恰是生产环境最现实的问题。第一章可以不做深入渗透测试,但是基本的安全意识必须从写第一个接口开始建立。
6.1 最常见的几个漏洞类型
- SQL 注入:用户输入拼接进 SQL,可能导致数据被删。解决:使用
PreparedStatement预编译参数。 - XSS 跨站脚本:用户提交内容未过滤,前端渲染时执行恶意脚本。解决:前端转义,后端对输出做 HTML 编码。
- CSRF 跨站请求伪造:利用用户已登录状态,诱导浏览器发起恶意请求。解决:校验 Referer 或加 CSRF Token。
- 越权漏洞:用户 A 能访问用户 B 的数据。解决:每个请求做权限校验,不只是隐藏按钮。
- 文件上传漏洞:上传恶意脚本获得服务器权限。解决:校验文件后缀、内容类型,存储到专门的对象存储服务。
6.2 登录认证的两种主流方案
- Session + Cookie:服务端保存状态,适合传统 Web 应用;集群环境需要共享 Session。
- JWT(JSON Web Token):客户端保存 token,服务端无状态验证签名,适合前后端分离和分布式场景。但 JWT 无法主动失效,注销要额外处理。
我建议新手先老老实实把 Session + 过滤器的登录校验跑通,再研究 JWT。很多人的问题不是方案不够新,而是连“登录态怎么传递”都没搞清楚就上了 JWT。
6.3 一个简单又完整的后端安全清单
- 数据库连接使用低权限账号,不要把密码写死在代码里,用环境变量或配置中心。
- 日志不要打印密码、手机号、身份证等敏感信息,必须脱敏。
- 接口要做限流,防止暴力破解和恶意刷接口。
- 生产环境必须上 HTTPS,免费证书申请也很快。
- 错误信息不要回传完整堆栈,给前端可读的提示就好。
7. 学习路线、常见报错与面试视角:第一章就能用上的经验
7.1 建议的学习顺序
我根据自己的经验推荐的 Java Web 入门路线是这样的:
- Java SE 基础:语法、集合、IO、多线程、网络基础。
- 数据库基础:SQL、MySQL 基本操作、事务概念。
- Web 前端基础:HTML、CSS、JavaScript、HTTP 协议常识。
- Java Web 基础:Servlet、JSP、Filter、Session。
- 框架提升:Maven -> MyBatis -> Spring -> Spring MVC -> Spring Boot。
- 项目实战:做一个带登录、增删改查、分页的完整小项目。
不要试图跳过 Servlet 直接学 Spring Boot。至少要手动部署一次 Servlet 项目,你才知道 Spring Boot 替你省了多少事。热词里那么多“java 学习路线”“java 入门”“java 开发工程师面试题”的搜索,基本都踩在同一个点上:基础没扎稳就开始追框架。
7.2 我见过的高频报错
ClassNotFoundException: javax.servlet.*:Servlet 依赖没加,或者包名版本不匹配。- 连接 MySQL 时报时区错误:连接串加
serverTimezone=Asia/Shanghai。 Failed to configure a DataSource:引入了 MyBatis 依赖但没配置数据源。OutOfMemoryError:Tomcat 堆内存不够,调整-Xmx参数。- 中文乱码:请求和响应都设置
UTF-8,数据库连接串加characterEncoding=utf8。
这些错误几乎每个新人都遇过,知道解决方法比背概念更值钱。
7.3 面试题视角下的 Java Web 重点
把第一章的内容转化成面试问题,大概是这样的:
- GET 和 POST 有什么区别?幂等性、参数位置、传输大小分别是什么?
- 转发(forward)和重定向(sendRedirect)有什么不同?
- Cookie 和 Session 的区别?禁掉 Cookie 后怎么办?
- Servlet 是线程安全的吗?
- Spring MVC 的执行流程是什么?
- Maven 的生命周期有哪些阶段?
建议每学完一个知识点,就用“能不能给小白讲明白”来检验自己。能说出来,才算真的懂。
我自己带过不少人,最大的体会是:第一章不要急着看完所有框架,而是要把第一条请求链路走通。哪怕只是一个 “Hello Java Web” 的 Servlet,你亲手部署到 Tomcat、看清控制台日志、改一次端口、再配一个过滤器,这比你刷十集视频都有用。多做两个小项目——一个传统 Servlet + JSP 的留言板,一个 Spring Boot + MyBatis 的简单管理系统。前者帮你打底子,后者帮你找工作。做完这两个,Java Web 第一章就算真正过关了。