Thymeleaf从Controller传递路径变量遇请求错误,寻求解决方案
问题解决方法
1. 修复URL路径变量错误
你的第一个错误是Thymeleaf路径变量语法不匹配,导致生成的URL出现非法的//。正确的路径变量写法要保证占位符名称与参数名一致:
<form method="post" th:action="@{/api/userProfile/savedAdventureHolidays/{postId}/post(postId=${postId})}"> <input type="submit" value="Save"/> </form>
解释:路径中的{postId}需要和括号内的postId=${postId}对应,之前你用了id=${postId},变量名不匹配导致路径拼接异常。
2. 解决415 Unsupported Media Type错误
这个错误是因为表单默认提交的Content-Type是application/x-www-form-urlencoded,但你的Controller方法使用@RequestBody,它仅支持JSON/XML这类结构化数据,不兼容表单编码格式。以下是两种可行方案:
方案一:修改Controller,改用@ModelAttribute接收参数
将@RequestBody替换为@ModelAttribute,让Spring可以直接处理表单提交的参数:
@PostMapping("/savedAdventureHolidays/{postId}/post") public String saveHoliday(@PathVariable(value = "postId") String postId, @Valid @ModelAttribute UserProfile comment, Model model) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); String username = authentication.getName(); adventureHolidaysRepository.findById(postId).map(post -> { comment.setAdventureHolidaysList(Collections.singletonList(post)); comment.setLoggedUserId(username); userProfileRepository.save(comment); return post; }).orElseThrow(() -> new ResourceNotFoundException("PostId " + postId + " not found")); // 处理完成后重定向到目标页面,自行替换视图路径 return "redirect:/your-target-view"; }
如果UserProfile需要前端提交字段,在表单中添加对应输入框即可:
<form method="post" th:action="@{/api/userProfile/savedAdventureHolidays/{postId}/post(postId=${postId})}"> <!-- 示例:若UserProfile包含name字段,添加输入框 --> <input type="text" name="name" th:value="${comment.name}"/> <input type="submit" value="Save"/> </form>
如果无需前端提交字段,空表单配合@ModelAttribute也能创建空对象供后端填充数据。
方案二:用JavaScript发送AJAX请求(提交JSON数据)
如果必须保留@RequestBody,可以通过JS监听表单提交事件,发送JSON格式请求:
<form id="saveHolidayForm" th:data-post-id="${postId}"> <input type="submit" value="Save"/> </form> <script> document.getElementById('saveHolidayForm').addEventListener('submit', function(e) { e.preventDefault(); // 阻止默认表单提交行为 const postId = this.dataset.postId; // 根据UserProfile实体类构造请求对象,无前端字段则留空 const comment = {}; fetch(`/api/userProfile/savedAdventureHolidays/${postId}/post`, { method: 'POST', headers: { 'Content-Type': 'application/json', // 开启CSRF保护时需添加token 'X-CSRF-TOKEN': document.querySelector('meta[name="_csrf"]').content }, body: JSON.stringify(comment) }) .then(response => { if (response.ok) { // 处理成功逻辑,比如刷新页面 window.location.reload(); } else { alert('保存失败,请重试'); } }) .catch(error => console.error('请求错误:', error)); }); </script>
注意:若项目启用了CSRF保护,需在页面头部添加CSRF元标签:
<meta name="_csrf" th:content="${_csrf.token}"/> <meta name="_csrf_header" th:content="${_csrf.headerName}"/>
内容的提问来源于stack exchange,提问作者Stefan Jankovic
相关产品推荐
相关产品推荐

