Per*_*rik 8 service grails layer
当我想要更新非简单域对象时,我在组织代码时遇到问题.问题是分离控制器和服务层的职责.
更明确地,假设我们有一个域类Client,它依赖于其他域类,如Address等.
在视图中有一个用于编辑某些Clients属性的gsp,包括一些嵌套属性,如Address上的street.
当我想更新这些字段时,我在Controller上调用update方法(在本例中为ClientController).
我喜欢在验证时来自域类错误的功能.就像我在控制器中写道一样
Client client = Client.get(params.id)
client.properties = params
client.validate()
Run Code Online (Sandbox Code Playgroud)
如果客户端现在有错误,则很容易在编辑视图中显示它们.
但是,我认为更新,保存和从数据库(Client.get(theId))获取客户端应该由服务层处理.在我的情况下,我必须在更新客户端之前更新或创建其他域对象(如地址).
所以我的一个问题是API应该如何看待服务层?
public ... updateClient(…)
Run Code Online (Sandbox Code Playgroud)
在文献中,他们有一个简单的例子来更新一个人的年龄.因此,他们的API由人的身份和新时代组成.但是,在我的情况下,我从视图中得到大约十个参数,它们只是客户端所有属性的子集,我不知道哪一个已经改变了.
我该如何结合这些?不同层面对更新有哪些责任?关于更新,服务层的API应该如何?
如果在某个地方有一个很好的参考实现,我会很乐意研究它.很多时候,服务层不幸被完全或部分忽略.
这个难题的缺失部分是命令对象.这些类表示API与服务的合约,并使您能够为视图和验证创建具体的类.我们来看一个例子.
给定一个域类Client,作为一个Address和几个Phone实例,您的服务层可能如下所示:
...
class ClientService {
def updateClient(ClientUpdateCommand cmd) {
..
}
}
...
Run Code Online (Sandbox Code Playgroud)
ClientUpdateCommand看起来像这样:
@grails.validation.Validateable
class ClientUpdateCommand {
Long id
String name
List<PhoneUpdateCommand> phoneNumbers = []
AddressUpdateCommand address = new AddressUpdateCommand()
...
static constraints {
id(nullable: false)
name(nullable: false, blank: false, size:1..50)
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
您将注意到此命令对象由其他命令对象组成,并具有验证约束.您似乎在复制域类,但我发现应用程序越复杂,域类和命令对象之间就会出现更多差异.
接下来是在控制器和视图中使用命令对象.控制器方法可能如下所示:
Class ClientController {
...
def clientService
...
def edit(ClientUpdateCommand cmd) {
...
cmd = clientService.load(cmd.id)
Map model = [client: cmd]
render(view: 'edit', model: model)
}
def update(ClientUpdateCommand cmd) {
Map model = [client: cmd]
if (cmd.hasErrors() {
render(view: 'edit', model: model]
return
} else {
clientService.update(cmd)
...
}
...
}
}
Run Code Online (Sandbox Code Playgroud)
我已经离开了很多控制器,因为我不想让你了解细节,而是展示命令对象如何替换域实例.在某些方面,它会有一些工作,但它会使您完全远离操纵域类并将其委托给您创建的服务.您还会注意到命令对象替换了视图模型的域类实例.我不打算给你任何关于GSP的例子,因为在使用这样的命令对象时它们确实没有太大变化.
我确信可能会有关于这个主题的书籍的整个章节,但希望这会给你一些见解,你可以看到你的问题的答案是:命令对象.
| 归档时间: |
|
| 查看次数: |
812 次 |
| 最近记录: |