无法在百里香分别输入日期

时间:2017-09-10 16:42:34

标签: java spring spring-boot thymeleaf

我一直在尝试将 dateOfBirth 字段添加到注册表单中。我想将日期分为3个字段:日,月和年。

当我输入日期到字段时,我进入控制器当前日期和奇怪的一年 - " 3890"。

我的HTML代码:

<div class="form-group row">
    <label for="confirm" class="col-sm-2 col-form-label">Date of Birth</label>
    <div class="col-sm-10">
        <input id="day" type="text" th:field="*{dateOfBirth.day}"/>
    </div>
</div>
<div class="form-group row">
    <label for="confirm" class="col-sm-2 col-form-label"></label>
    <div class="col-sm-10">
        <input id="month" type="text" th:field="*{dateOfBirth.month}"/>
    </div>
</div>
<div class="form-group row">
    <label for="confirm" class="col-sm-2 col-form-label"></label>
    <div class="col-sm-10">
        <input id="year" type="text" th:field="*{dateOfBirth.year}"/>
    </div>
</div>

我的控制器代码:

@GetMapping(value = "/register")
public String showRegistrationForm(WebRequest request, Model model) {
    ChannelDTO channelData = new ChannelDTO();
    model.addAttribute("channel", channelData);
    return "registration";
}

@PostMapping(value = "/register")
public ModelAndView registerUserAccount(@ModelAttribute("channel") @Valid ChannelDTO channelData, BindingResult result,
                                        HttpServletRequest request, Errors errors, RedirectAttributes redirectAttributes) {
    Channel channel = null;
    if (!result.hasErrors()) {
        channel = createUserAccount(channelData, result);
    }

    // logic...

    return new ModelAndView("redirect:/register/select-interests");
}

我的ChannelDTO:

@PasswordMatches
public class ChannelDTO {

    @NotNull
    @NotEmpty
    @Email
    private String email;

    @NotNull
    @NotEmpty
    private String name;

    //@NotNull
    //@NotEmpty
    @DateTimeFormat(pattern="yyyy-MM-dd")
    private Date dateOfBirth;

    @NotNull
    @NotEmpty
    private String password;

    @NotNull
    @NotEmpty
    private String matchingPassword;
}

感谢您的帮助,谢谢。

1 个答案:

答案 0 :(得分:0)

您正在使用原始日期类(它与java 8&n; datetime API无关): java.util.Date

文档说明了setYear:

  

将此Date对象的年份设置为指定值加上1900。

因此您需要在1900年之前减去年份值。 可能你可以用th:value来做,或者在控制器中你可以在逻辑部分之前减去1900年的dateOfBirth。

或者您可以使用Thymeleaf java8 datetime API模块,如下所示: Thymeleaf - Module for Java 8 Time API compatibility

如果您想在1900之前减去日期,请尝试以下方法:

@PostMapping(value = "/register")
public ModelAndView registerUserAccount(@ModelAttribute("channel") @Valid ChannelDTO channelData, BindingResult result, HttpServletRequest request, Errors errors, RedirectAttributes redirectAttributes) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(channelData.getDateOfBirth());
    cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - 1900);
    channelData.setDateOfBirth(cal.getTime());

    Channel channel = null;
    if (!result.hasErrors()) {
        channel = createUserAccount(channelData, result);
    }

    //logic...

    return new ModelAndView("redirect:/register/select-interests");
}

同时修改此行:

<input id="day" type="text" th:field="*{dateOfBirth.day}"/>

对此:

<input id="day" type="text" th:field="*{dateOfBirth.date}"/>

您也可以尝试不使用dateOfBirth的Date类型,而是使用Calendar。

修改

您可以尝试两种选择:

选项1:

按原样保留ChannelDTO并修改控制器,如下所示:

@PostMapping(value = "/register")
public ModelAndView registerUserAccount(@ModelAttribute("channel") @Valid ChannelDTO channelData,
                                        BindingResult result, HttpServletRequest request, Errors errors, RedirectAttributes redirectAttributes) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(channelData.getDateOfBirth());
    cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - 1900);
    cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) - 1);
    channelData.setDateOfBirth(cal.getTime());

    Channel channel = null;
    if (!result.hasErrors()) {
        channel = createUserAccount(channelData, result);
    }

    //logic...

    return new ModelAndView("redirect:/register/select-interests");
}

将您的html修改为:

<div class="form-group row">
    <label for="confirm" class="col-sm-2 col-form-label">Date of Birth</label>
    <div class="col-sm-10">
        <input id="day" type="text" th:field="*{dateOfBirth.date}" />
    </div>
</div>
<div class="form-group row">
    <label for="confirm" class="col-sm-2 col-form-label"></label>
    <div class="col-sm-10">
        <input id="month" type="text" th:field="*{dateOfBirth.month}" />
    </div>
</div>
<div class="form-group row">
    <label for="confirm" class="col-sm-2 col-form-label"></label>
    <div class="col-sm-10">
        <input id="year" type="text" th:field="*{dateOfBirth.year}" />
    </div>
</div>

选项2:

创建一个新类,用于保存年,月和日值:

public class CustomDate {
    public CustomDate() {
    }

    private int year;
    private int month;
    private int day;

    public int getYear() {
        return year;
    }
    public void setYear(int year) {
        this.year = year;
    }
    public int getMonth() {
        return month;
    }
    public void setMonth(int month) {
        this.month = month -1;
    }
    public int getDay() {
        return day;
    }
    public void setDay(int day) {
        this.day = day;
    }
}

像这样修改ChannelDTO类:

public class ChannelDTO {

    public ChannelDTO() {
    }

    @NotNull
    @NotEmpty
    @Email
    private String email;

    @NotNull
    @NotEmpty
    private String name;

    //@NotNull
    //@NotEmpty
    @DateTimeFormat(pattern="yyyy-MM-dd")
    private Date dateOfBirth;

    private CustomDate customDateOfBirth;

    @NotNull
    @NotEmpty
    private String password;

    @NotNull
    @NotEmpty
    private String matchingPassword;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getDateOfBirth() {
        Calendar cal = Calendar.getInstance();
        cal.set(customDateOfBirth.getYear(), customDateOfBirth.getMonth(), customDateOfBirth.getDay());
        return cal.getTime();
    }

    public void setDateOfBirth(Date dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getMatchingPassword() {
        return matchingPassword;
    }

    public void setMatchingPassword(String matchingPassword) {
        this.matchingPassword = matchingPassword;
    }

    @Transient
    public CustomDate getCustomDateOfBirth() {
        return customDateOfBirth;
    }

    public void setCustomDateOfBirth(CustomDate customDateOfBirth) {
        this.customDateOfBirth = customDateOfBirth;
    }

}

请注意,有一个名为customDateOfBirth的新字段,customDateOfBirth的getter方法有一个@Transient注释,可防止JPA将其插入数据库。如果你想跳过它通过Jackson序列化,也可以在getter方法上放一个@JsonIgnore注释。

getDateOfBirth方法中有一个自定义逻辑,它将customDateOfBirth转换为Date类型。

像这样修改你的html:

<div class="form-group row">
    <label for="confirm" class="col-sm-2 col-form-label">Date of
        Birth</label>
    <div class="col-sm-10">
        <input id="day" type="text" th:field="*{customDateOfBirth.day}" />
    </div>
</div>
<div class="form-group row">
    <label for="confirm" class="col-sm-2 col-form-label"></label>
    <div class="col-sm-10">
        <input id="month" type="text" th:field="*{customDateOfBirth.month}" />
    </div>
</div>
<div class="form-group row">
    <label for="confirm" class="col-sm-2 col-form-label"></label>
    <div class="col-sm-10">
        <input id="year" type="text" th:field="*{customDateOfBirth.year}" />
    </div>
</div>

请注意,customDateOfBirth用于html模板。