Параметры без мутаторов и аксессоров (установщиков/геттеров) вместе с перехватчиком параметров в Struts 2

В следующем классе действий я использую перехватчик параметров.

@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value = "struts-default")
@InterceptorRefs(@InterceptorRef(value="store", params={"operationMode", "AUTOMATIC"}))
public final class TestAction extends ActionSupport implements Serializable, ValidationAware, Preparable
{
    private static final long serialVersionUID = 1L;

    private String param1;
    private String param2;

    //Getters and setters.

    public TestAction() {}

    @Action(value = "TestMessage",
        results = {
            @Result(name=ActionSupport.SUCCESS, type="redirectAction", params={"namespace", "/admin_side", "actionName", "Test"}),
            @Result(name = ActionSupport.INPUT, location = "Test.jsp")},
        interceptorRefs={
            @InterceptorRef(value="paramsPrepareParamsStack", params={"params.acceptParamNames", "param1, param2", "params.excludeParams", "extraParam", "validation.validateAnnotatedMethodOnly", "true"})
        })
    public String insert() {
        // Do something. Add or update a row to the database (one at a time).
        addActionMessage("Action message");
        addActionError("Error message");
        return ActionSupport.SUCCESS;
    }

    @Action(value = "Test",
    results = {
        @Result(name = ActionSupport.SUCCESS, location = "Test.jsp"),
        @Result(name = ActionSupport.INPUT, location = "Test.jsp")},
    interceptorRefs = {
        @InterceptorRef(value = "paramsPrepareParamsStack", params = {"params.acceptParamNames", "param1, param2", "params.excludeParams", "extraParam", "validation.validateAnnotatedMethodOnly", "true", "validation.excludeMethods", "load"})})
    public String load() throws Exception {
        // This method is just required to return an initial view on page load.
        return ActionSupport.SUCCESS;
    }

    @Override
    public void prepare() throws Exception {}
}

Далее <s:form>:

<s:form namespace="/admin_side" action="Test" validate="true" id="dataForm" name="dataForm">
    <s:if test="hasActionMessages()">
        <s:actionmessage theme="jquery"/>
    </s:if>

    <s:if test="hasActionErrors()">
        <s:actionerror theme="jquery"/>
    </s:if>

    <s:hidden name="param1"/>
    <s:hidden name="param2"/>
    <s:hidden name="extraParam"/>
    <s:submit value="Submit" action="TestMessage"/>
</s:form>

Здесь скрытое поле формы extraParam не объявлено и, следовательно, не имеет сеттера и геттера в классе действий.

В этом случае при отправке этой формы на серверном терминале появляется следующее сообщение.

СЕРЬЕЗНЫЙ: уведомление разработчика (установите для struts.devMode значение false, чтобы отключить это сообщение): обнаружена непредвиденная ошибка при настройке «extraParam» для «действий класса». TestAction: ошибка установки выражения «extraParam» со значением ['', ]

params.excludeParams не исключает параметр extraParam, как в классе действий.

Можем ли мы как-то предотвратить такие исключения при использовании перехватчика параметров. Такие сообщения без необходимости добавляются к сообщениям о действиях и отображаются через <s:actionmessage/>, если они используются, когда они вообще не должны отображаться.


Если это paramsPrepareParamsStack заменить на defaultStack в классе действий, то такие сообщения не появляются. Он просто выдает предупреждение следующим образом.

ВНИМАНИЕ: Параметр [extraParam] находится в списке шаблонов excludeParams!

Пожалуйста, не говорите просто установите struts.devMode на false, чтобы отключить такие сообщения.


person Tiny    schedule 06.02.2014    source источник
comment
Как вы думаете, почему параметры наследуются?   -  person Roman C    schedule 07.02.2014
comment
параметры наследуются? Я не понимаю!   -  person Tiny    schedule 07.02.2014
comment
если у вас есть какая-то конфигурация, и у нее есть какие-то параметры для действия или перехватчика, и вы расширяете их из родительского пакета, и это становится не таким, как если бы вы указывали аннотацию на класс или на метод.   -  person Roman C    schedule 08.02.2014
comment
@RomanC: Вы можете ответить на вопрос. Я не понимаю, о чем вы говорите.   -  person Tiny    schedule 08.02.2014
comment
Пожалуйста, добавьте ответы, если у кого-то есть.   -  person Tiny    schedule 10.05.2014


Ответы (3)


Я уже говорил в комментарии, что параметры перехватчика не наследуются конфигами перехватчика родительских пакетов, если вы определяете свой собственный набор параметров, которые переопределяют настройки по умолчанию. См. раздел Переопределение параметров перехватчика.

Существуют также некоторые методы, используемые для получения двух разных карт параметров перехватчика, см. Получение параметров перехватчика в Struts2.

Плагин соглашения создает конфигурации пакета XWork, которые унаследованы от некоторого родительского пакета. См. мой ответ для Плагин Struts 2 для определения нескольких родительских пакетов.

Итак, все, что вам нужно сделать, это переопределить параметр по умолчанию, установленный родительской конфигурацией, если вы хотите добавить в набор свои собственные параметры. Либо тег interceptor, либо тег interceptor-stack, и вы должны сделать это для каждого тега interceptor-ref.

Плагин соглашения использует @InterceprorRef для той же цели, но с оговоркой, что если она применяется к классу, она применяется к каждому действию этого класса. Поэтому будьте осторожны при использовании этой аннотации на уровне класса. Вы переопределяете параметры стека перехватчика, поэтому вы должны использовать префикс, за которым следует точка имени перехватчика, указанного в стеке, для каждого имени параметра, но это работает, только если у вас есть уникальные имена interceptor-refs в стеке.

Если у вас есть две ссылки на перехватчик params в paramsPrepareParamsStack, вы не сможете переопределить второй params interceptor-ref, если только вы не создадите свой собственный стек перехватчиков и не укажете переопределения параметров для каждой ссылки перехватчика.

person Roman C    schedule 10.05.2014
comment
Спасибо. Позже постараюсь применить на практике. - person Tiny; 11.05.2014

Давайте посмотрим на paramsPrepareParamsStack:

 <interceptor-stack name="paramsPrepareParamsStack">
      <interceptor-ref name="exception"/>
      <interceptor-ref name="alias"/>
      <interceptor-ref name="i18n"/>
      <interceptor-ref name="checkbox"/>
      <interceptor-ref name="multiselect"/>
      <interceptor-ref name="params">
          <param name="excludeParams">dojo\..*,^struts\..*</param>
      </interceptor-ref>
      <interceptor-ref name="servletConfig"/>
      <interceptor-ref name="prepare"/>
      <interceptor-ref name="chain"/>
      <interceptor-ref name="modelDriven"/>
      <interceptor-ref name="fileUpload"/>
      <interceptor-ref name="staticParams"/>
      <interceptor-ref name="actionMappingParams"/>
      <interceptor-ref name="params">
          <param name="excludeParams">dojo\..*,^struts\..*</param>
       </interceptor-ref>
       <interceptor-ref name="conversionError"/>
       <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>

Есть 2 params перехватчика. Когда вы устанавливаете параметр excludeParams в своем классе действий, то он, вероятно, установлен для первого перехватчика params - параметр для второго перехватчика остается по умолчанию. Теперь, когда вызывается второй перехватчик params (по умолчанию excludeParams), выдается данное исключение.

Можно попробовать продублировать настройку параметра excludeParams, чтобы задать его и для второго перехватчика:

 @InterceptorRef(value = "paramsPrepareParamsStack", params = {"params.acceptParamNames", "param1, param2", "params.excludeParams", "extraParam", "params.excludeParams", "extraParam", "validation.validateAnnotatedMethodOnly", "true", "validation.excludeMethods", "load"})})
person Kamil Chaber    schedule 16.02.2014
comment
Фрагмент кода в вопросе является лишь примером. На самом деле не существует определенных параметров, таких как extraParam, поскольку даже конечные пользователи могут указать любое количество вредоносных параметров (в зависимости от длины интересующего их URL-адреса), которые могут вызвать такое исключение, как указано в вопросе. params.acceptParamNames должен принимать только те параметры, которые перечислены. Остальное должно быть запрещено без появления таких сообщений, как в вопросе. - person Tiny; 17.02.2014
comment
Как я уже говорил, в paramsPrepareParamsStack есть 2 перехватчика params. Когда вы устанавливаете params.acceptParamNames, это устанавливается только для первого перехватчика. Вам нужно установить этот параметр и для второго перехватчика. - person Kamil Chaber; 17.02.2014
comment
Указание params.acceptParamNames или params.excludeParams дважды в перехватчике параметров не имеет значения. Это не предотвращает исключение, как указано в вопросе. Поэтому в настоящее время я не рассматриваю возможность принятия ответа, чтобы он был указан в списке вопросов без ответа. Если позже вы намеренно или случайно встретите решение, пожалуйста, не забудьте обновить ответ, независимо от того, сколько времени это займет, может быть годы. Для меня это единственное место, где я могу учиться. Спасибо. - person Tiny; 22.02.2014
comment
Я случайно назначил награду за неправильный ответ в первый раз. Я чувствую вину и стыд за это. Когда-то завершенное действие уже нельзя отменить. Пожалуйста, простите меня. Я действительно извиняюсь за свою ошибку. - person Tiny; 22.02.2014

Я не говорю точно,

пример кода следующий:

<s:form action="save" method="post">
    <s:textfield key="personBean.firstName" /> 
    <s:textfield key="personBean.lastName" /> 
    <s:textfield key="personBean.email" />
    <s:textfield key="personBean.phoneNumber" />
    <s:select key="personBean.sport" list="sports" />
    <s:radio key="personBean.gender" list="genders" />
    <s:select key="personBean.residency" list="states" listKey="stateAbbr" listValue="stateName"/>
    <s:checkbox key="personBean.over21" />
    <s:checkboxlist key="personBean.carModels" list="carModelsAvailable" />
    <s:submit key="submit" />
</s:form>

Возможно, он не работает, перейдите по этой ссылке:

person jmail    schedule 17.02.2014
comment
Спасибо, но на самом деле я не понимаю. - person Tiny; 17.02.2014