最近刚把一个基于 JavaWeb 的老项目翻新了一遍,发现好多人对 Ajax 在 JavaWeb 里的用法还停留在“复制粘贴能用就行”的阶段。一旦遇到参数乱码、请求格式不对、后端返回的数据前端解析不了这些问题,就卡住了。这篇我就拿一个真实的 JavaWeb 项目作为例子,把 Ajax 从最基础的原生写法到参数传递、编码格式处理、JSON 数据交互、常见问题排查,完整走一遍。内容不挑基础,刚学 JavaWeb 的新人能照着做,写过几年项目的老手也能从里面的细节里捡回一些容易忽略的东西。
1. Ajax 在 JavaWeb 项目中的角色定位
1.1 为什么 JavaWeb 开发离不开 Ajax
先看清楚一个事实:Ajax 并不是某种新技术框架,它本质上就是浏览器内置 XMLHttpRequest 对象提供的一组 API。JavaWeb 的服务端跑的是 Servlet、Filter、JSP 这一套,而页面上的 JavaScript 通过 Ajax 发请求到后端接口,拿到结果后再动态更新页面内容,这套搭配决定了 Ajax 在 JavaWeb 项目里几乎无处不在。
不用 Ajax 的传统方式,就是用户点一个按钮,整个表单提交给服务器,服务器处理完返回一个新的 JSP 页面让浏览器重新渲染。这个过程最让人难受的就是每次都要刷新整个页面,用户填到一半的信息、滚动的位置、页面状态全部没了。Ajax 打破了这个模式,它只向服务器发送需要的请求参数,服务器返回一段纯数据(通常是 JSON 字符串),由前端 JavaScript 解析后局部更新页面中的某一块区域。用户的视觉体验是“页面没有跳转,但数据已经变了”。
从技术分工上看,这正好对应了 JavaWeb 后端和前端 JavaScript 各自的职责边界。后端只负责封装业务逻辑、访问 MySQL 数据库、返回一个标准的 JSON 结果,前端负责收集用户输入、构造请求、解析响应、渲染页面。界限清晰之后,前后端可以并行开发,后端把接口定好,前端拿 mock 数据先跑页面,这也是现在团队协作效率高的原因之一。
1.2 同步请求和异步请求的本质区别
很多初学者会混淆“页面不刷新”和“异步”这两个概念。Ajax 确实可以让页面不刷新,但不代表只要用了 XMLHttpRequest 就一定是异步。XMLHttpRequest 的 open 方法第三个参数可以传 true 或 false,true 表示异步,false 表示同步。
同步请求发出之后,浏览器 JavaScript 引擎会被阻塞在那里等待服务器的响应,期间用户什么都做不了,页面像是卡死了一样。如果网络慢一点,整个页面就僵住了,体验极差。异步请求发出之后,浏览器会立刻返回继续执行后面的代码,真正等响应回来之后再通过回调函数处理结果,用户界面始终是流畅的。
在 JavaWeb 项目里几乎都应该用异步模式。唯一可以考虑同步的场景,是某些业务操作必须依赖接口返回结果才能决定下一步动作,而且操作本身非常快,比如判断用户是否已经登录。即便如此,我仍然建议尽量用异步加回调的方式来处理,把后续逻辑放到回调函数里,而不是依赖同步阻塞。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 开发环境搭建:从 IDEA 到 Tomcat
2.1 新版 IDEA 创建 JavaWeb 项目的关键配置
先说说环境,现在主流的开发工具依旧是 IntelliJ IDEA,如果你用的是 2023 版本及更新的版本,创建 JavaWeb 项目的流程和老版本相比有一些变化,这里值得单独讲清楚。
打开 IDEA 之后,选择 File -> New -> Project。在左侧项目类型里定位到 Jakarta EE 这个分类。里面可以选 Web Application 作为模板,这里要注意,现在的 IDEA 版本默认用的是 Jakarta EE 规范,命名空间是 jakarta.servlet 开头,而不是老项目里常见的 javax.servlet。如果你的项目最终要放到老版本 Tomcat 8 及以下去运行,需要调整为对应版本,否则编译都过不了。选好之后,Build Tool 可以保持默认的 Maven,这样后面引入依赖(比如 MySQL 驱动、JSON 处理库)会方便很多。
项目创建完成后,右键项目根目录,选择 Add Framework Support,确认 Web 模块是否已经添加进去。如果看不到 Web 选项,说明项目类型创建得不对,可以手动在 WEB-INF 目录下补一个 web.xml 文件来标识这是个 Web 应用。IDEA 2023 版本对 Maven 的集成非常友好,pom.xml 里加依赖、刷新项目、打包 war 包,这些操作都比老版本顺手很多。但在配置 Artifact 时要注意一点,IDEA 自动生成的 Artifact 输出的类型是 war exploded(解压目录),这是开发模式下的测试用配置,后面如果要发布到服务器上,记得单独执行 Maven package 打成标准 war 包,再用 Tomcat 去部署。
2.2 配置 Tomcat 运行环境的经验之谈
开发模式下,IDEA 内置支持配置 Tomcat 启动项目,不需要手动去 Apache Tomcat 安装目录里复制 war 包。操作路径是 Run -> Edit Configurations,点击左上角加号,找到 Tomcat Server -> Local。在 Application Server 那里点击 Configure,选择你本机的 Tomcat 安装目录,IDEA 会自动识别版本号。Deployment 标签页里点加号,把 Artifact 添加进去,Application Context 建议设置成 /,这样本地访问的时候就无需输入多余的项目路径前缀。
跑起来之后访问地址就是 http://localhost:8080/。如果端口冲突,可以在 Server 标签页的 HTTP port 里改,比如改成 8081,但要注意端口改了之后,前端 Ajax 请求的地址也要跟着改。我这里有个实操经验,本地调试时我习惯用随机端口启动,因为 8080 经常被其他程序占用,但发布到正式环境时统一使用 80 端口配合 Apache 转发,这样用户访问时不需要带端口号,体验更好。
环境准备好之后,下一步就要开始写代码了。Ajax 部分的代码主要分两块:前端的 JavaScript 代码写在 JSP 页面或静态 HTML 页面里,后端的接收逻辑写在 Servlet 里。
3. 原生 Ajax 请求的完整实现流程
3.1 从零封装一个可复用的 XMLHttpRequest 对象
虽然现在很多人用 JQuery 的 $.ajax 或者 axios 库,但我觉得做 JavaWeb 项目的人还是应该先掌握原生写法。原生的好处是让你知道请求到底是怎么发出去的,遇到问题能快速定位是在哪一层出的错。而且老项目里经常能看到原生 XMLHttpRequest 的代码,真要去维护的时候不至于懵。
先写一个最基础的创建 XMLHttpRequest 对象的方法。现代浏览器都支持 new XMLHttpRequest(),但考虑到某些企业内部系统可能还跑着老版本 IE(不要笑,生产环境真的有),最好加一段兼容判断。
javascript复制function createXHR() {
if (typeof XMLHttpRequest !== "undefined") {
return new XMLHttpRequest();
}
// 兼容老版本 IE 的写法,了解一下就行
if (typeof ActiveXObject !== "undefined") {
return new ActiveXObject("Micros
