我正在尝试正确使用命令对象。我有一些问题。
给定一个通用域,例如:
package com.foo
class Ticket {
Customer customer
Product product
Defect defect
Solution solution
String comment
static constraints = {
customer nullable:false
product nullable:false
defect nullable:true
solution nullable:true
comment nullable:true
}
}
然后,考虑以下Ticket 形式的规则:
- 客户只能在创建时选择。在编辑时,不能显示选择,而是显示标签;
- 产品只能在创建时选择。然而,在编辑时,选择必须显示为 disabled;
- 可以在创建或编辑时选择缺陷;
- 无论如何都不能以这种形式设置解决方案。
- 评论只能由具有特定角色的用户通知(例如使用 SpringSecurity)。如果用户没有这样的角色,则文本区域必须显示为禁用。
现在,我想知道的是:
使用 CommandObject 处理这种情况的最佳方法是什么?
- 1 个单一的 CommandObject 用于两个操作?
- 1 个特定于每个操作的 CommandObject?
- 在单个 CommandObject 的情况下,如何防止用户入侵程序,例如传递禁止的参数?
实施表格规则的最佳方法是什么?也就是说,在每种情况下显示/启用/禁用哪个字段。
- 这种情况有什么模式或建议吗?
- 这些规则是否应该以实际形式编写?
- 或者表格应该“问”某人吗?也许是 CommandObject?还是域实例本身?
例如,考虑这个表单的要点:
<div class="fieldcontain ${hasErrors(bean:ticketInstance, field:'customer', 'error')} required">
<label for="customer">
<g:message code="ticket.customer.label" default="Customer" />
<span class="required-indicator">*</span>
</label>
<g:if test="${ticketInstance.id}">
<span class="label read-only">${ticketInstance.customer.name}</span>
</g:if>
<g:else>
<g:select id="customer" name="customer.id" from="${Customer.list()}" optionKey="id"
required="" disabled="" value="${ticketInstance?.customer?.id}" class="many-to-one"/>
</g:else>
</div>
在这种情况下,没有太大问题,因为检查相当简单。那是:
<g:if test="${ticketInstance.id}">
...
但是,考虑一个更复杂的规则。就像是:
<g:if test="${ticketInstance.id && currentUser.granted('SOME_RULE') && ticketInstance.someField != null}">
...
等等。
现在,这种方法存在一些问题:
- 它相当冗长,因此容易出错。
- 假设这样的规则在其他领域之间共享。在这种情况下,我必须以某种方式管理它(局部变量、复制代码等)。
- 另外,为此,我需要在我的 TicketCommand 中有一个属性“Id”,我不知道这是否是个好主意。
因此,我想知道是否有任何模式或建议可用于改进这些场景。也就是说,可以封装这种复杂性的东西。例如:
<g:if test="${cmd.customerAllowed}">
...
CommandObject 可能是这样的:
@Validateable
class TicketCreateCommand {
def currentUser //injected somehow..
Customer customer
Product product
Defect defect
String comment
static constraints = {
importFrom Ticket
}
boolean isNew() {
true
}
boolean isCustomerAllowed() {
this.new && currentUser.granted('SOME_RULE') && this.someField != null
//some more rules if necessary..
}
boolean isSomeFieldAllowed() {
//rules for creating
}
}
还有一个用于编辑的 CommandObject:
@Validateable
class TicketEditCommand {
def currentUser //injected somehow..
Customer customer
Product product
Defect defect
String comment
static constraints = {
importFrom Ticket
}
boolean isNew() {
false
}
boolean isCustomerAllowed() {
this.new && currentUser.granted('SOME_RULE') && this.someField != null
//some more rules if necessary..
}
boolean isSomeFieldAllowed() {
//rules for editing
}
}
CommndObject 可以承担这样的责任吗?如果没有,还有其他更好的方法来集中这些复杂性吗?另外,正如我之前所说,物业客户无法设置更新。如何处理?
嗯,我想这差不多。
我很感激任何意见和建议。一些教程的任何链接也会很棒。
PS: 想看的朋友可以在github上找到完整的项目。