struts2值栈取值从源代码中分析

本文详细解析了Struts2框架中的取值原理,重点介绍了参数拦截器(params interceptor)的作用过程,包括如何通过OGNL表达式从请求中获取参数,并设置到Action对象中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

想要知道struts2取值原理 就从源码中看struts2的拦截器顺序知道原理

从struts2-core\2.3.24\struts2-core-2.3.24.jar核心包里面找到的核心配置文件 struts-default.xml

 <interceptor-stack name="defaultStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="scopedModelDriven"/>
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="datetime"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="actionMappingParams"/>
                <!--这个是参数拦截器params -->
                <interceptor-ref name="params"/>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>

找到params实现类

 <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>

这是实现类

public class ParametersInterceptor extends MethodFilterInterceptor

从实现类里面找到doIntercept(拦截器核心方法)

  public String doIntercept(ActionInvocation invocation) throws Exception {
          //获取当前action
        Object action = invocation.getAction();
        //如果action没有实现NoParameters就不会进去,
        /*
        假设我if条件为true进去了
        */
        if (!(action instanceof NoParameters)) {
        //获取action上下文
            ActionContext ac = invocation.getInvocationContext();
            final Map<String, Object> parameters = retrieveParameters(ac);

            if (LOG.isDebugEnabled()) {
                LOG.debug("Setting params " + getParameterLogMap(parameters));
            }

            if (parameters != null) {
                Map<String, Object> contextMap = ac.getContextMap();
                try {
                    ReflectionContextState.setCreatingNullObjects(contextMap, true);
                    ReflectionContextState.setDenyMethodExecution(contextMap, true);
                    ReflectionContextState.setReportingConversionErrors(contextMap, true);
                    //通过action上下问去值,下面看getValueStack()
                    //是怎么实现的
                    ValueStack stack = ac.getValueStack();
                    setParameters(action, stack, parameters);
                } finally {
                    ReflectionContextState.setCreatingNullObjects(contextMap, false);
                    ReflectionContextState.setDenyMethodExecution(contextMap, false);
                    ReflectionContextState.setReportingConversionErrors(contextMap, false);
                }
            }
        }
        return invocation.invoke();
    }
    //这是ActionContext类下的方法
   public ValueStack getValueStack() {
        return (ValueStack) get(VALUE_STACK);
    }
    //找到这个常亮在跟这找
     public static final String VALUE_STACK = ValueStack.VALUE_STACK;
public interface ValueStack {
    //就找到这里了ValueStack 是个接口看实现类
    public static final String VALUE_STACK = "com.opensymphony.xwork2.util.ValueStack.ValueStack";
//看类名知道了取值是用的OGNL表达式取的值
public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack {
  //...这里不是关键代码就删掉了
      //这是struts2的值栈 现在看struts2是怎么实现栈结构的
      //栈结构肯定有压栈,和弹栈两个方法
    CompoundRoot root;
       //这是struts2 context
    transient Map<String, Object> context;
//值栈用的是ArrayList 集合,在看看压栈和弹栈两个方法
public class CompoundRoot extends ArrayList {

    public CompoundRoot() {
    }

    public CompoundRoot(List list) {
        super(list);
    }


    public CompoundRoot cutStack(int index) {
        return new CompoundRoot(subList(index, size()));
    }

    public Object peek() {
        return get(0);
    }
    //弹栈
    /**
    每次都是从第0号元素删除,遵守了栈规则
    */
    public Object pop() {
        return remove(0);
    }
    //压栈
    /**
        栈规则是:前进后出
        每一次添加都要ArrayList集合中的第0个元素开始,
        是栈结构
    */
    public void push(Object o) {
        add(0, o);
    }
}
  • 上面写了,知道了struts2的赋值的原理所以我们想让struts自动赋值一定要在 params 拦截器之前赋值。下面我们在回到struts2拦截器上
<interceptor-stack name="defaultStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="i18n"/>
                <!--是在params拦截器之上可用这个拦截器
                进行赋值
                <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
                -->
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="scopedModelDriven"/>
                <!--这个是模型驱动 这就是模型驱动可以赋值的原因modelDriven拦截器是在params拦截器上面-->
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="datetime"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params"/>
                <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-ref name="debugging"/>
                <interceptor-ref name="deprecation"/>
            </interceptor-stack>
  • prepare拦截器赋值使用
    (模板驱动就不写了,我相信大家都会写)
//实现Preparable接口添加未实现方法prepare()
public class Dome1 extends ActionSupport implements Preparable {

    private User user = new User();
    //实现原理把要赋值的对象压入栈顶
    @Override
    public void prepare() throws Exception {
        //1获得值栈
        ValueStack vs = ActionContext.getContext().getValueStack();
        //2将u压入栈顶
        vs.push(user);

    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值