Мультидействие в форме распорок

Я хочу добавить 3 кнопки в форму распорок. Мой код:

@Action("/admin/product/insert")
public String insert() throws Exception {
    if(upload.hasFile()){
        model.setImage(upload.getFileFileName());
        upload.saveTo("../images/customers/");
    }
    else{
        model.setImage("product.png");
    }
    XHibernate.save(model);
    return "new";
}

@Action("/admin/product/update")
public String update() throws Exception {
    if(upload.hasFile()){
        model.setImage(upload.getFileFileName());
        upload.saveTo("../images/customers/");
    }
    System.out.println("update");
    XHibernate.update(model);
    return "input";
}

@Action("/admin/product/delete")
public String delete() throws Exception {
    XHibernate.delete(model);
    return "new";
}

В JSP:

<s:form enctype="multipart/form-data" theme="simple" role="form">

    <div class="form-group col-md-4">
        <label for="id">Product Id</label>
        <s:textfield id="productId" name="id" cssClass="form-control" />
    </div>

    <div class="form-group col-md-4">
        <label for="name">Product Name</label>
        <s:textfield name="name" cssClass="form-control" />
    </div>

    <div class="form-group col-md-4">
        <label for="unitPrice">Unit Price</label>
        <s:textfield name="unitPrice" cssClass="form-control" />
    </div>

    <div class="form-group col-md-4">
        <label for="unitBrief">Unit Description</label>
        <s:textfield name="unitBrief" cssClass="form-control" />
    </div>

    <div class="form-group col-md-4">
        <label for="discount">Discount</label>
        <s:textfield name="discount" cssClass="form-control" />
    </div>

    <div class="form-group col-md-4">
        <label for="quantity">Quantity</label>
        <s:textfield name="quantity" cssClass="form-control" />
    </div>

    <div class="form-group col-md-4">
        <label for="productDate">Product Date</label>
        <s:textfield name="productDate" cssClass="form-control" />
    </div>

    <div class="form-group col-md-4">
        <label for="supplier.id">Supplier</label>
        <s:select name="supplier.id" list="suppliers" listKey="id"
            listValue="name" cssClass="form-control" />
    </div>

    <div class="form-group col-md-4">
        <label for="category.id">Category</label>
        <s:select name="category.id" list="categories" listKey="id"
            listValue="name" cssClass="form-control" />
    </div>

    <div class="form-group col-md-4">
        <label>Features</label>
        <div>
            <label><s:checkbox name="available" /> Available</label> <label><s:checkbox
                    name="special" /> Special</label> <label><s:checkbox
                    name="latest" /> latest</label>
        </div>
    </div>

    <div class="form-group col-md-4">
        <label for="image">Image</label> <input id="image" type="file"
            name="upload.file">
        <s:hidden name="image" />
    </div>

    <div class="form-group col-md-12">
        <label for="description">Description</label>
        <s:textarea id="index_description" name="description" rows="30"
            cssClass="form-control" />
    </div>

    <div class="col-md-12">
        <s:submit value="Thêm mới" action="admin/product/insert"
            cssClass="btn btn-default" />
        <s:submit value="Cập nhật" action="admin/product/update"
            cssClass="btn btn-default" />
        <s:submit value="Xóa" action="admin/product/delete" cssClass="btn btn-default" />
        <a href="product/index" class="btn btn-default">Nhập lại</a>
    </div>
</s:form>

Проблема в том, что он не может вызвать точное действие.

Я всегда получал сообщение об ошибке: «Действие не сопоставлено для пространства имен /admin/product и имени действия admin/product/update».

Должен ли я разделить его на 3 формы? ИЛИ Есть ли способ иметь 3 кнопки для 3 действий в 1 форме, как мой код? Любая помощь будет здорово.

обновлен журнал при включении devmode:

ognl.MethodFailedException: Method "setDiscount" failed for object eshop.entity.Product@48e4d3df [java.lang.NoSuchMethodException: setDiscount([Ljava.lang.String;)]
at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:823)
at ognl.OgnlRuntime.setMethodValue(OgnlRuntime.java:964)
at ognl.ObjectPropertyAccessor.setPossibleProperty(ObjectPropertyAccessor.java:75)
at ognl.ObjectPropertyAccessor.setProperty(ObjectPropertyAccessor.java:131)
at com.opensymphony.xwork2.ognl.accessor.ObjectAccessor.setProperty(ObjectAccessor.java:28)
at ognl.OgnlRuntime.setProperty(OgnlRuntime.java:1656)
at com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor.setProperty(CompoundRootAccessor.java:50)
at ognl.OgnlRuntime.setProperty(OgnlRuntime.java:1656)
at ognl.ASTProperty.setValueBody(ASTProperty.java:101)
at ognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:177)
at ognl.SimpleNode.setValue(SimpleNode.java:246)
at ognl.Ognl.setValue(Ognl.java:476)
at com.opensymphony.xwork2.ognl.OgnlUtil.setValue(OgnlUtil.java:192)
at com.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:155)
at com.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:143)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.setParameters(ParametersInterceptor.java:273)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:187)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:148)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:93)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:306)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:89)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:128)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at org.apache.struts2.interceptor.ProfilingActivationInterceptor.intercept(ProfilingActivationInterceptor.java:104)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:267)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:126)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:138)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:148)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:128)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:176)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:236)
at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:468)
at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)

person Anh Nguyen    schedule 30.11.2014    source источник
comment
попробуйте иметь разные имена в каждой кнопке отправки.   -  person Ken de Guzman    schedule 30.11.2014
comment
я пробовал но все равно не работает   -  person Anh Nguyen    schedule 30.11.2014
comment
если у вас есть одна кнопка отправки, она работает?   -  person Ken de Guzman    schedule 30.11.2014
comment
если у меня есть одна кнопка, я поместил действия в тег формы, и это сработало.   -  person Anh Nguyen    schedule 30.11.2014
comment
stackoverflow.com/q/13343954/1700321.   -  person Aleksandr M    schedule 01.12.2014


Ответы (1)


Чтобы решить вашу текущую проблему, вы должны добавить

<constant name="struts.enable.SlashesInActionNames" value="true"/>

в struts.xml, это значение по умолчанию равно false и будет использовать всю часть до последней косой черты в качестве пространства имен, а не имени действия. Кстати, это имеет побочные эффекты:

Имена действий с косой чертой

Если в именах ваших действий есть косые черты (например,
<action name="admin/home" class="tutorial.Admin"/>), вам необходимо специально разрешить косые черты в именах ваших действий с помощью константы в файле struts.xml, указав

<constant name="struts.enable.SlashesInActionNames" value="true"/>.

См. JIRA Issue WW-1383 для обсуждения, поскольку существуют побочные эффекты установить для этого свойства значение true.

Чтобы решить проблему правильным образом, вам необходимо правильно использовать пространства имен:

Действие

@Namespace("/admin/product")
public class YourAction extends ActionSupport

    @Action("insert")
    public String insert() throws Exception {
        /* .... */
    }

    @Action("update")
    public String update() throws Exception {
        /* .... */
    }

    @Action("delete")
    public String delete() throws Exception {
        /* .... */
    }

JSP

<s:submit value="Thêm mới" action="insert" cssClass="btn btn-default" />
<s:submit value="Cập nhật" action="update" cssClass="btn btn-default" />
<s:submit value="Xóa"      action="delete" cssClass="btn btn-default" />

Вам также следует реорганизовать структуру пакета для действий и JSP, чтобы она соответствовала структуре пространства имен.

PS: не забудьте включить префикс действия, как описано в этом ответе, если вы используете версию Struts2 выше 2.3. .15.2:

<constant name="struts.mapper.action.prefix.enabled" value="true"/>

ИЗМЕНИТЬ

Если namespace действия, которое вы используете для отображения JSP, отличается от вызываемых действий (в данном случае /admin/product), вам необходимо указать его в теге <s:form>:

<s:form namespace = "/admin/product" 
          enctype = "multipart/form-data" 
            theme = "simple" 
             role = "form">

И (если вы используете версию Struts2 выше 2.3.15.2) установите следующее свойство в struts.xml:

<constant name="struts.mapper.action.prefix.crossNamespaces" value="true"/>

потому что по умолчанию он отключен по соображениям безопасности.

person Andrea Ligios    schedule 01.12.2014
comment
Извините, я занят в течение дня, я попробую ваше предложение и отвечу вам как можно скорее. Спасибо за вашу поддержку - person Anh Nguyen; 02.12.2014
comment
Странно. Я последовал вашему предложению, сработали 3 кнопки, но когда я нажимаю «Вставить», форма не вызывает вставку (только изменение формы для действия вставки), затем я нажимаю «Обновить» (действие вставки отображается в URL), затем я нажимаю «Удалить» (обновление действие отображается в URL). Посмотрите, как что-то помешало действию, и сложите его. Но меняется только URL, код в контроллере не срабатывает. - person Anh Nguyen; 02.12.2014
comment
Как вы определили результат INPUT? Включите devMode и внимательно проверьте журналы сервера и журналы приложений на наличие трассировки стека. - person Andrea Ligios; 02.12.2014
comment
Пожалуйста, проверьте мое обновление для журналов в консоли, когда я нажимаю действие. - person Anh Nguyen; 02.12.2014
comment
Вы используете старую версию Struts2? issues.apache.org/jira/browse/WW-2971 - person Andrea Ligios; 02.12.2014
comment
Да, я использую версию 2.1.6. Можно ли как-то решить проблему без смены версии распорок? - person Anh Nguyen; 02.12.2014
comment
Вау, попался с дальним выстрелом! : O Кстати, нет, если только вы не хотите исправлять это самостоятельно. Поверьте мне, обновившись до 2.3.16.3, вы получите МНОГО преимуществ, включая исправления безопасности и функциональные возможности, с очень небольшим количеством настроек ... уже перечисленных в этом ответе! :) - person Andrea Ligios; 02.12.2014
comment
Мне потребовалось 2 часа, чтобы собрать библиотеку для интеграции struts 2.3.16.3 и hibernate, и теперь это все еще не работает. Можете ли вы показать мне список совместимых библиотек последних версий Struts и Hibernate? - person Anh Nguyen; 02.12.2014
comment
Давайте продолжим обсуждение в чате. - person Anh Nguyen; 02.12.2014