我想知道,在脚手架控制器和视图中,您在“创建”页面中填写的字段如何在保存操作之前更新到您的域类实例。我正在使用Grails 2.4.4。
举一个例子,我有一个名为Customer的类,我生成控制器并以默认方式查看所有内容。
class Customer {
String name;
String email;
String address;
String mobile;
}
当您运行应用程序并在生成的绿色样式索引页面中,单击“创建新客户”时,将创建一个客户实例,因为链接将转到“创建”操作。
<ul>
<li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
<li><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
</ul>
在控制器中:
def create() {
log.info "A customer object is created here.";
Customer c=new Customer(params)
respond c
}
但是现在你还没有在所有字段中填写表单!在create.gsp中填写表单后,该链接将直接指向“保存”操作。
<g:form url="[resource:customerInstance, action:'save']" >
<fieldset class="form">
<g:render template="form"/>
</fieldset>
<fieldset class="buttons">
<g:submitButton name="create" class="save" value="${message(code: 'default.button.create.label', default: 'Create')}" />
</fieldset>
</g:form>
但是在保存操作中,我看到与表单上的字段设置字段无关。 它在哪里完成?
@Transactional
def save(Customer customerInstance) {
if (customerInstance == null) {
notFound()
return
}
if (customerInstance.hasErrors()) {
respond customerInstance.errors, view:'create'
return
}
customerInstance.save flush:true
//omit everything after save here
}
答案 0 :(得分:5)
Grails使用Data Binding自动为您完成此操作。 Grails控制器可以采用两类参数:基本对象和复杂对象。默认行为是在适用的情况下按名称将HTTP请求参数映射到操作参数。例如,假设我们有一个像这样的控制器:
def doSomething(Integer magicNumber) {
println "The magic number is $magicNumber"
}
以及包含如下字段的视图:
<g:textField name="magicNumber" value="${magicNumber}" />
当表单提交到doSomething
操作时,Grails将自动获取magicNumber
请求参数,将其从String转换为Integer并将其传递给操作。
复杂类型(如域对象)被视为command objects。对于数据绑定,命令对象以与基本对象类似的方式起作用。请注意,在您的代码中,保存操作如何将Customer
实例作为参数?在幕后,Grails获取HTTP请求参数并将这些参数绑定到给定对象的属性,在本例中为Customer
。来自文档:
在执行控制器操作之前,Grails将自动创建命令对象类的实例,并通过绑定请求参数来填充其属性。
换句话说,Grails将查看所有传入的请求参数,并尝试将这些参数绑定到您已声明为该操作的参数的对象上的属性。此外,它还会为您执行验证。它与:
基本相同@Transactional
def save() {
Customer customerInstance = new Customer(params)
customerInstance.validate()
if (customerInstance == null) {
notFound()
return
}
if (customerInstance.hasErrors()) {
respond customerInstance.errors, view:'create'
return
}
customerInstance.save flush:true
//omit everything after save here
}