假设以下动作类。
@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>
(or <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 操作之后有一种方法可以获取此列表。由于从数据库中获取此列表的成本很高,因此该列表应仅在每个操作(插入、编辑、更新、删除)完成后初始化一次。