代码之家  ›  专栏  ›  技术社区  ›  PewPhon

Thymeleaf如何使用选择输入将对象发送到控制器

  •  0
  • PewPhon  · 技术社区  · 3 年前

    您好,我无法使用Thymeleaf和Spring Boot(+Spring data)将一个对象作为另一个对象的属性发送给POST请求。

    在这种情况下,我很难理解Spring Boot controller是如何传递和处理数据的。 传递基本数据类型(以字符串形式)很容易由控制器管理,并转换为适当的数据类型服务器端。 但当我需要将复杂对象数据类型作为属性传递时,问题就来了:

    这是用户类:

    //Import...
    public class User implements Serializable {
    
    @Id
    @Column(name="c_Username", length=64, unique = true, nullable = false)
    private String username;
    
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "c_Role")
    private Role role;
    
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "c_Team")
    @JsonManagedReference
    private Team team;
    
    @Column(name="e_Email", unique = true, length=128, nullable = false)
    @Email
    private String email;
    
    @Column(name="x_Name", nullable = false, length=32)
    private String name;
    
    @Column(name="x_Surame", nullable = false, length=64)
    private String surname;
    
    @Column(name="x_Description", nullable = false, length=128)
    private String description;
    
    @Column(name="i_Cost", nullable = false)
    private double cost;
    
    @Column(name="x_Time", nullable = false, length=5)
    private String time;
    
    @Column(name="h_Password", nullable = false, length=128)
    private String passwordHash;
    
    @Column(name="f_Enabled", nullable = false)
    private boolean enabled;
    
    //... hashcode & equals
    }
    

    这是单个用户更新的映射:

        @PostMapping("/updateuser")
    public void updateUser(@Valid User user){
        System.out.println(user); //For debugging reason
        //find object and validate if it exists.. or return error response
        utentiService.saveUser(user);
    }
    

    这是一个Javascript函数,通过它,我只需点击一个按钮,就可以对编辑过的表的每一行(每一行代表一个用户)进行post请求。(您必须通过复选框检查行,但我发现在location.reload()之后复选框不会重置,我将稍后尝试修复此问题)

        function saveUsers(){
        for (let index in tableRowList){
            if(tableRowList[index]){
                let data = new FormData(document.getElementById("form"+index));
                for (let value of data.values()) {
                    console.log(value);
                }
                fetch("/updateuser", {method: 'POST', body: data})
                    .then(response => console.log(response));
            }
        }
        fetch("/users")
            .then(() => window.location.reload());
    }
    

    这是生成表中每一行的html代码。 表格得到了很好的生成,每一个值都在每个表格单元格中,读取工作正常。

    <tr th:each="user,iter : ${listaUtenti}" th:id="riga+${iter.index}">
        <form th:action="@{/updateuser}"  th:id="form+${iter.index}" th:object="${user}" method="post">
            <td>
                <input type="hidden" th:id="pass + ${iter.index}" name="passwordHash" value="fake">
                <input th:onclick="'selezionaRigaTabella(\'' + ${iter.index} + '\');'" type="checkbox" class="tablecheckbox">
            </td>
            <td>
                <input class="input has-background-primary-light has-text-primary is-primary" th:id="username + ${iter.index}" name="username" type="text" th:value="${user.username}" th:placeholder="${user.username}" maxlength="64" required readonly>
            </td>
            <td>
                <div class="select">
                    <select th:id="role + ${iter.index}" name="role" th:selected="${user.role.roleName}" class="width110">
                        <option name="role" th:each="role : ${listaRuoli}" th:selected="${user.role.roleName == role.roleName}" th:value="${role}" th:text="${role.roleName}"></option>
                    </select>
                </div>
            </td>
            <td>
                <input class="input" th:id="name + ${iter.index}" name="name" type="text" th:value="${user.name}" th:placeholder="${user.name}" maxlength="32" required>
            </td>
            <td>
                <input class="input" th:id="surname + ${iter.index}" name="surname" type="text" th:value="${user.surname}" th:placeholder="${user.surname}" maxlength="64" required>
            </td>
            <td>
                <input class="input" th:id="description + ${iter.index}" name="description" type="text" th:value="${user.description}" th:placeholder="${user.description}" maxlength="128" required>
            </td>
            <td>
                <input class="input" th:id="email + ${iter.index}" name="email" type="email" th:value="${user.email}" th:placeholder="${user.email}" maxlength="128" required onresize="this.style.width = ((this.value.length + 1) * 8) + 'px';">
            </td>
            <td>
                <div class="select">
                    <select th:id="team + ${iter.index}" name="team" th:selected="${user.team.teamName}" class="width110">
                        <option th:each="team : ${listaTeams}" th:selected="${user.team.teamName == team.teamName}" th:value="${team}" th:text="${team.teamName}"></option>
                    </select>
                </div>
            </td>
            <td>
                <input class="input" th:id="cost + ${iter.index}" name="cost" type="text" th:value="${user.cost}" th:placeholder="${user.cost}" required>
            </td>
            <td>
                <input class="input" th:id="time + ${iter.index}" name="time" type="text" th:value="${user.time}" th:placeholder="${user.time}" minlength="5" maxlength="5" required>
            </td>
            <td>
                <div class="select">
                    <select th:id="enabled + ${iter.index}" name="enabled" class="width80">
                        <option th:selected="${user.enabled}" value="true">yes</option>
                        <option th:selected="${!user.enabled}" value="false">no</option>
                    </select>
                </div>
            </td>
        </form>
    </tr>
    

    问题是我不知道如何在用户对象中传递对象团队和角色。 目前,它们是从thymeleaf生成的。 这是表单从生成的HTML(基本上是字符串“ClassName(attribute1=Value,attribute2=Value)”)发出post请求时发送的值的一个示例

    <select id="team0" name="team" class="width110" selected="selected">
        <option value="Team(teamName=AMM, teamDesc=Administration)" selected="selected">AMM</option>
        <option value="Team(teamName=ANA, teamDesc=Analytics)">ANA</option>
        <option value="Team(teamName=DEV, teamDesc=Developers)">DEV</option>
    </select>
    

    错误是在服务器端,我只为实际上是对象的两个属性(团队和角色)获取空值,我必须禁用非空约束才能使其工作。

    我不知道控制器如何在他的方法中实例化对象。

    我对thymeleaf很陌生,你知道这个对象传递/绑定应该如何工作吗? 我尝试在select标记上使用th:字段,但它在编译时会出错。

    我的临时修复程序只传递这些对象(角色和团队)的密钥,从请求体读取它们,通过服务检索它们,并为请求在post映射方法中实例化的对象用户手动设置它们。

    虽然这给了我很多响应/错误逻辑的可能性,但我在问自己是否有可能自动正确实例化post-mapping方法的用户对象。

    谢谢

    0 回复  |  直到 3 年前