You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Postman验证后端正常,前端AJAX请求返回HTML致404错误求助

问题描述

AJAX请求期望接收JSON格式响应,但实际获取到HTML,触发404错误。

前后端代码

前端JS代码

function checkCustomersAccount() {
    console.log("checkCustomersAccount called");

    var customersAccountReg = /^[a-zA-Z0-9]{5,10}$/;
    var account = document.getElementById("customersAccountInput").value;
    var customersAccountMsgSpan = document.getElementById("customersAccountMsg");

    if (!customersAccountReg.test(account)) {
        customersAccountMsgSpan.innerText = "格式不符合要求";
        return false;
    }

    var encodedAccount = encodeURIComponent(account);
    var requestUrl = "/customers/checkAccountUsed?account=" + encodedAccount;
    console.log("Request URL:", requestUrl);

    fetch(requestUrl, {
        method: 'GET',
        headers: {
            'Accept': 'application/json'
        }
    })
    .then(response => {
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        return response.json();
    })
    .then(result => {
        console.log("Result:", result);
       
        if (result.available) {
            customersAccountMsgSpan.innerText = "";
        } else {
            customersAccountMsgSpan.innerText = "账号已存在";
        }
    })
    .catch(error => {
        console.error("Fetch error:", error);
        customersAccountMsgSpan.innerText = "请求失败";
    });
}

前端HTML代码

<form action="/customers/regist" method="post" onsubmit="return verify(this)">
    <table class="boder">
        <tr>
            <td class="col1">客户账号: <br></td>
            <td class="col2">
                <input type="text" id="customersAccountInput" name="account" class="textfield" onblur="checkCustomersAccount()"
                       placeholder="5-10位大小写英文及数字组合" style="font-size: 12px"/>
                <span id="customersAccountMsg" class="msg"></span>
            </td>
        </tr>
    </table>
</form>

后端SpringBoot代码

// 框架:SpringBoot
@RestController
public class CustomersController {
    @GetMapping(value = "/customers/checkAccountUsed")
    @CrossOrigin(origins = "*")
    public ResponseEntity<Result> checkAccountUsed(@RequestParam("account") String account) {
        System.out.println("Received account" + account);
        Customers customers = customerService.getCustomersByAccount(account);

        Result result = (customers != null) ? new Result(false) : new Result(true);

        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_JSON)  
                .body(result);
    }
}

排查情况

已通过Postman验证后端接口可正常返回JSON响应,但前端网页请求异常。尝试过以下方案均无效:

  • 使用Postman校验接口
  • 重建Tomcat 10.1.21
  • 改用XMLHttpRequest发起请求

请求响应信息

  • 请求URL:http://localhost:8080/customers/checkAccountUsed?account=cutes5566
  • 请求方法:GET
  • 状态码:404 Not Found
  • 请求头包含Accept: application/json,响应头返回Content-Type: text/html;charset=utf-8

问题原因及解决思路

1. 上下文路径不匹配

Postman请求可能包含了项目上下文路径,但前端用相对路径/customers/checkAccountUsed发起请求,若SpringBoot配置了server.servlet.context-path(比如/demo),前端请求会因缺少该前缀导致404。

  • 解决:检查application.properties/application.yml中的上下文路径配置,前端请求URL需拼接该前缀,或者通过JS动态获取上下文路径:
    // 动态获取上下文路径
    const contextPath = window.location.pathname.split('/')[1];
    const requestUrl = `/${contextPath}/customers/checkAccountUsed?account=${encodedAccount}`;
    

2. 前端部署路径错误

若前端页面部署在Tomcat独立的webapp目录下,而SpringBoot应用部署在另一个上下文,前端的相对路径会指向Tomcat根目录,而非SpringBoot应用的上下文,导致请求地址无效。

  • 解决:使用绝对路径发起请求,直接写完整URL:http://localhost:8080/customers/checkAccountUsed;或把前端静态资源放在SpringBoot的resources/static目录下,和后端同上下文部署。

3. SpringBoot路由拦截或匹配问题

  • 检查控制器的@GetMapping路径是否拼写错误,比如大小写、斜杠是否正确;
  • 查看SpringBoot日志,确认请求是否进入控制器方法,若未进入,排查是否有拦截器、过滤器对/customers/**路径做了拦截;
  • 解决:修正路径拼写,移除或调整拦截器的拦截规则,确保请求能到达控制器。

4. 跨域配置未生效

虽然添加了@CrossOrigin,但如果前端页面的域名/端口和后端不一致,可能存在跨域配置未生效的情况,浏览器发起的预检请求被拦截后返回404页面。

  • 解决:明确指定@CrossOrigin的origins为前端实际访问地址(比如origins = "http://localhost:8081"),或配置全局跨域:
    @Configuration
    public class CorsConfig implements WebMvcConfigurer {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedMethods("GET", "POST", "PUT", "DELETE")
                    .allowedHeaders("*");
        }
    }
    

内容的提问来源于stack exchange,提问作者呂逸承

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 12:47:06