Getting Interceptor Parameters in Struts 2

2020-04-07 04:54发布

I have following action mapping

<action name="theAction" ...>
...
    <param name="param1">one</param>
    <param name="param2">two</param>
    ...
    <param name="paramN">nth-number</param>
...
</action>

I can get parameter map using following line in Interceptor

Map<String, Object> params = ActionContext.getContext().getParameters();

Just as above, is there any way to get interceptor parameters as defined in following mapping.

<action name="theAction" ...>
...
    <interceptor-ref name="theInterceptor">
        <param name="param1">one</param>
        <param name="param2">two</param>
        ...
        <param name="paramN">nth-number</param>
    </interceptor-ref>
...
</action>

And action parameters are defined in following way, action parameters and interceptor parameters should be accessible separately.

<action name="theAction" ...>
...
    <param name="param1">one</param>
    <param name="param2">two</param>
    ...
    <param name="paramN">nth-number</param>
    ....
    <interceptor-ref name="theInterceptor">
        <param name="param1">one</param>
        <param name="param2">two</param>
        ...
        <param name="paramN">nth-number</param>
    </interceptor-ref>
...
</action>

Please note that I don't want to declare parameter fields in my interceptor as

//all fields with their getters and setters
private String param1;
private String param2;
...
private String paramN;

After Dev Blanked's asnwer, I implemented his technique. It did not work so I am sharing my code here. I am using Struts 2.3.1.2.

Libraries

  • asm-3.3.jar
  • asm-commons-3.3.jar
  • asm-tree-3.3.jar
  • commons-fileupload-1.2.2.jar
  • commons-io-2.0.1.jar
  • commons-lang-2.5.jar
  • freemarker-2.3.18.jar
  • javassist-3.11.0.GA.jar
  • ognl-3.0.4.jar
  • struts2-core-2.3.1.2.jar
  • xwork-core-2.3.1.2.jar

Struts.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <constant name="struts.devMode" value="true" />

    <package name="the-base" namespace="/" extends="struts-default" abstract="true">

        <interceptors>
            <interceptor name="header" class="demo.interceptors.HttpHeaderInterceptor"></interceptor>

        <interceptor-stack name="theStack">
            <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="header"></interceptor-ref>
            </interceptor-stack>
        </interceptors>

        <default-interceptor-ref name="theStack"></default-interceptor-ref>

    </package>

    <package name="the-module" extends="the-base">
        <action name="theAction">
            <result>/the-action.jsp</result>
            <interceptor-ref name="theStack">
                <param name="header.Cache-control">no-store,no-cache</param>
                <param name="header.Pragma">no-cache</param>
                <param name="header.Expires">-1</param>
                <param name="header.arbitrary">true</param>
            </interceptor-ref>
        </action>
    </package>
</struts>

Interceptor

package demo.interceptors;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.StrutsStatics;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class HttpHeaderInterceptor extends AbstractInterceptor {

    private final Map<String, String> interceptorConfigs = new HashMap<String, String>();

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        System.out.println("Calling 'intercept' method.");
        HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().get(StrutsStatics.HTTP_RESPONSE);

        for(Entry<String, String> entry: interceptorConfigs.entrySet()) {
            String header = entry.getKey();
            String value = entry.getValue();
            System.out.printf("Adding header: %s=%s\n",header,value);
            response.setHeader(header, value);
        }

        return invocation.invoke();
    }

    public Map<String, String> getInterceptorConfigs() {
        System.out.println("calling method 'getInterceptorConfigs'");
        return interceptorConfigs;
    }

    public void addInterceptorConfig(final String configName, final String configValue) {
        System.out.printf("Calling method 'addInterceptorConfig' with params configName = %s, configValue=%.\n",configName, configValue);
        interceptorConfigs.put(configName, configValue);
    }

}

Console Output when theAction is hit.

Calling 'intercept' method. 

2条回答
我欲成王,谁敢阻挡
2楼-- · 2020-04-07 05:32

To be short I'll say no, you can't get interceptor parameters if you defined them in the interceptor-ref element. The parameters are set and applied to the interceptor during build time. However, if you put parameters to the interceptor element like

<interceptor name="theInterceptor" class="com.struts.interceptor.TheInterceptor">
  <param name="param1">one</param>
  <param name="param2">two</param>
</interceptor>

you could retrieve them on the fly

PackageConfig packageConfig = Dispatcher.getInstance().getConfigurationManager().getConfiguration().getPackageConfig("default");
Map<String, Object> interceptorConfigs = packageConfig.getInterceptorConfigs();
InterceptorConfig interceptorConfig =  (InterceptorConfig)interceptorConfigs.get("theInterceptor");
Map<String, String> params = interceptorConfig.getParams();  

If you don't want to define properties on the interceptor to hold the values then OGNL will not set the values but will try, so I don't see the reasons to not to define these properties, the xml configuration marked invalid if your interceptor bean doesn't contain these properties and builder might be throw an exception in this case. So, not defining properties for params I'm not recommending.

查看更多
老娘就宠你
3楼-- · 2020-04-07 05:49

In your custom interceptor you can define a map like below

private final Map<String, String> interceptorConfigs = new HashMap<String, String>();

public Map<String, String> getInterceptorConfigs() {
    return interceptorConfigs;
}


public void addInterceptorConfig(final String configName, final String configValue) {
    interceptorConfigs.put(configName, configValue);
}

Then in your action mappings you can pass in parameters like below .. these will be stored in the map of the interceptor

    <action name="yourAction" class="your.actionClass">
        <result name="success">some.jsp</result>
        <interceptor-ref name="defaultStack">
            <param name="yourInterceptor.interceptorConfigs.key">value</param>
            <param name="yourInterceptor.interceptorConfigs.aParamName">paramValue</param>            </interceptor-ref>
    </action>

"yourInterceptor" refers to the name of the interceptor you have given when adding your interceptor to the struts.xml. When configured like above 'interceptorConfigs' map inside the interceptor will have , key/value pairs.

If you want to make these available to your action, you can just set the map as a context variable in the ActionContext. This can then be retrieved inside the action.

查看更多
登录 后发表回答