将自定义对象从thymeleaf视图传递到控制器

时间:2019-08-03 07:04:51

标签: java html spring model-view-controller thymeleaf

试图将使用的自定义对象从View传递到th:value到Controller,但只能通过th:value传递Java的原始数据类型。有什么办法可以通过th:value

发送复杂的对象

我是新来的春天,正在尝试一些随机的东西。 这是一个简单的Web应用程序。

我正在尝试做的事情:

我有一个创建团队的表格。该表单包括一个用于团队名称的文本字段和一堆用于选择团队成员的复选框。对于每个选中的复选框,应将相应的成员添加到团队列表中。

我尝试使用thymeleaf的th:value属性将对象从View传递到Controller。但是我只能使用th:value

传递字符串值 teamCreationForm.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Create your Team</title>
</head>
<body>
    <h1>Create your dream team</h1>

    <form method="post" th:object="${team}">

        <span>Name of the team</span>
        <input type="text" th:field="*{name}">

        <div th:each="player : ${playersList}">
            <input type="checkbox" name="players" th:value="${player}" th:valueType="com.example.kkvamshee.Cricket.Player">
            <span th:text="${player.name}">Player Name</span>
        </div>

        <button type="submit">Submit your team</button>
    </form>
</body>
</html>
CreateTeamController.java
package com.example.kkvamshee.Cricket.web;

import com.example.kkvamshee.Cricket.Player;
import com.example.kkvamshee.Cricket.Team;
import com.example.kkvamshee.Cricket.data.JdbcPlayerRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;
import java.util.List;

@Slf4j
@Controller
@RequestMapping("/create-your-team")
public class CreateTeamController {

    ....

    @GetMapping
    public String showSelectTeamPage(Model model) {
        List<Player> playersList = playerRepo.findAll();

        model.addAttribute("playersList", playersList);
        model.addAttribute("team", new Team());

        return "teamCreationForm";
    }

    .....

}

Team.java
package com.example.kkvamshee.Cricket;

import lombok.Data;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;

@Data
public class Team {
    @NotNull private String name;

    @Size(min = 3, max = 3, message = "You can only have 3 members on the team")
    private List<Player> players;
}

错误日志

Field error in object 'team' on field 'players': rejected value [Player(name=vamshee, age=20, exp=1),Player(name=messi, age=32, exp=18),Player(name=ronaldo, age=34, exp=18)]; codes [typeMismatch.team.players,typeMismatch.players,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [team.players,players]; arguments []; default message [players]]; default message [Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.List' for property 'players'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.example.kkvamshee.Cricket.Player' for property 'players[0]': no matching editors or conversion strategy found]

在此错误日志的末尾,“没有找到匹配的编辑器或转换策略”。

我尝试将th:valueType更改为Integer,并成功将对应的文本转换为Integer值。但是我在使用Team对象或任何其他自定义对象执行相同操作时遇到此强制转换错误。

2 个答案:

答案 0 :(得分:1)

Thymeleaf可以知道您正在使用哪个对象,特别是如果您正确映射了该对象并正确接受了该对象。查看我对您的代码所做的测试。

请注意如何在表单中引入操作。

enter image description here

enter image description here

enter image description here

答案 1 :(得分:0)

模板引擎必须将<input ... th:value="${player}">标记转换为HTML(浏览器可以理解的HTML),转换后的标记看起来像<input ... value="string returned by player.toString()">

因此,视图不了解对象Player。该值只是视图的简单字符串。 Spring需要一些转换器才能将字符串转换为适当的Player对象。

这可以通过实现Converter<String, Player>接口,然后在我们的应用程序中注册Converter来完成。

转换器接口的实现:

package com.example.kkvamshee.cricket.config;

import com.example.kkvamshee.cricket.Player;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class StringToPlayerConverter implements Converter<String, Player> {

    @Override
    public Player convert(String source) {
        String pattern = "Player\\(name=([a-zA-z0-9]+), age=([1-9]+), exp=([1-9]+)\\)";

        Matcher matcherResult = Pattern.compile(pattern).matcher(source);

        log.info("regex result : " + matcherResult.find());

        String name = matcherResult.group(1);
        int age = Integer.parseInt(matcherResult.group(2));
        int exp = Integer.parseInt(matcherResult.group(3));

        return new Player(name, age, exp);
    }
}

注册上述Converter对象:

package com.example.kkvamshee.cricket.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new StringToPlayerConverter());
    }
}

有多种方法可以实现这种类型转换。

有关更多详细信息,请参见documentation

相关问题