核心方法:检查 X-Requested-With 请求头
这是目前最通用、最标准的判断方法,绝大多数现代的 JavaScript 框架(如 jQuery、axios、fetch)在发送 AJAX 请求时,都会自动添加一个 X-Requested-With: XMLHttpRequest 的请求头。

在原生 Servlet 中判断
如果你使用的是原生的 Java Servlet,可以通过 HttpServletRequest 对象的 getHeader() 方法来检查。
import javax.servlet.http.HttpServletRequest;
public class AjaxUtils {
// 定义一个常量,避免硬编码,方便维护
public static final String AJAX_HEADER = "X-Requested-With";
public static boolean isAjaxRequest(HttpServletRequest request) {
// 获取请求头
String requestedWith = request.getHeader(AJAX_HEADER);
// 如果请求头不为空,且值为 XMLHttpRequest,则认为是 AJAX 请求
return "XMLHttpRequest".equals(requestedWith);
}
}
如何使用:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/api/data")
public class DataServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (AjaxUtils.isAjaxRequest(req)) {
// 是 AJAX 请求,返回 JSON 数据
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
resp.getWriter().write("{\"message\": \"这是从 AJAX 请求返回的数据\"}");
} else {
// 不是 AJAX 请求(比如是普通的页面跳转),返回 HTML 或重定向
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
resp.getWriter().write("<h1>这是一个普通请求</h1>");
}
}
}
在 Spring MVC 中判断
Spring MVC 提供了更便捷的方式来处理这个问题,推荐使用 @RequestMapping 的 produces 属性。
使用 produces 属性(推荐)

这种方式更符合 RESTful 风格,它直接定义了该接口能返回的响应内容类型,前端 AJAX 请求通常期望接收 JSON,而普通请求期望接收 HTML。
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
@RestController // @RestController 中的所有方法默认都返回 JSON,相当于都加了 @ResponseBody
public class MyAjaxController {
// 这个方法会处理 AJAX 请求
@GetMapping(value = "/api/user", produces = "application/json")
public User getUserForAjax() {
User user = new User("张三", 30);
return user; // Spring MVC 会自动将对象序列化为 JSON 并返回
}
// 这个方法会处理普通请求,返回一个视图名
@GetMapping("/page/user")
public ModelAndView getUserPage() {
ModelAndView mav = new ModelAndView("userPage"); // 返回一个 HTML 页面
mav.addObject("username", "李四");
return mav;
}
}
// 一个简单的 POJO
class User {
private String name;
private int age;
// ... 构造器、getter 和 setter
}
手动检查请求头
如果你仍然想手动检查,可以通过 HttpServletRequest 参数。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
public class ManualCheckController {
@GetMapping("/api/manual-check")
public String check(HttpServletRequest request) {
if (AjaxUtils.isAjaxRequest(request)) {
return "这是一个 AJAX 请求的响应";
} else {
return "这是一个普通请求的响应";
}
}
}
其他方法(作为补充)
虽然 X-Requested-With 是最主流的,但在某些特定场景下,你也可以使用其他方法。
检查 Accept 请求头
AJAX 请求通常会在 Accept 头中声明它期望接收的数据类型,application/json 或 application/xml,而浏览器直接请求时,Accept 头会包含 text/html。
public static boolean isAjaxRequestByAccept(HttpServletRequest request) {
String acceptHeader = request.getHeader("Accept");
// Accept 头中包含 application/json,则很可能是 AJAX 请求
return acceptHeader != null && acceptHeader.contains("application/json");
}
注意: 这种方法不如 X-Requested-With 可靠,因为一个普通请求也可能要求接收 JSON 数据,但它可以作为一个辅助判断的依据。
检查 Content-Type 请求头
这个方法适用于 POST/PUT 请求,AJAX 请求在发送数据(如 JSON、Form Data)时,会设置 Content-Type。
- 发送 JSON 数据:
Content-Type: application/json - 发送表单数据:
Content-Type: application/x-www-form-urlencoded
public static boolean isAjaxRequestByContentType(HttpServletRequest request) {
String contentType = request.getContentType();
// Content-Type 是 application/json,则认为是 AJAX 请求
return contentType != null && contentType.contains("application/json");
}
注意: 这个方法不适用于 GET 请求,因为 GET 请求没有请求体,也就没有 Content-Type,它只能作为 POST/PUT 请求的辅助判断。
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
检查 X-Requested-With |
最标准、最可靠,被所有主流 JS 框架支持 | 某些老旧的 AJAX 库或自定义脚本可能不包含此头 | 所有场景下的首选和推荐方法 |
检查 Accept 头 |
可以判断期望的响应格式 | 可靠性较低,普通请求也可能要求 JSON | 作为辅助判断,或在无法控制请求头时使用 |
检查 Content-Type 头 |
对于 POST/PUT 请求判断准确 | 不适用于 GET 请求,需要手动判断 | 主要用于处理 AJAX 提交的数据,如文件上传 |
最终建议:
- 首选
X-Requested-With:在你的工具类中封装一个isAjaxRequest方法,基于此进行判断,这是最健壮、最通用的方案。 - 在 Spring 中拥抱约定:优先使用 Spring MVC 的
produces属性来区分返回 JSON 还是 HTML,让框架帮你处理大部分逻辑,代码更清晰。 - 组合使用:在非常复杂的场景下,可以结合
X-Requested-With和Accept/Content-Type进行更精确的判断,但通常没有必要。
前端示例(jQuery)
为了让你更完整地理解,这里给出一个使用 jQuery 发送 AJAX 请求的例子,你会看到它确实会带上 X-Requested-With 头。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">AJAX 请求示例</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<h1>测试 AJAX 请求</h1>
<button id="ajaxBtn">发送 AJAX 请求</button>
<button id="normalBtn">发送普通请求</button>
<div id="result"></div>
<script>
$(document).ready(function() {
// 使用 jQuery 发送 AJAX 请求
$("#ajaxBtn").click(function() {
$.ajax({
url: "/api/data",
type: "GET",
success: function(response) {
$("#result").html("<pre>" + JSON.stringify(response, null, 2) + "</pre>");
},
error: function() {
$("#result").text("请求失败");
}
});
});
// 发送普通请求(页面跳转或刷新)
$("#normalBtn").click(function() {
window.location.href = "/page/user"; // 假设这个路径处理普通请求
});
});
</script>
</body>
</html>
当你点击“发送 AJAX 请求”按钮时,浏览器的开发者工具(Network 标签页)中会看到对 /api/data 的请求,其请求头中包含了 X-Requested-With: XMLHttpRequest,而点击“发送普通请求”则没有,这就是后端能够区分它们的依据。
