Spring MVC中GET请求URL为何自动添加额外请求参数?
我有一个网站website.com,使用Spring MVC表单代码如下:
<form:form method="get" id="profileForm" modelAttribute="profile" onsubmit="updateFormAction()"> <form:label path="username">Name</form:label> <form:input path="username" id="usernameInput"/> <input type="submit" value="Submit"/> </form:form> <script> function updateFormAction() { var username = document.getElementById("usernameInput").value; var form = document.getElementById("profileForm"); form.action = "/profile/" + username; } </script>
预期提交后的URL应为website.com/profile/username123,但实际生成的URL是website.com/profile/username123?username=username123。
我的Web控制器映射方法如下:
@GetMapping("/profile/{username}") public String profile(@PathVariable("username") String name, Model model, RestTemplate restTemplate) throws JsonProcessingException { // 方法逻辑 }
将表单method设为post时可正常工作,但我需要使用GET方法以支持通过链接直接访问。尝试使用@ModelAttribute("username") String username后,URL变为website.com/profile/?username=username123,请问如何解决该问题?是否不应使用表单,而是改用按钮的onsubmit参数?
方案1:移除输入字段的name属性
使用GET方法提交表单时,浏览器会自动将所有带name属性的表单字段拼接为URL的查询参数。你的form:input标签会自动生成带name="username"的input元素,所以即便修改了form的action,浏览器仍会把该字段追加到URL后。
可以通过两种方式处理:
- 替换
form:input为普通input标签,且不设置name属性:<input type="text" id="usernameInput" placeholder="Name"/> - 在
updateFormAction函数中移除输入框的name属性:function updateFormAction() { var usernameInput = document.getElementById("usernameInput"); var username = usernameInput.value; var form = document.getElementById("profileForm"); // 移除name属性,避免被拼入查询参数 usernameInput.removeAttribute("name"); form.action = "/profile/" + username; }
方案2:阻止表单默认提交,手动跳转页面
直接在onsubmit中拦截表单的默认提交行为,通过window.location.href手动跳转到目标URL,完全绕过表单的GET提交逻辑:
<form:form method="get" id="profileForm" modelAttribute="profile" onsubmit="return handleSubmit()"> <form:label path="username">Name</form:label> <form:input path="username" id="usernameInput"/> <input type="submit" value="Submit"/> </form:form> <script> function handleSubmit() { var username = document.getElementById("usernameInput").value; window.location.href = "/profile/" + username; // 返回false阻止表单默认提交 return false; } </script>
这种方式更直接,完全按照预期的URL格式跳转,不会产生多余的查询参数。
方案3:调整Spring MVC请求映射(不推荐)
如果不想修改前端代码,可以将控制器的映射改为支持查询参数,但这样URL会变成/profile?username=username123,不符合你想要的REST风格路径:
@GetMapping("/profile") public String profile(@RequestParam("username") String name, Model model, RestTemplate restTemplate) throws JsonProcessingException { // 方法逻辑 }
此方案仅作为备选,优先推荐前两种前端调整方案。
内容的提问来源于stack exchange,提问作者sebbington

