【问题标题】:Wrong date format when submit Spring form提交 Spring 表单时日期格式错误
【发布时间】:2016-01-18 15:59:52
【问题描述】:

我有一个使用 Spring MVC 和 Thymeleaf 的项目。 我需要根据每个用户的喜好以不同的格式显示日期。 例如,UserA 想显示像 MM/dd/yyyy 这样的日期,而 UserB 要显示像 dd/MM/yyyy 这样的日期。

为此,我使用了这个 thymeleaf 参数:

th:value="${#dates.format(myDate, dateFormat)}"

“dateFormat”值取决于用户偏好。这很好用。

我的问题是日期输入在表单中,当我提交表单时,它没有采用好的格式。我总是得到 MM/dd/yyyy。

如果我选择 dd/MM/yyyy 格式并输入 18/01/2016,在我的 spring 控制器中,我会获得“Thu Jun 01 00:00:00 CEST 2017”,它对应于 dd/ 中的 01/06/2017月/年。

我可以做些什么来获得我想要的格式的日期?

这是我的代码:

<form th:action="@{/test}" th:object="${filter}" th:method="POST">
    <input type="date" th:type="date" class="form-control" th:id="myDate"
           th:name="myDate" th:value="${#dates.format(filter.myDate, dateFormat)}"/>
</form>

控制器:

@RequestMapping(value = "/test", method = RequestMethod.POST)
public String myTest(@ModelAttribute Filter filter, Model model) {

    Systeme.out.println(model.dateFormat);
    // dd/MM/yyyy

    Systeme.out.println(filter.myDate.toString());
    // Thu Jun 01 00:00:00 CEST 2017

    return "test";
}

【问题讨论】:

  • 任何参考?....

标签: forms date spring-mvc formatting thymeleaf


【解决方案1】:

你可以注释 Date 属性

    @DateTimeFormat(pattern = "dd/MM/yyyy")
    private Date dob;

自 Spring 3.2 起不再依赖 Joda

【讨论】:

  • @DateTimeFormat 注释在 Bean 中为我工作。这是最简单的答案,而且确实有效!
【解决方案2】:

经过一天的研究,我发现Spring读取了Web请求中发送的值,并尝试将其与Filter对象绑定。

对于日期值,它会查找具有“MM/dd/yyyy”格式的值。如果您发送具有其他格式的值,则它不起作用。

要解决这个问题,可以使用注解“InitBinder”。

@InitBinder
private void dateBinder(WebDataBinder binder) {
    //The date format to parse or output your dates
    SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormat());
    //Create a new CustomDateEditor
    CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
    //Register it as custom editor for the Date type
    binder.registerCustomEditor(Date.class, editor);
}

这个方法针对每个网络请求执行。在这里,我调用我的“dateFormat()”方法来获取用户偏好中的格式,并向 Spring 说它在 Web 请求中找到的所有 java.util.Date 都具有这种格式。

这是我的完整代码:

过滤器:

import java.util.Date;

@lombok.Data
public class TestDateFilter {
    private Date myDate;

    public TestDateFilter() {
        this.myDate = new Date();
    }
}

控制器:

@RequestMapping(value = "/testdate")
public String testDate(Model model) {
    model.addAttribute("filter", new TestDateFilter());
    return "testdate";
}

@RequestMapping(value = "/testdate", method = RequestMethod.POST)
public String testDatePost(@ModelAttribute("filter") TestDateFilter filter, Model model) {
    System.out.printf(filter.getLoadingStartDate().toString());
    System.out.printf(dateFormat());
    return "testdate";
}

@ModelAttribute("dateFormat")
public String dateFormat() {
    return userPreferenceService.getDateFormat();
}

@InitBinder
private void dateBinder(WebDataBinder binder) {
    //The date format to parse or output your dates
    SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormat());
    //Create a new CustomDateEditor
    CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
    //Register it as custom editor for the Date type
    binder.registerCustomEditor(Date.class, editor);
}

HTML:

    <form th:action="@{/testdate}" th:object="${filter}" th:method="POST">
        <div class="row">
            <div class="col-xs-12 col-sm-6">
                <div class="input-group date">
                    <input type="date" th:type="date" class="form-control"
                           th:id="loadingStartDate" th:name="loadingStartDate"
                           th:value="${#dates.format(filter.loadingStartDate, dateFormat)}" />
                </div>
            </div>
        </div>
        <div class="row">
            <div class="form-group">
                <div class="col-xs-12 col-sm-12">
                    <button type="submit" class="btn btn-primary btn-lg pull-right">
                        submit
                    </button>
                </div>
            </div>
        </div>
    </form>

【讨论】:

  • 我喜欢这个解决方案,因为它允许我为不同的语言环境设置不同的格式
  • 我遇到了一个导致我提出这个问题的问题。我将用你的例子来说明这个问题。在testDatePost() 中,如果我在返回之前在模型上设置@ModelAttribute("filter") TestDateFilter filter(以防出现错误),则日期格式会回到默认的Date.toString() 值。例如,我的 @InitBinder 值产生了 2018-05-15 19:04:03.0 但是当我从 POST 传回时,它作为 Tue May 15 19:04:03 PDT 2018 传递,这就是这个答案在最初加载表单的情况下所修复的。这只是解决了我的问题的一半。
  • 谢谢分享!我遇到了同样的问题,这个答案在第一次尝试时有效
【解决方案3】:

我认为有麻烦,因为 Spring 不明白输入的值是日期。 你的变量 myDate 是 java.util.Date 类型吗?

如果是,请尝试注册这样的格式化程序:

package your.pack.formatter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.format.Formatter;

public class DateFormatter implements Formatter<Date> { 

    final String defaultDateFormat = "dd.MM.yyyy";

    @Override
    public String print(Date object, Locale locale) {
        return new SimpleDateFormat(defaultDateFormat).format(object);
    }

    @Override
    public Date parse(String text, Locale locale) throws ParseException {
        return DateUtils.parseDate(text, defaultDateFormat);
    }
}

然后在你的配置中注册它:

@Configuration
public class ConversionServiceConfig extends WebMvcConfigurerAdapter {

   @Bean
   public DateFormatter dateFormatter() {
       return new DateFormatter();
   }

   @Override
   public void addFormatters(FormatterRegistry registry) {
       registry.addFormatter(dateFormatter());
   }
}

但我不知道如何让它按照你的意愿动态运行......

用户偏好是存储在数据库中还是存储在属性中?

【讨论】:

  • 我的变量是 java.util.Date 并且我将首选项存储在数据库中。在我的控制器中,我有一个带有“RequestMapping”的方法,它调用服务来获取首选项。我终于通过使用“InitBinder”注释找到了解决方案。
猜你喜欢
  • 2018-11-11
  • 1970-01-01
  • 2019-12-24
  • 1970-01-01
  • 2019-12-02
  • 1970-01-01
  • 2018-06-22
  • 1970-01-01
相关资源
最近更新 更多