假设有以下动作类。
@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value="struts-default")
public final class TestAction extends ActionSupport implements Serializable, ValidationAware, Preparable
{
private Long currentPage=1L;
//This method is called on page load.
//Validation is skipped, location is set to a valid action, not "redirectAction", the request is dispatched.
//It is mapped to an action of <s:form>.
public String load() throws Exception
{
//Nothing to see here. Leave it empty.
return ActionSupport.SUCCESS;
}
//Assuming necessary validators and action whose result type is set to "redirectAction".
//It is mapped to an action of <s:submit>.
public String insert()
{
//Do something to either add or update data in a model based on a conditional check.
return ActionSupport.SUCCESS;
}
//Assuming necessary validators and action whose loction is set to a valid action. not "redirectAction".
//The request is dispatched/forwarded.
//It is mapped to an action of <s:a>.
public String edit()
{
//Nothing to see here. Leave it empty.
return ActionSupport.SUCCESS;
}
//Assuming necessary validators and action whose result type is set to "redirectAction".
//It is mapped to an action of <s:submit>.
public String delete()
{
//Do something to delete data from a model.
return ActionSupport.SUCCESS;
}
@Override
public void prepare() throws Exception
{
list= service.getList((int)(currentPage-1)*pageSize, pageSize);
}
}
我已经删除了注释和其他内容以避免代码噪音。映射到这些方法的操作使用paramsPrepareParamsStack
拦截器。
此处,当与insert()
方法关联的操作(例如,由<s:submit>
完成)触发时,结果将是重定向操作。因此,将创建动作类的新实例,该实例导致执行load()
方法,这又导致prepare()
方法再次执行。更新和删除时会发生同样的事情。
一旦与prepare()
(或<s:submit>
)相关联的操作被触发,就会首先执行<s:link>
方法,然后在重定向请求时再次执行{这可以理解,因为重定向请求导致创建动作类的新实例,该实例将导致执行与load()
方法关联的操作,并且在每个操作上执行一次prepare()
。
prepare()
方法中唯一的行有昂贵的操作。为了防止getList()
方法被执行两次,我做了一些条件检查,如下所示。
@Override
public void prepare() throws Exception
{
String actionName = ActionContext.getContext().getName();
if(actionName.equals("load")||actionName.equals("edit"))
{
list= service.getList((int)(currentPage-1)*pageSize, pageSize);
}
}
此方法可能会有更多条件检查和复杂代码。
这样做仍然不够。如果由于条件而发生任何验证/转换错误,则不会初始化该列表。在出现任何错误后,hasErrors()
方法中的hasActionErrors()
,hasFieldErrors()
和prepare()
都不会被评估为真。这需要在validate()
方法中加载列表,如下所示。
@Override
public void validate()
{
if(hasErrors())
{
list= service.getList((int)(currentPage-1)*pageSize, pageSize);
}
}
这现在符合要求,但看起来非常难看有这样的条件检查,不能被认为是一个好方法。
是否有更好的方法可以保证在执行诸如插入,更新,删除等操作的请求之后,只保留从数据库中检索列表一次的某种机制?
它应该独立于每个请求在场景后面执行的操作数量。尽管存在一些转换/验证错误,但应该在请求完成之前仅检索一次列表。
@Before
,@BeforeResult
,@After
注释似乎无法解决这种情况。
在用于检索/初始化列表的validate()
方法中使用此类代码似乎不是一个好习惯。
我希望有一种方法可以在 CRUD操作之后获取此列表。由于从数据库中获取此列表的成本很高,因此在 每个操作(插入,编辑,更新,删除)完成后,只应初始化此列表。
答案 0 :(得分:3)
执行为每个操作执行的prepare
方法,诸如填充列表之类的繁重操作不是一个好方法。因为并非所有操作都需要执行此类操作。但是当与验证一起使用时,根本不执行任何操作。如果发生验证错误,则返回INPUT
结果。此结果是您的用例中的dispatcher
结果,并且需要在执行此结果之前填充列表。在validate
方法结束并返回validate
结果之前,您正在使用INPUT
方法手动检查验证错误,然后重新填充列表。这个逻辑已经由workflow
拦截器实现,defaultStack
拦截器是public String input() throws Exception {
list = service.getList((int)(currentPage-1)*pageSize, pageSize);
return INPUT;
}
的成员。您可以配置此拦截器以在发生验证错误时调用方法。在此方法中,您可以重新填充列表。
workflow
现在,您应该将此方法配置为与insert()
拦截器一起使用,方法是将注释放入您的crud方法delete()
,@InputConfig(methodName="input")
。
edit()
在load()
和input()
方法中,如果操作返回调度程序结果,则可以手动调用INPUT
,可能与{{1}}结果位置相同。