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

使用Thymeleaf传递Select选项的Skill对象到Controller报错求助

问题描述

我尝试通过Thymeleaf将select组件选中的Skill对象传递到Controller,但提交表单时出现400错误,相关代码及错误信息如下:

实体类Skill

@Entity
@Table(name = "Skills")
@Builder
public class Skill {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id", nullable = false)
        private Long id;

        @Column(name = "title", nullable = false, length = 40)
        private String title;

        @Column(name = "category", nullable = false, length = 30)
        @Enumerated(EnumType.STRING)
        private Category category;
}

传入技能列表的IndexController

@Controller
@RequestMapping("/")
@RequiredArgsConstructor
public class IndexController {

        private final SkillService skillService;

        @GetMapping("/manager-profile")
        public String managerProfile(Model model) {
                model.addAttribute("skillList", skillService.findAllSkills());
                return "manager-profile";
        }
}

视图表单代码

<form th:action="@{/getEmployeeBySkill}" method="post" id="skill-form">
    <div class="select-box manager">
        <select class="select_box manager" id="select-skill" name="skill">
            <option value="">Select</option>
            <option th:each="skill : ${skillList}" th:attr="data-category=${skill.category}" th:value="${skill}" th:name="skill" th:text="${skill.title}"></option>
        </select>
        <input type="number" class="form-control" id="experience" placeholder="Experience">
        <button type="submit" class="btn manager-select_box">Search</button>
    </div>
</form>

接收请求的EmployeeController

@Controller
@RequestMapping("/")
public class EmployeeController {

        private final EmployeeService employeeService;

        @PostMapping("/getEmployeeBySkill")
        String getEmployeesBySkill (Model model, @ModelAttribute("skill") Skill skill) {
                // do stuff
                return "candidate-list";
        }

}

错误信息

There was an unexpected error (type=Bad Request, status=400).
Failed to convert value of type 'java.lang.String' to required type 'com.neusta.domain.Skill'; Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'com.neusta.domain.Skill@bb0c873'
org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'com.neusta.domain.Skill'; Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'com.neusta.domain.Skill@bb0c873'

错误原因

核心问题出在<option>标签的th:value="${skill}"上:当你直接将Skill对象赋值给value属性时,Thymeleaf会默认调用对象的toString()方法,最终提交到后台的是类似com.neusta.domain.Skill@bb0c873的字符串。而Spring无法将这个无意义的字符串直接转换为Skill对象,因此抛出类型转换异常。


修复方案

有两种常用的解决方式:

方式一:传递Skill的ID,后台通过ID查询对象

这是最简单直接的方案:

  1. 修改视图中的<option>标签,将th:value改为Skill的id,并移除重复的th:name="skill"(父标签<select>已设置name="skill"):
<option th:each="skill : ${skillList}" 
        th:attr="data-category=${skill.category}" 
        th:value="${skill.id}" 
        th:text="${skill.title}"></option>
  1. 修改Controller方法,接收id后查询对应的Skill对象:
@PostMapping("/getEmployeeBySkill")
String getEmployeesBySkill (Model model, @RequestParam("skill") Long skillId) {
        Skill skill = skillService.findSkillById(skillId);
        // 后续业务逻辑
        return "candidate-list";
}

方式二:自定义Converter实现自动转换(适合复杂场景)

如果希望保持Controller接收Skill对象的写法,可以自定义Spring Converter,让框架知道如何将提交的ID字符串转换为Skill对象:

  1. 实现Converter<String, Skill>接口:
@Component
public class StringToSkillConverter implements Converter<String, Skill> {

    private final SkillService skillService;

    public StringToSkillConverter(SkillService skillService) {
        this.skillService = skillService;
    }

    @Override
    public Skill convert(String source) {
        if (source == null || source.isEmpty()) {
            return null;
        }
        return skillService.findSkillById(Long.parseLong(source));
    }
}
  1. 视图部分同方式一(传递Skill的id),Controller可以保持原来的写法直接接收Skill对象:
@PostMapping("/getEmployeeBySkill")
String getEmployeesBySkill (Model model, @ModelAttribute("skill") Skill skill) {
        // do stuff
        return "candidate-list";
}

内容的提问来源于stack exchange,提问作者Greta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 06:10:11