Spring控制器Post请求无法解析Thymeleaf表单提交参数问题求助
问题根因
- POST接口配置了
consumes = "application/json",但HTML表单默认提交的Content-Type为application/x-www-form-urlencoded,类型不匹配导致Spring无法匹配到对应的处理方法,参数无法解析。 - 表单提交路径与接口路径不匹配:表单配置
th:action="@{/forecast/saveInput}",但POST接口路径为/saveInput,缺少/forecast前缀。 - GET方法加了多余的
@ResponseBody注解,该注解会将返回值直接作为响应体输出,而非解析为Thymeleaf视图,属于配置冗余。 - 使用
@ModelAttribute绑定时缺少表单的th:object配置,导致Thymeleaf无法找到绑定的实体对象,触发th:field解析错误。 InputBean上多余的@Component注解,该类仅为数据传输POJO,无需交给Spring容器管理。
修正步骤
1. 修正Controller配置
- 移除POST接口错误的
consumes、produces配置,直接使用@PostMapping简化注解 - 移除GET方法上的
@ResponseBody注解 - 按需调整接口路径,或者给Controller类添加
@RequestMapping("/forecast")前缀匹配表单提交路径 - 使用
@ModelAttribute直接绑定InputBean接收参数,无需手动从ModelMap取值
2. 修正Thymeleaf页面配置
- 表单标签添加
th:object="${inputBean}"绑定后台传递的实体对象 - 所有表单输入项改用
th:field="*{属性名}"绑定实体属性,无需手动配置name属性,Thymeleaf会自动生成
修正后代码示例
Controller代码
@Controller // 若保留表单的/forecast路径前缀,取消下面注解的注释 // @RequestMapping("/forecast") public class InputFormController { private final ForecastReportService forecastReportService; @Autowired public InputFormController(ForecastReportService forecastReportService) { this.forecastReportService = forecastReportService; } @GetMapping("/") public ModelAndView showForm() { ModelAndView modelAndView = new ModelAndView("index"); modelAndView.addObject("inputBean", new InputBean()); return modelAndView; } @PostMapping("/saveInput") public ModelAndView processInput(@ModelAttribute("inputBean") InputBean inputBean) { ModelAndView modelAndView = new ModelAndView("forecast-success"); try { forecastReportService.execute(inputBean); } catch (IOException | ParseException e) { e.printStackTrace(); } modelAndView.addObject("inputBean", inputBean); return modelAndView; } }
Thymeleaf表单代码
<form th:action="@{/saveInput}" th:object="${inputBean}" class="form-input" method="post" align="center"> <label for="username" class="sr-only">Username</label> <input type="text" id="username" th:field="*{username}" class="form-control" placeholder="Username" required autofocus> <p> <label for="password" class="sr-only">Password</label> <input type="password" id="password" th:field="*{password}" class="form-control" placeholder="Password" required> </p> <p> <label for="startDate" class="sr-only">Start date</label> <input type="text" id="startDate" th:field="*{startDate}" class="form-control" placeholder="StartDate" required> </p> <p> <label for="endDate" class="sr-only">End date</label> <input type="text" id="endDate" th:field="*{endDate}" class="form-control" placeholder="EndDate" required> </p> <button class="btn btn-lg btn-primary btn-block" type="submit">Submit</button> </form>
InputBean代码(移除@Component注解)
public class InputBean { private String username; private String password; private String startDate; private String endDate; public InputBean() { } public InputBean(String username, String password, String startDate, String endDate) { this.username = username; this.password = password; this.startDate = startDate; this.endDate = endDate; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getStartDate() { return startDate; } public void setStartDate(String startDate) { this.startDate = startDate; } public String getEndDate() { return endDate; } public void setEndDate(String endDate) { this.endDate = endDate; } }
内容的提问来源于stack exchange,提问作者Rosen Hristov
相关产品推荐
相关产品推荐

