Data binding 从控制器中的参数绑定Grails日期

Data binding 从控制器中的参数绑定Grails日期,data-binding,date,grails,groovy,controller,Data Binding,Date,Grails,Groovy,Controller,为什么通过grails控制器中的参数从视图中提取日期如此困难 我不想像这样手工提取日期: instance.dateX = parseDate(params["dateX_value"])//parseDate is from my helper class 我只想使用instance.properties=params 在模型中,类型是java.util.Date,在参数中是所有信息:[dateX\u month:'value',dateX\u day:'value',…] 我在网上搜索了一

为什么通过grails控制器中的参数从视图中提取日期如此困难

我不想像这样手工提取日期:

instance.dateX = parseDate(params["dateX_value"])//parseDate is from my helper class
我只想使用
instance.properties=params

在模型中,类型是
java.util.Date
,在参数中是所有信息:
[dateX\u month:'value',dateX\u day:'value',…]

我在网上搜索了一下,却什么也没找到。我希望Grails1.3.0能有所帮助,但还是一样

我不能也不会相信手工提取日期是必要的

Grails版本>=2.3
Config.groovy
中的设置定义了将参数绑定到
date

grails.databinding.dateFormats = [
        'MMddyyyy', 'yyyy-MM-dd HH:mm:ss.S', "yyyy-MM-dd'T'hh:mm:ss'Z'"
]
将按照列表中包含的顺序尝试在
grails.databinding.dateFormats
中指定的格式

您可以使用
@BindingFormat

import org.grails.databinding.BindingFormat

class Person { 
    @BindingFormat('MMddyyyy') 
    Date birthDate 
}
Grails版本<2.3 我不能也不会相信手工提取日期是必要的

你的固执得到了回报,早在Grails1.3之前就可以直接绑定日期了。这些步骤是:

(1)创建一个类,为日期格式注册编辑器

import org.springframework.beans.PropertyEditorRegistrar
import org.springframework.beans.PropertyEditorRegistry
import org.springframework.beans.propertyeditors.CustomDateEditor
import java.text.SimpleDateFormat

public class CustomDateEditorRegistrar implements PropertyEditorRegistrar {

    public void registerCustomEditors(PropertyEditorRegistry registry) {

        String dateFormat = 'yyyy/MM/dd'
        registry.registerCustomEditor(Date, new CustomDateEditor(new SimpleDateFormat(dateFormat), true))
    }
}
(2)通过在
Grails app/conf/spring/resources.groovy中注册以下bean,让Grails意识到这个日期编辑器

beans = {
    customPropertyEditorRegistrar(CustomDateEditorRegistrar)
}
(3)现在,当您以
yyyy/MM/dd
格式发送名为
foo
的参数中的日期时,它将自动绑定到名为
foo
的属性,方法如下:

myDomainObject.properties = params


您是否尝试过使用任何Grails日期选择器插件

我在这方面有很好的经验

(使用日历插件时)提交日期选择请求时,可以自动将查询参数绑定到要用请求填充的域对象

例如

您还可以解析“yyyy/MM/dd”日期字符串,如下所示

new Date().parse("yyyy/MM/dd", "2010/03/18")

@唐:谢谢你上面的回答

这里有一个替代自定义编辑器的选项,该编辑器检查第一个日期时间,然后检查日期格式

Groovy,只需在java中添加分号即可

import java.text.DateFormat
import java.text.ParseException
import org.springframework.util.StringUtils
import java.beans.PropertyEditorSupport

class CustomDateTimeEditor extends PropertyEditorSupport {
    private final java.text.DateFormat dateTimeFormat
    private final java.text.DateFormat dateFormat
    private final boolean allowEmpty

    public CustomDateTimeEditor(DateFormat dateTimeFormat, DateFormat dateFormat, boolean allowEmpty) {
        this.dateTimeFormat = dateTimeFormat
        this.dateFormat = dateFormat
        this.allowEmpty = allowEmpty
    }

    /**
     * Parse the Date from the given text, using the specified DateFormat.
     */
    public void setAsText(String   text) throws IllegalArgumentException   {
        if (this.allowEmpty && !StringUtils.hasText(text)) {
            // Treat empty String as null value.
            setValue(null)
        }
        else {
            try {
                setValue(this.dateTimeFormat.parse(text))
            }
            catch (ParseException dtex) {
                try {
                    setValue(this.dateFormat.parse(text))
                }
                catch ( ParseException dex ) {
                    throw new IllegalArgumentException  ("Could not parse date: " + dex.getMessage() + " " + dtex.getMessage() )
                }
            }
        }
    }

    /**
     * Format the Date as String, using the specified DateFormat.
     */
    public String   getAsText() {
        Date   value = (Date) getValue()
        return (value != null ? this.dateFormat.format(value) : "")
    }
}

Grails2.1.1在params中有一个新方法,可以方便地进行空安全解析

def val = params.date('myDate', 'dd-MM-yyyy')
// or a list for formats
def val = params.date('myDate', ['yyyy-MM-dd', 'yyyyMMdd', 'yyMMdd']) 
// or the format read from messages.properties via the key 'date.myDate.format'
def val = params.date('myDate')

在doc中找到它

Grails版本>=2.3

将字符串转换为日期的localeAware版本

在src/groovy中:

package test

import org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest
import org.grails.databinding.converters.ValueConverter
import org.springframework.context.MessageSource
import org.springframework.web.servlet.LocaleResolver

import javax.servlet.http.HttpServletRequest
import java.text.SimpleDateFormat

class StringToDateConverter implements ValueConverter {
    MessageSource messageSource
    LocaleResolver localeResolver

    @Override
    boolean canConvert(Object value) {
        return value instanceof String
    }

    @Override
    Object convert(Object value) {
        String format = messageSource.getMessage('default.date.format', null, "dd/MM/yyyy", getLocale())
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format)
        return simpleDateFormat.parse(value)
    }

    @Override
    Class<?> getTargetType() {
        return Date.class
    }

    protected Locale getLocale() {
        def locale
        def request = GrailsWebRequest.lookup()?.currentRequest
        if(request instanceof HttpServletRequest) {
            locale = localeResolver?.resolveLocale(request)
        }
        if(locale == null) {
            locale = Locale.default
        }
        return locale
    }
}
bean的名称“defaultDateConverter”非常重要(要覆盖默认的日期转换器)

Grails版本>=3.x 您可以按照以下语法在application.yml中设置日期格式:

grails:
  databinding:
    dateFormats:
      - 'dd/MM/yyyy'
      - 'dd/MM/yyyy HH:mm:ss'
      - 'yyyy-MM-dd HH:mm:ss.S'
      - "yyyy-MM-dd'T'hh:mm:ss'Z'"
      - "yyyy-MM-dd HH:mm:ss.S z"
      - "yyyy-MM-dd'T'HH:mm:ssX"

我认为显式调用
newdate.parse()
正是他想要避免的。好的,如果您直接绑定参数,您仍然需要注册一个自定义日期编辑器(如我的回复中所述)。否则,databinder怎么可能知道哪个字段是月份,哪个字段是年份(例如)。我同意日历插件是最好的日期选择器插件。是的,一定要使用参数绑定方法。new Date().parse()在其他地方可能非常有用。我认为我现在的方法非常糟糕。我首先从参数中删除日期值,如下所示:(params.remove(“datefield”))然后执行类似的操作:instance.datefield=hlpr.exDate(params[“datefield_value”]作为字符串)我知道这听起来很奇怪,但不知怎的,这是它现在工作的唯一方式…为了快速回答,我以前尝试过这个方法(在我的spring参考资料中已经有customPropertyEditorRegistrar,我看到了上面提到的旧stackoverflow问题),但不知怎么的,这对我不起作用。我的类看起来是这样的:类CustomDateEditorRegistrar实现PropertyEditorRegistrar{public void RegisterCustomomeditors(PropertyEditorRegistry registry registry){String dateFormat='dd.MM.yyyy'registry.registerCustomEditor(Date,new CustomDateEditor(new SimpleDateFormat(dateFormat),true))}并且调试器正在正确地提取它。我的dateFormat(dots)是否有问题?还是什么?我得到了以下警告:
project/src/java/customeditorregistar.java使用或覆盖了一个不推荐的API
。有什么“新”的方法吗?@zoran119我不知道。如果你打算使用java而不是Groovysorry don,你需要对上面的代码做一些小的更改。我把评论贴错了位置问:(我的评论是针对这个问题的:请注意,在最近的(2。x)版本的GRAILS中有一个影响日期绑定的bug:对于子孙后代:请注意JoDA时间插件自动实现数据绑定。我认为这是从<代码> PARAMS < /代码>中读取的,而不是“绑定日期”。似乎是最好的答案。但我测试了它并发现了一个问题。如果我的messages.properties中没有代码,Grails会引发“在code date.myDate.format下找不到消息”异常。我认为引擎应该搜索通用格式(默认的.date.format)在引发这样的异常之前。这是一个很好的解决方案,它可以改变整个应用程序的所有数据绑定,并且具有区域设置意识。我很惊讶Grails在默认情况下不会这样做,因为它符合约定而不是配置。
package test

import org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest
import org.grails.databinding.converters.ValueConverter
import org.springframework.context.MessageSource
import org.springframework.web.servlet.LocaleResolver

import javax.servlet.http.HttpServletRequest
import java.text.SimpleDateFormat

class StringToDateConverter implements ValueConverter {
    MessageSource messageSource
    LocaleResolver localeResolver

    @Override
    boolean canConvert(Object value) {
        return value instanceof String
    }

    @Override
    Object convert(Object value) {
        String format = messageSource.getMessage('default.date.format', null, "dd/MM/yyyy", getLocale())
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format)
        return simpleDateFormat.parse(value)
    }

    @Override
    Class<?> getTargetType() {
        return Date.class
    }

    protected Locale getLocale() {
        def locale
        def request = GrailsWebRequest.lookup()?.currentRequest
        if(request instanceof HttpServletRequest) {
            locale = localeResolver?.resolveLocale(request)
        }
        if(locale == null) {
            locale = Locale.default
        }
        return locale
    }
}
beans = {
    defaultDateConverter(StringToDateConverter){
        messageSource = ref('messageSource')
        localeResolver = ref('localeResolver')
    }
}
grails:
  databinding:
    dateFormats:
      - 'dd/MM/yyyy'
      - 'dd/MM/yyyy HH:mm:ss'
      - 'yyyy-MM-dd HH:mm:ss.S'
      - "yyyy-MM-dd'T'hh:mm:ss'Z'"
      - "yyyy-MM-dd HH:mm:ss.S z"
      - "yyyy-MM-dd'T'HH:mm:ssX"