1

我有以下动作类:

@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()映射到<s:submit>动作的关联)时,该prepare()方法只执行一次。

在执行插入或更新时,prepare()可以看到该方法被调用了两次。为什么会这样?

type="redirectAction"在in的情况下@Result(),该prepare()方法被执行两次。当of设置为时,有没有办法防止该prepare()方法被执行两次?type@ResultredirectAction

4

2 回答 2

1

我遇到了同样的问题,我最终发现我在多个地方引用了一个拦截器堆栈。在您的情况下,您似乎在班级级别:

@ParentPackage(value="struts-default"),我相信它使用默认堆栈。

然后在@Act​​ion 级别,您可以参考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 设置为“默认”:

<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>
于 2014-07-08T19:35:32.457 回答
1

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()应该不同,即使操作名称不同,您也可以检查这一点。因此,没有prepare方法被调用两次,因为它只是prepare每个动作的堆栈中的拦截器。另一方面,如果你使用paramsPrepareParamsStack拦截params器被调用两次:prepare拦截器之前和之后。

于 2014-01-07T16:48:29.617 回答