Grails中如何将ID列表绑定到Command Object命令对象?
嘿,这个问题我熟!你现在遇到的核心问题是:表单提交的是逗号分隔的字符串(比如"4, 6, 10..."),但你的EmailCommand里的ids是List<Registration>类型——Grails(我猜你用的是Grails,因为有Command Object的写法)没办法自动把字符串直接转换成实体类的列表,所以需要我们手动加一层转换逻辑。
下面给你两种常用的解决方案,你可以根据自己的场景选:
方案一:在Command Object里手动处理(快速简单)
这种方法不需要额外配置,直接在Command Object里先接收字符串,再转换成Registration列表:
- 修改
EmailCommand类,先接收表单提交的字符串,然后在绑定完成后处理转换:
class EmailCommand { // 先接收表单传来的逗号分隔字符串 String ids // 最终要使用的Registration列表 List<Registration> registrations // 绑定完成后自动触发的方法,用来转换数据 def afterPropertiesSet() { if (ids) { // 1. 分割字符串,去掉空格,过滤掉非数字的内容 def idList = ids.split(/,\s*/) .collect { it.trim() } .findAll { it.isLong() } .collect { it as Long } // 2. 批量查询Registration实例(比循环get更高效) registrations = Registration.getAll(idList).findAll() // findAll()用来过滤掉不存在的ID对应的null值 } else { registrations = [] } } }
- 然后在控制器里直接使用转换后的列表:
def process(EmailCommand cmd) { cmd.registrations.each { registration -> // 这里处理每个Registration实例 } }
方案二:自定义PropertyEditor(全局复用)
如果你在多个地方都需要把逗号分隔的ID字符串转换成Registration列表,推荐用这种全局绑定的方式,一劳永逸:
- 创建一个自定义的PropertyEditor,负责把字符串转成
List<Registration>:
import java.beans.PropertyEditorSupport import grails.gorm.transactions.Transactional @Transactional class RegistrationListEditor extends PropertyEditorSupport { @Override void setAsText(String text) { if (!text) { setValue([]) return } // 处理字符串,批量查询实例 def idList = text.split(/,\s*/) .collect { it.trim() } .findAll { it.isLong() } .collect { it as Long } def registrations = Registration.getAll(idList).findAll() setValue(registrations) } }
- 注册这个编辑器,让Grails知道什么时候用它。在
grails-app/conf/spring/resources.groovy里添加:
beans = { customPropertyEditorRegistrar(org.springframework.beans.PropertyEditorRegistrar) { registerCustomEditors = { registry -> // 给EmailCommand里的ids属性注册编辑器 registry.registerCustomEditor(List, "ids", new RegistrationListEditor()) // 如果想全局所有List<Registration>类型都生效,可以换成: // registry.registerCustomEditor(List<Registration>, new RegistrationListEditor()) } } }
- 这下你的
EmailCommand和控制器代码完全不用改!保持原来的样子就行:
// Command Object class EmailCommand { List<Registration> ids } // 控制器 def process(EmailCommand cmd){ cmd.ids.each { registration -> // 直接处理每个Registration实例 } }
小提示:如果你的Registration是域类,用getAll()比循环调用get()性能好很多,因为它只会发一次SQL查询,而循环get会发N次。
内容的提问来源于stack exchange,提问作者kofhearts
相关产品推荐
相关产品推荐

