[英]Performing CRUD operations in an action class along with the prepare() method in Struts2
假設有以下動作類。
@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>
)時,結果將是重定向操作。 因此,將創建 action 類的一個新實例,這將導致執行load()
方法,這又導致再次執行prepare()
方法。 更新和刪除時也會發生同樣的事情。
prepare()
方法在與<s:submit>
(或<s:link>
)相關聯的動作被觸發時首先執行,然后在請求重定向時再次執行(這可以理解,因為請求的重定向導致創建 action 類的一個新實例,它會導致執行與load()
方法關聯的 action,並且prepare()
在每個 action 上執行一次)。
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
注釋似乎都@BeforeResult
這種情況。
在用於檢索/初始化列表的validate()
方法中使用此類代碼似乎不是一個好習慣。
我希望有一種方法可以在CRUD 操作后獲取此列表。 由於從數據庫獲取此列表的成本很高,因此該列表應僅在每次操作(插入、編輯、更新、刪除)完成后初始化一次。
在為每個動作執行的prepare()
方法中prepare()
,諸如填充列表之類的繁重操作不是一個好方法。 因為並不是所有的動作都需要執行這樣的操作。
但是當與驗證一起使用時,根本不執行任何操作。 如果發生驗證錯誤,則返回INPUT
結果。 此結果是您的用例中的dispatcher
結果,它需要在執行此結果之前填充列表。
在validate
方法結束並返回INPUT
結果之前,您正在validate
方法中手動檢查驗證錯誤,然后重新填充列表。
此邏輯已由作為defaultStack
成員的workflow
攔截器實現。 您可以配置此攔截器以在發生驗證錯誤時調用方法。 在此方法中,您可以重新填充列表。
public String input() throws Exception {
list = service.getList((int)(currentPage-1)*pageSize, pageSize);
return INPUT;
}
現在,您應該通過在 crud 方法insert()
、 delete()
放置注釋來配置此方法以與workflow
攔截器一起使用。
@InputConfig(methodName="input")
在edit()
和load()
方法中,如果操作返回調度程序結果(可能與INPUT
結果相同的位置load()
您可以手動調用input()
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.