【问题标题】:Sping MVC, Thymeleaf, POST request, how to pass list of objects to controllerSpring MVC,Thymeleaf,POST请求,如何将对象列表传递给控制器
【发布时间】:2021-11-21 06:04:03
【问题描述】:

一个“老师”可以有几个指定的“科目”来教授:

public class Teacher {
    private int id;
    private String firstName;
    private String lastName;
    ...
    private List<Subject> subjects;
}

在 HTML 视图中,用户可以为老师选择一门或多门科目并发送 POST 请求:

<select class="form-control" id="subjects" name="subjects" size="5" multiple required>
   <option th:each="subject: ${allSubjects}"
       th:value="${subject.id}"
       th:text="${subject.name}"
       th:selected="${teacher.subjects.contains(subject)}">
   </option>
</select>

处理此请求的控制器:

@PostMapping("/update")
    public String update(@ModelAttribute("teacher") Teacher teacher) {
        logger.debug("Received update data: {}", teacher);
        teacherService.update(teacher);
        return "redirect:/teachers";
    }

这是正在传递的 POST 请求:

我希望 Spring 采用 subject.id 并将它们作为主题列表注入到教师中。 但我得到了例外:

BindException

org.springframework.validation.BeanPropertyBindingResult: 
1 errors Field error in object 'teacher' on field 'subjects': rejected value [2,4]; codes [typeMismatch.teacher.subjects,typeMismatch.subjects,typeMismatch.java.util.List,typeMismatch]; 
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [teacher.subjects,subjects]; 
arguments []; default message [subjects]]; default message [Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.List' for property 'subjects'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'ua.com.foxminded.university.model.Subject' for property 'subjects[0]': no matching editors or conversion strategy found]

我仔细阅读了我的问题的前 50 个 google 结果,代码应该可以工作,但不能。我一定是错过了什么。

【问题讨论】:

    标签: java spring spring-mvc thymeleaf


    【解决方案1】:

    首先是错误的注释——你不要在帖子内部使用@ModelAttribute,而是使用@RequestBody,这在帖子的spring控制器中是隐含的。

    除此之外,您发送的不是教师实体,而是teacherDTO,它不会包含您显示的教师实体所具有的所有字段(集合)。这意味着您应该接收不同的课程 (TeacherDTO),然后将其正确转换为教师实体,然后在数据库中更新该实体

    【讨论】:

      【解决方案2】:

      我想这是一个更新表单,所以它需要一个对象教师作为输入。试试这个

      
      <form th:object="${teacher}" method="post">
      <select class="form-control" th:field="*{subjects}" id="subjects" name="subjects" size="5" multiple required>
         <option th:each="subject: ${allSubjects}"
             th:value="${subject.id}"
             th:text="${subject.name}"
             th:selected="*{subjects.contains(subject)}">
         </option>
      </select>
      </form>
      

      【讨论】:

        【解决方案3】:

        最后,我在处理项目的另一部分时找到了解决方案。 我试图将 Lecture 对象传递给控制器​​,Lecture 包含学生组列表。每个组有 2 个字段:id 和 name。 首先我们实现一个格式化程序

        public class GroupFormatter implements Formatter<Group> {
        
            @Override
            public Group parse(String text, Locale locale) throws ParseException {
                Group group=new Group();
                if (text != null) {
                    String[] parts = text.split(",");
                    group.setId(Integer.parseInt(parts[0]));
                    if(parts.length>1) {
                        group.setName(parts[1]);
                    }
                }
                return group;
            }
        
            @Override
            public String print(Group group, Locale locale) {
                return group.toString();
            }
        }
        

        在 MVCConfig 中注册格式化程序

        @Override
            public void addFormatters(FormatterRegistry registry) {
                GroupFormatter groupFormatter=new GroupFormatter();
                registry.addFormatter(groupFormatter);
            }
        

        我们从 POST 请求中得到正确的格式:

        groups=[4:VM-08, 5:QWE-123]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-14
          • 2019-11-15
          • 2018-11-17
          • 2013-08-17
          相关资源
          最近更新 更多