gpt4 book ai didi

grails - Grails JSON View :不透明的 View 选择-在另一个目录中选择默认模板

转载 作者:行者123 更新时间:2023-12-02 15:43:17 24 4
gpt4 key购买 nike

我正在使用Grails 3.3.9和json View 1.2.10。

在另一个测试中,我有一个像这样的网址映射

    "/api/test"(resources:'test')

而且我有一个空的views / test文件夹,并且没有Test域对象。

但是我确实有一个Device域实体,并且在该目录中有一个views / device / _device.gson模板来帮助呈现设备对象。

TestController的show Action 如下所示
def show (Device device) {
if(device == null) {
render status:404
} else {
respond device}
}

这会在域模型中查找设备,然后填充到“显示参数”列表中,然后我对该设备进行响应。

但是,views / test目录中没有show.gson(它是空的)。

但是,当您在浏览器“ http://localhost:8080/api/test/1”中访问该URL时,grails将使用“views / device / _device.gson”模板来呈现响应。

这非常令人困惑,因为很难准确地确定 View 实际正在使用的 View 响应(除非您使用view:'xxx'map变量来强制使用它)。

如何/为什么返回TestController / show action响应,选择“views / device / _device.gson”模板?

最佳答案

(代表问题作者发布答案)。

步骤1)如果您创建了一个新的 Controller (我使用grails create-controller <controller>,然后编辑生成的 Controller 以从RestfulController<domain type>扩展(但不要覆盖任何方法),那么为您的 Controller 设置URL映射,在我的示例中是

"/api/org"(resources:'OrgRoleInstance')

为此,我在模型中具有相应的域类“OrgRoleInstance”。

create-controller操作还会生成一个空的 View 包“views / orgRoleInstance”(不生成gson文件)

a)如果您现在执行运行应用程序并打开网址
http://localhost:8080/api/org

那么您仍然会得到渲染的响应(像这样)!
[{"id":1,"sites":[],"domains":[],"role":{"enumType":"com.softwood.domain.OrgRoleInstance$OrgRoleType","name":"Service_Provider"},"name":"Vodafone","mags":[{"id":2}]},{"id":2,"sites":[],"domains":[],"role":{"enumType":"com.softwood.domain.OrgRoleInstance$OrgRoleType","name":"Maintainer"},"name":"Cisco","mags":[{"id":1}]},{"id":3,"sites":[],"domains":[],"role":{"enumType":"com.softwood.domain.OrgRoleInstance$OrgRoleType","name":"Supplier"},"name":"Cisco","mags":[]},{"id":4,"sites":[{"id":1},{"id":2}],"domains":[{"id":1}],"role":{"enumType":"com.softwood.domain.OrgRoleInstance$OrgRoleType","name":"Customer"},"name":"Acme","mags":[]}]

实际上,有一些“默认框架逻辑”试图呈现从RestfulController'继承的“index”(和“show”等) Action 的默认实现。即使没有预先存在的gson也可以完成此操作-不提供警告。

第2步:下一步停止应用程序(它仍在缓存先前的“默认”行为)。

现在转到空 View 目录并创建一个没有模型的“index.gson”
json ([1,2,3])

然后在您的IDE中重新启动该应用程序。现在,当它启动时,它检测到存在index.gson,并且当您调用url' http://localhost:8080/api/org'时,您得到的是静态列表[1,2,3]的呈现的json。

第3步:gson View 在后台使用静态编译,并且非常巧妙地使其完全正确。但是,在默认的RestfulController索引操作的情况下,将从域模型中选择一个OrgRoleInstances列表,并将其作为照明传递给 View 。如果您希望与 View 的数据绑定(bind)有效,那么如果您的域对象是T类型,则将返回一个 List<T>

代码库中的内部默认值是,如果您返回 List<T>以进行响应,则该 View 中的数据模型被假定为 List<T> <T>List,即,在我的示例中为

gson View 模型中的 List<OrgRoleInstance> orgRoleInstanceList。现在有了修改过的index.gson(您可以在开发模式下不停止/启动服务器的情况下进行编辑)
import com.softwood.domain.OrgRoleInstance

model {
List<OrgRoleInstance> orgRoleInstanceList
}

json {

recordCount orgRoleInstanceList.size()
}

现在,当您获取URL时,您将得到一个带有列表大小的json响应:
{"recordCount":4}

请注意,如果您像这样向模型添加额外的变量:
import com.softwood.domain.OrgRoleInstance

model {
List<OrgRoleInstance> orgRoleInstanceList
Integer orgRoleInstanceCount
}

json {

recordCount orgRoleInstanceList.size()
size orgRoleInstanceCount
}

并修改index.gson以显示新的Integer变量-则它不是默认响应操作中的数据绑定(bind)。

浏览器响应如下所示:
{"recordCount":4,"size":null}

选项4:-研究调用"template"类。建立了一个需要 List<T>的模型后,通过数据绑定(bind)构建的runTime类型就是“grails.orm.PagedResultList”的一个实例。这是一个Iterable类型。

在文档中阅读这非常令人困惑-但是,如果创建一个名为 _<file>.gson的文件,则还不清楚。然后将其视为模板gson文件。

它可以有自己的model / json,但是由于所有这些都是静态编译的,因此您必须获得完全匹配的类型,并在调用模板时(通过g.render或隐式 tmpl.<file>)在必要时声明模型变量的“名称”。

从父 View 调用模板时,可以传递 List<T>迭代模型类型,也可以在父 View 中进行迭代,然后将每个 <T>传递给模板。您必须确保传递给tmpl的模型类型在tmpl模型中声明为相同的类型。

例如假设在父 View 中为 List<T>,但在模板中为 <T>,则需要为列表中的每个项目调用tmpl。例如
如果您有一个类似“_orgRoleInstance.gson”的tmpl。

如果您具有这样的父 View (请注意声明了单个 <T>和名为'org'的模型变量
import com.softwood.domain.OrgRoleInstance

model {
OrgRoleInstance org
}
json {
id org.id
name org.name
}

然后,在父 View “index.gson”中,您需要像在列表中输入条目一样多次调用tmpl的操作,但是我必须通过传递参数来告诉框架tmpl模型变量名称为“org”一张 map 。这将按照您的期望进行渲染。
import com.softwood.domain.OrgRoleInstance

model {
List<OrgRoleInstance> orgRoleInstanceList
Integer orgRoleInstanceCount
}

orgRoleInstanceList.each { OrgRoleInstance org ->
json tmpl.orgRoleInstance(org:org)
}

如果您将tmpl变量声明为“def org”,它仍然可以工作,但是由于它是静态类型的,因此该变量作为Object的静态实例传递(运行时类型正确,但是您不能仅将属性作为静态类型来访问)是Object),并且很难整理出访问属性所需的类型。

如果希望父 View 将模型 List<T>变量传递给tmpl,则可以=,但必须确保tmpl中的模型变量为 List<T>,否则数据绑定(bind)无效。

现在,在模板中,您可以调用json并遍历List

例如像这样修改过的tmpl
import com.softwood.domain.OrgRoleInstance

model {
//OrgRoleInstance org
List<OrgRoleInstance> orgs
}
json {
id orgs.id
name orgs.name
}

以及一个经过修改的父 View ,以调用tmpl:
import com.softwood.domain.OrgRoleInstance

model {
List<OrgRoleInstance> orgRoleInstanceList
Integer orgRoleInstanceCount
}

/*
orgRoleInstanceList.each { OrgRoleInstance org ->
json tmpl.orgRoleInstance(orgs:org)
}*/

//alternate approach
json tmpl.orgRoleInstance (orgs:orgRoleInstanceList)

呈现的是:
{"id":[1,2,3,4],"name":["Vodafone","Cisco","Cisco","Acme"]}

您会注意到,只有一个json子句,因此首先迭代所有id,然后迭代所有名称。

如果这不是您想要的,则必须遍历列表以依次执行每个操作

即像这样的修改后的tmpl将依次遍历每个条目
import com.softwood.domain.OrgRoleInstance

model {
//OrgRoleInstance org
List<OrgRoleInstance> orgs
}
json (orgs) {OrgRoleInstance org ->
id org.id
name org.name
}

并在浏览器中产生
[{"id":1,"name":"Vodafone"},{"id":2,"name":"Cisco"},{"id":3,"name":"Cisco"},{"id":4,"name":"Acme"}]

对于任何对Grails Views感到困惑的人,我希望这可以说明这在URL映射之间是如何工作的(您可以使用Gradle“urlMappingsReport”来查看这些内容),并显示将哪些URL映射到了什么 Action 。然后,您需要使用与这些操作相同的名称创建的gson View ,并配置gson View 和您创建的任何tmpl,以了解处理代码时JsonViews应用的隐式行为。

关于grails - Grails JSON View :不透明的 View 选择-在另一个目录中选择默认模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54252038/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com