Соглашение Struts2 и параметры перенаправления

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

@Action(value="/{categorie:\\w+}/{hoofdgroep:\\w+}/{artikelgroep:\\w+}/", results = {
    @Result(name="success", location="articlelist.jsp"),
    @Result(name="maingroup", location="/%{categorie}/%{hoofdgroep}/", type="redirect"),
    @Result(name="category", location="/%{categorie}/", type="redirect")
}, interceptorRefs = {
    ...
})
public String execute() throws Exception {
   ...
   Category category = service.getCategory(categorie);
   if (category == null) return NONE;
   ...
   MainGroup mGroup = service.getMainGroup(hoofdgroep);
   if (mGroup == null) return "category";
   ...
   ArticleGroup artGroup = service.getArticleGroup(artikelgroep);
   if (artGroup == null) return "maingroup";
   ...
   return SUCCESS;
}

Когда, например, нет группы artGroup для указанной артикельгруппы, он должен перенаправить link _http://site/categorie/hoofdgroep/artikelgroep/ на URL-адрес _http://site/categorie/hoofdgroep/, что он прекрасно делает. Единственная проблема здесь заключается в том, что он также добавляет дополнительные параметры, которые нежелательны. Итак, ссылка _http://site/categorie/hoofdgroep/artikelgroep/ перенаправляется на _http://site/categorie/hoofdgroep/?categorie=categorie&hoofdgroep=hoofdgroep&artikelgroep=artikelgroep.

Мой вопрос: как избавиться от этих параметров?

Вот некоторые параметры конфигурации из моего файла struts.properties.

...
struts.serve.static=false
struts.ognl.allowStaticMethodAccess=true
struts.enable.DynamicMethodInvocation=false
struts.action.extension= ,
struts.url.includeParams=none

struts.enable.SlashesInActionNames=true
struts.mapper.alwaysSelectFullNamespace=false
struts.patternMatcher=regex

struts.convention.default.parent.package=app-default
struts.convention.action.packages=...
struts.convention.action.alwaysMapExecute=false
struts.convention.package.locators.disable=true
struts.convention.relative.result.types=dispatcher
struts.convention.result.path=/WEB-INF/jsp/

Так в основном это ошибка или так и должно работать?

Возможно, это не такое элегантное решение, но вот что я сделал. Я отменил org.apache.struts2.dispatcher.ServletRedirectResult#getProhibitedResultParams

public class ServletRedirectResult
        extends org.apache.struts2.dispatcher.ServletRedirectResult
{

    public ServletRedirectResult() {
        super();
        initProhibitedResultParams();
    }

    public ServletRedirectResult(String location) {
        super(location);
        initProhibitedResultParams();
    }

    public ServletRedirectResult(String location, String anchor) {
        super(location, anchor);
        initProhibitedResultParams();
    }

    private List<String> prohibitedParamNames;

    private void initProhibitedResultParams() {

        String[] parentParams = (String[])super.getProhibitedResultParams().toArray();
        int len = parentParams.length;
        String[] params = new String[len + 4];
        for (int i = 0; i < len; i++) {
            params[i] = parentParams[i];
        }
        params[len] = "statusCode";

        // TODO: This is a temporary solution because RegexPatternMatcher puts parameters
        // from urls into ResultConfig for some reason.
        params[len+1] = "categorie";
        params[len+2] = "hoofdgroep";
        params[len+3] = "artikelgroep";

        prohibitedParamNames = Arrays.asList(params);
    }

    protected List<String> getProhibitedResultParams() {
        return prohibitedParamNames;
    }
}

person user1278890    schedule 19.03.2012    source источник
comment
Вы можете передать эти значения в действие, составить нужную строку местоположения и вместо этого ссылаться на эту новую строку. Думали ли вы о том, чтобы превратить эту функциональность в перехватчик, как только она заработает?   -  person Quaternion    schedule 20.03.2012
comment
Я никогда раньше не видел такого оператора @Action. Может ли кто-нибудь объяснить (или указать мне на какую-нибудь документацию), что на самом деле означает @Action(value=/{categorie:\\w+}/{hoofdgroep:\\w+}/{artikelgroep:\\w+}/   -  person user497087    schedule 20.03.2012
comment
Кому @user497087. Вы можете писать так при использовании машины шаблонов регулярных выражений с подстановочными знаками ( struts.patternMatcher=regex) плюс подключаемый модуль   -  person user1278890    schedule 20.03.2012
comment
@Quaternion. Можете ли вы уточнить, что вы имеете в виду? У меня уже есть значения /categorie/hoofdgroep/artikelgroep/ в соответствующих полях действия, когда я пишу вот так [ @Action(value=/{categorie:\\w+}/{hoofdgroep:\\w+}/{artikelgroep: \\w+}/,..]. А зачем мне перехватчик?У меня есть три отдельных действия, которые обрабатывают три типа URL-адресов /categorie/hoofdgroep/artikelgroep/, /categorie/hoofdgroep/ и /categorie/ и этого достаточно для меня.   -  person user1278890    schedule 20.03.2012
comment
Это было неясно до сих пор... перенаправления могли быть направлены на многие действия, если это так, то перехватчик был бы хорош. В вашем случае это не имеет значения. Но зная, что вам нужно обрабатывать только три шаблона URL-адресов... Я бы сделал три разных действия и, вероятно, поместил их в один и тот же класс без каких-либо переадресаций. Похоже, если кто-то неправильно введет URL-адрес, вы хотите, чтобы он автоматически возвращался на более высокий уровень? Я бы просто показал страницу с ошибкой.   -  person Quaternion    schedule 20.03.2012
comment
@Quaternion. Я бы также показал страницу с ошибкой, но это было требованием клиента, так что...   -  person user1278890    schedule 21.03.2012


Ответы (2)


То, что вы описываете, является поведением по умолчанию как com.opensymphony.xwork2.util.NamedVariablePatternMatcher, так и org.apache.struts2.util.RegexPatternMatcher, однако это не поведение com.opensymphony.xwork2.util.WildcardHelper (который является реализацией по умолчанию)

Из того, что вы показали, реализация по умолчанию может справиться с тем, что вы делаете, с гораздо меньшими головными болями (регулярное сопоставление с подстановочными знаками).

На этой странице: http://struts.apache.org/2.3.1.2/docs/wildcard-mappings.html

В нем указано «Параметры в пространствах имен» (я знаю, что вы это не используете):

В Struts 2.1+ шаблоны пространств имен можно извлекать как параметры запроса и привязывать к действию.

Однако это в равной степени относится к тому, что происходит в действии, и это действительно кажется единственным поведением (где я бы предположил, что «может быть», что был бы другой выбор, когда это действительно должно было быть написано как «... namespace/ шаблоны действий извлекаются как параметры запроса...") и, по-видимому, в равной степени применимы к сопоставлению шаблонов регулярных выражений, было бы неплохо, чтобы в документации это было указано более явно.

Из ваших комментариев я могу лучше понять, что вы делаете...

Почему бы вам просто не настроить три действия для:

*/*/*, */* and *

Затем просто передать пронумерованные параметры в действие?

person Quaternion    schedule 20.03.2012
comment
Большое спасибо за ваш ответ. Часть объяснения о параметрах в пространствах имен остается для меня неясной. Пока вы сказали, что то, что вы описываете, является поведением по умолчанию как для com.opensymphony.xwork2.util.NamedVariablePatternMatcher..., так и для активации параметров в пространствах имен, мы должны установить struts.patternMatcher=namedVariable. Действительно, я могу управлять отображением действий с помощью /*/, /, * и нумерованных параметров, но я не знаю, как это будет работать, потому что у меня также есть URL-адреса типа «/customer». /passrestore/forgetPassword» и «/customer/registerCustomer». Будут ли конфликты? - person user1278890; 21.03.2012
comment
В любом случае, это правильное поведение для NamedVariablePatternMatcher и RegexPatternMatcher? Если они определяют некоторые параметры в конфигурации действия при создании @Action(value="/{categorie:\\w+}/{hoofdgroep:\\w+}/{artikelgroep:\\w+}/"... сопоставления, они должны быть объявлены на уровне действия, а не на уровне результата. Например. они должны присутствовать в вызове invocation.getProxy().getConfig().getParams(), но не в ResultConfig#getParams(). Но, может быть, я ошибаюсь. В любом случае, я выбрал решение, переопределив ServletRedirectResult#getProhibitedResultParams и добавив эти параметры для исключения. - person user1278890; 21.03.2012
comment
Не должно быть конфликта между */*/* и */*... Я говорю, что используйте параметры по умолчанию, а не именованные или регулярные выражения. - person Quaternion; 21.03.2012

Я копался в коде org.apache.struts2.dispatcher.ServletRedirectResult#doExecute. Вероятно, эта часть добавляет нежелательные параметры

ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(invocation.getResultCode());
if (resultConfig != null)
{
    Map<String, String> resultConfigParams = resultConfig.getParams();

    for (Map.Entry<String, String> e : resultConfigParams.entrySet())
    {
        if (!getProhibitedResultParams().contains(e.getKey()))
        {
            String potentialValue = e.getValue() == null ? "" : conditionalParse(e.getValue(), invocation);
            if (!suppressEmptyParameters || ((potentialValue != null) && (potentialValue.length() > 0)))
            {
                    requestParameters.put(e.getKey(), potentialValue);
            }
        }
    }
}

В этом коде нет ничего плохого. И вопрос: почему эти три параметра появились в ResultConfig? Потому что это работает, когда ты так пишешь

 <result name="maingroup" type="redirect">
     <param name="location">/${categorie}/${hoofdgroep}/</param>
     <param name="namespace">/</param>
     <param name="categorie">${categorie}</param>
     <param name="hoofdgroep">${hoofdgroep}</param>
     <param name="artikelgroep">${artikelgroep}</param>
 </result>
person user1278890    schedule 20.03.2012