[英]The prepare() method is called twice, when the result type is redirect action in Struts2
我有以下動作課:
@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value="struts-default")
public final class FabricAction extends ActionSupport implements Serializable, ValidationAware, Preparable, ModelDriven<Fabric>
{
@Autowired
private final transient FabricService fabricService=null;
private static final long serialVersionUID = 1L;
private int pageSize=5;
private Long id;
private Boolean deleteOneRow;
private Boolean deleteMultipleRows;
private String message;
private List<Long>chk;
private Long deleteId;
private Long begin;
private Long end;
private Long currentPage=1L;
private Long rowCount;
private Long totalPages;
private Integer status;
private Fabric entity=new Fabric();
private List<Fabric>fabrics=new ArrayList<Fabric>();
//Getters & Setters.
@Action(value = "Fabric",
results = {
@Result(name=ActionSupport.SUCCESS, location="Fabric.jsp"),
@Result(name = ActionSupport.INPUT, location = "Fabric.jsp")},
interceptorRefs={
@InterceptorRef(value="paramsPrepareParamsStack", params={"params.acceptParamNames", "id, currentPage, rowCount, totalPages, message, status", "validation.validateAnnotatedMethodOnly", "true", "validation.excludeMethods", "load"})})
public String load() throws Exception
{
//Invokes, when the page is loaded.
return ActionSupport.SUCCESS;
}
@Action(value = "FabricPage",
results = {@Result(name=ActionSupport.SUCCESS, location="Fabric.jsp", params={"namespace", "/admin_side", "actionName", "Fabric", "currentPage", "${currentPage}"}),
@Result(name = ActionSupport.INPUT, location = "Fabric.jsp")},
interceptorRefs={
@InterceptorRef(value="conversionError"),
@InterceptorRef(value="paramsPrepareParamsStack", params={"params.acceptParamNames", "currentPage", "validation.validateAnnotatedMethodOnly", "true"})})
public String page()
{
//Invokes, when a page link is clicked.
return ActionSupport.SUCCESS;
}
@Validations(
requiredStrings={
@RequiredStringValidator(fieldName="fabricName", type= ValidatorType.FIELD, key = "fabric.name.required")},
stringLengthFields={
@StringLengthFieldValidator(fieldName="fabricName", type= ValidatorType.FIELD, minLength="2", maxLength="45", key="fabric.name.length", messageParams={"2", "45"})})
@Action(value = "AddFabric",
results = {
@Result(name=ActionSupport.SUCCESS, type="redirectAction", location="Fabric.jsp", params={"namespace", "/admin_side", "actionName", "Fabric", "currentPage", "${currentPage}", "message", "${message}", "id", "${id}", "status", "${status}"}),
@Result(name = ActionSupport.INPUT, location = "Fabric.jsp")},
interceptorRefs={
@InterceptorRef(value="conversionError"),
@InterceptorRef(value="paramsPrepareParamsStack", params={"params.acceptParamNames", "id, fabricId, fabricName, currentPage, rowCount, totalPages, status", "validation.validateAnnotatedMethodOnly", "true"})
})
public String insert()
{
//Handles insert and update operations.
return ActionSupport.SUCCESS;
}
@Action(value = "EditFabric",
results = {
@Result(name=ActionSupport.SUCCESS, location="Fabric.jsp"),
@Result(name = ActionSupport.INPUT, location = "Fabric.jsp")},
interceptorRefs={
@InterceptorRef(value="paramsPrepareParamsStack", params={"params.acceptParamNames", "id, fabricId, fabricName, currentPage", "validation.validateAnnotatedMethodOnly", "true"}),
@InterceptorRef(value="conversionError")})
public String edit()
{
//Invokes, when an edit link is clicked.
return ActionSupport.SUCCESS;
}
@Validations(
fieldExpressions={@FieldExpressionValidator(fieldName="deleteOneRow", expression="deleteOneRow==true", shortCircuit=true, key="delete.row.reject")})
@Action(value = "DeleteFabric",
results = {
@Result(name=ActionSupport.SUCCESS, type="redirectAction", location="Fabric.action", params={"currentPage", "${currentPage}", "message", "${message}", "status", "${status}"}),
@Result(name = ActionSupport.INPUT, location = "Fabric.jsp")},
interceptorRefs={
@InterceptorRef(value="paramsPrepareParamsStack", params={"params.acceptParamNames", "deleteId, deleteOneRow, currentPage, status", "validation.validateAnnotatedMethodOnly", "true"}),
@InterceptorRef(value="conversionError")})
public String deleteSingleRow()
{
//Handles deletion of a single row.
return ActionSupport.SUCCESS;
}
@Validations(
requiredFields={
@RequiredFieldValidator(type= ValidatorType.FIELD, fieldName="chk", key="delete.multiple.alert"),
@RequiredFieldValidator(type= ValidatorType.FIELD, fieldName="deleteMultipleRows", key="delete.multiple.confirm")})
@Action(value = "DeleteFabrics",
results = {
@Result(name=ActionSupport.SUCCESS, type="redirectAction", location="Fabric.jsp", params={"namespace", "/admin_side", "actionName", "Fabric", "currentPage", "${currentPage}", "message", "${message}", "status", "${status}"}),
@Result(name = ActionSupport.INPUT, location = "Fabric.jsp")},
interceptorRefs={
@InterceptorRef(value="paramsPrepareParamsStack", params={"params.acceptParamNames", "deleteMultipleRows, chk, currentPage, rowCount, totalPages", "validation.validateAnnotatedMethodOnly", "true"}),
@InterceptorRef(value="conversionError")})
public String deleteMultipleRows()
{
//Handles deletion of multiple rows.
return ActionSupport.SUCCESS;
}
public Fabric getEntity() {
return entity;
}
public void setEntity(Fabric entity) {
this.entity = entity;
}
public List<Fabric> getFabrics()
{
return fabrics;
}
@Override
public Fabric getModel()
{
return entity;
}
@Override
public void prepare() throws Exception
{
fabrics= fabricService.getList((int)(currentPage-1)*pageSize, pageSize);
}
}
在執行除與 insert()
方法關聯的insert和update以外的所有操作(它們都與被映射到<s:submit>
動作的insert()
關聯)時, prepare()
方法僅執行一次。
在執行插入或更新時,可以看到 prepare()
方法被調用了兩次。為什么會這樣?
如果@Result()
的type="redirectAction"
,則prepare()
方法將執行兩次。 @Result
type
設置為redirectAction
時,是否有一種方法可以防止prepare()
方法執行兩次?
選擇結果type
或location
出錯。 因為"Fabric.jsp"
或"Fabric.action"
不是有效的動作名稱。
@Result(name=ActionSupport.SUCCESS, type="redirectAction", location="Fabric.jsp",
應該是dispatcher
結果
@Result(name=ActionSupport.SUCCESS, location="Fabric.jsp",
或redirectAction
結果
@Result(name=ActionSupport.SUCCESS, type="redirectAction", location="Fabric"
如果使用redirectAction
結果類型,則默認情況下會創建新的動作類實例,在該實例中,在動作之前執行prepare
方法。 如果打印的hashCode()
應該不同(即使動作名稱不同hashCode()
也可以進行檢查。 因此,沒有調用兩次的prepare
方法,因為它僅在每個動作的堆棧中prepare
攔截器。 另一方面,如果使用paramsPrepareParamsStack
,則兩次調用params
攔截器:在prepare
攔截器之前和之后。
我遇到了同樣的問題,最終發現我在多個地方引用了一個攔截器堆棧。 就您而言,您似乎在課程級別上:
@ParentPackage(value="struts-default")
,我相信它使用默認堆棧。
然后在@Action級別,您可以引用paramsPrepareParamsStack
:
interceptorRefs={
@InterceptorRef(value="paramsPrepareParamsStack"...)})
在我的特定情況下,我的Action類擴展了BaseAction類。 我在兩個地方都聲明了@InterceptorRef
批注。 BaseAction(已引用第一個攔截器堆棧):
@Namespace("/")
@InterceptorRef("myCustomStack")
@Results({ @Result(name = "cancel", location = "${previousPageLink}", type = "redirectAction", params = {
}) })
public class BaseAction extends ActionSupport implements ServletRequestAware, ParameterAware,
SessionAware {
...
}
然后,在動作類中,我再次有了攔截器ref(“ myCustomStack”)。 在我的HomeAction類中刪除攔截器引用堆棧對我來說解決了這個問題。
@Namespace("/")
@InterceptorRefs({
@InterceptorRef(value = "store", params = {"operationMode", "RETRIEVE"}) })
/*@InterceptorRef("myCustomStack") })*/
@Results({ @Result(name = "success", location = "home.def", type = "tiles")
})
public class HomeAction extends BaseAction implements Preparable {
...
}
最后,這是我的struts.xml,其default.parent.package設置為“ default”:
<struts>
<constant name="struts.convention.action.packages" value="com.myapp.action" />
<constant name="struts.convention.default.parent.package" value="default" />
<constant name="struts.action.extension" value="action" />
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.ognl.allowStaticMethodAccess" value="true" />
<package name="default" namespace="/" extends="tiles-default,json-default">
<interceptors>
<interceptor-stack name="myCustomStack">
<interceptor-ref name="basicStack" />
<interceptor-ref name="staticParams" />
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
</package>
</struts>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.