Java 在SpringMVC中,如何将用户输入绑定到BigDecimal对象字段?

Java 在SpringMVC中,如何将用户输入绑定到BigDecimal对象字段?,java,spring,spring-mvc,thymeleaf,Java,Spring,Spring Mvc,Thymeleaf,在我的项目中,我有一个类,其中一个字段是BigDecimal @实体 公共类产品{ // ... @小数点(“0.01”) 私人价格; // ... } 在thymeleaf中,我有一个包含此类字段输入的表单,负责price的表单是: 从该表单返回@modeldattribute时,产品的价格字段为空。当price是double时,它通常起作用。我怎样才能做到这一点?我想到了一个解决方法-将此输入作为@RequestParam,然后使用双精度值“手动”初始化产品。price,但是否有某种解

在我的项目中,我有一个类,其中一个字段是
BigDecimal

@实体
公共类产品{
// ...
@小数点(“0.01”)
私人价格;
// ...
}
在thymeleaf中,我有一个包含此类字段输入的表单,负责
price
的表单是:



从该表单返回
@modeldattribute
时,
产品
价格
字段为空。当
price
double
时,它通常起作用。我怎样才能做到这一点?我想到了一个解决方法-将此输入作为
@RequestParam
,然后使用
双精度
值“手动”初始化
产品。price
,但是否有某种解决方案让thymeleaf为我这样做?

。我刚刚使用Spring Boot 2.3.0对其进行了如下测试:

我使用的是表单数据对象,因为直接将实体用于表单会使报告过于混乱:

import javax.validation.constraints.DecimalMin;
import java.math.BigDecimal;

public class ProductFormData {

    @DecimalMin("0.01")
    private BigDecimal price;

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }
}
使用这样的控制器:

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/product")
public class ProductController {

    @GetMapping
    public String product(Model model) {
        model.addAttribute("product", new ProductFormData());
        return "product";
    }

    @PostMapping
    public String doSaveProduct(@ModelAttribute("product") ProductFormData formData) {
        System.out.println("formData = " + formData.getPrice());

        return "redirect:/product";
    }
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http:www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Product</title>
</head>
<body>
<h1>Product</h1>
<form th:action="@{/product}" th:object="${product}" method="post">
    <input type="number" step="any" th:field="*{price}">
    <button type="submit">submit</button>
</form>
</body>
</html>
product.html
模板如下:

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/product")
public class ProductController {

    @GetMapping
    public String product(Model model) {
        model.addAttribute("product", new ProductFormData());
        return "product";
    }

    @PostMapping
    public String doSaveProduct(@ModelAttribute("product") ProductFormData formData) {
        System.out.println("formData = " + formData.getPrice());

        return "redirect:/product";
    }
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http:www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Product</title>
</head>
<body>
<h1>Product</h1>
<form th:action="@{/product}" th:object="${product}" method="post">
    <input type="number" step="any" th:field="*{price}">
    <button type="submit">submit</button>
</form>
</body>
</html>

产品
产品
提交

当我在表单中键入一个数字并按“提交”时,我看到控制台中打印的值。

应该可以。我刚刚使用Spring Boot 2.3.0对其进行了如下测试:

我使用的是表单数据对象,因为直接将实体用于表单会使报告过于混乱:

import javax.validation.constraints.DecimalMin;
import java.math.BigDecimal;

public class ProductFormData {

    @DecimalMin("0.01")
    private BigDecimal price;

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }
}
使用这样的控制器:

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/product")
public class ProductController {

    @GetMapping
    public String product(Model model) {
        model.addAttribute("product", new ProductFormData());
        return "product";
    }

    @PostMapping
    public String doSaveProduct(@ModelAttribute("product") ProductFormData formData) {
        System.out.println("formData = " + formData.getPrice());

        return "redirect:/product";
    }
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http:www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Product</title>
</head>
<body>
<h1>Product</h1>
<form th:action="@{/product}" th:object="${product}" method="post">
    <input type="number" step="any" th:field="*{price}">
    <button type="submit">submit</button>
</form>
</body>
</html>
product.html
模板如下:

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/product")
public class ProductController {

    @GetMapping
    public String product(Model model) {
        model.addAttribute("product", new ProductFormData());
        return "product";
    }

    @PostMapping
    public String doSaveProduct(@ModelAttribute("product") ProductFormData formData) {
        System.out.println("formData = " + formData.getPrice());

        return "redirect:/product";
    }
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http:www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Product</title>
</head>
<body>
<h1>Product</h1>
<form th:action="@{/product}" th:object="${product}" method="post">
    <input type="number" step="any" th:field="*{price}">
    <button type="submit">submit</button>
</form>
</body>
</html>

产品
产品
提交

当我在表单中键入一个数字并按“提交”时,我会看到控制台中打印的值。

是否有类似于DTO的内容?像只从表单检索数据的对象吗?(然后用于创建实体对象?)这对性能不是很坏吗?确实如此。然后,我要么在
ProductFormData
上使用
toProduct()
方法,要么将
ProductFormData
传递给服务方法(例如
service.addProduct(ProductFormData)
,甚至将
ProductFormData
转换为
AddProductParameters
(例如
service.addProduct>)(formData.toProductParameters())
)。这确保了您可以为实体使用丰富的域模型。我没有看到任何情况下出现性能问题。通过“达到实体的域模型”你的意思是,例如,我想以某种方式扩展我的实体类?顺便说一下,谢谢你的回答,它们确实有帮助,但我不完全理解使用
ProductFormData
的好处。我的意思是
ProductFormData
通常只使用
String
int
BigDecimal
。在实体中,您可以使用
价格
类或
数量
类。当然,在
产品
中,您可能有一个
供应商
参考,但在
产品表单数据
中,您使用
字符串供应商ID
,因为这将更容易绑定到Thymeleaf表单。因此类似DTO?like的东西e一个只从表单中检索数据的对象?(然后用于创建实体对象?)这对性能不是很坏吗?确实如此。然后我要么在
ProductFormData
上有一个
toProduct()
方法,要么将
ProductFormData
传递给一个服务方法(例如
service.addProduct(ProductFormData))
,甚至可以将
ProductFormData
转换为
AddProductParameters
(例如
service.addProduct(formData.toProductParameters())
)。这确保了您可以为实体使用丰富的域模型。我没有看到任何情况下会出现性能问题。通过“达到实体的域模型”你的意思是,例如,我想以某种方式扩展我的实体类?顺便说一下,谢谢你的回答,它们确实有帮助,但我不完全理解使用
ProductFormData
的好处。我的意思是
ProductFormData
通常只使用
String
int
BigDecimal
。在实体中,您可以使用
价格
类或
数量
类。当然,在
产品
中,您可能有一个
供应商
参考,但在
产品表单数据
中,您使用
字符串供应商ID
,因为这样更容易绑定到表单。