Frage

I use a Struts2 Convention plug-in to map my actions. Please, help me to solve the following problem. Here I have an action mapping

@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;
}

When, for instance, there is no artGroup for specified artikelgroep it should redirect link _http://site/categorie/hoofdgroep/artikelgroep/ to url _http://site/categorie/hoofdgroep/ which it perfectly does. The only problem here is that it also prepends additional parameters which are undesired. So link _http://site/categorie/hoofdgroep/artikelgroep/ is redirected to _http://site/categorie/hoofdgroep/?categorie=categorie&hoofdgroep=hoofdgroep&artikelgroep=artikelgroep.

My question is How to get rid of these parameters?

Here are some config params from my struts.properties file

...
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/

So basically is this a bug or it should work this way?

Perhaps it is not so elegant solution but here what I have done. I overrode 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;
    }
}
War es hilfreich?

Lösung

What you describe is the default behaviour of both com.opensymphony.xwork2.util.NamedVariablePatternMatcher and org.apache.struts2.util.RegexPatternMatcher however it not the behaviour of com.opensymphony.xwork2.util.WildcardHelper (which is the default implementation)

From what you have shown the default implementation can handle what you are doing with far less headaches (regular wildcard matching).

Consulting this page: http://struts.apache.org/2.3.1.2/docs/wildcard-mappings.html

It states for "Parameters in namespaces" (I know you are not using this):

From Struts 2.1+ namespace patterns can be extracted as request parameters and bound to the action.

However this equally applies to what is happening in the action and it really seems to be the only behaviour (where I would assume from "can be" that there would be another choice when it should have really been written as "... namespace/action patterns are extracted as request parameters...") and it seems to apply to the regex pattern matching equally, it would be nice for the documentation to more explicitly state this.

From your comments I can better understand what you are doing...

Why don't you simply set up three actions for:

*/*/*, */* and *

Then just pass the numbered parameters into the action?

Andere Tipps

I was digging into the code of org.apache.struts2.dispatcher.ServletRedirectResult#doExecute. Probably this piece prepends undesired parameters

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);
            }
        }
    }
}

There is nothing wrong with this code. And the question is Why those three parameters appeared in the ResultConfig? Because it is working like, when you write like so

 <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>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top