zoukankan      html  css  js  c++  java
  • struts2 18拦截器详解(十)

    ModelDrivenInterceptor


       该拦截器处于defaultStack中的第九的位置,在ScopedModelDrivenInterceptor拦截器之后,要使该拦截器有效的话,Action必须实现ModelDriven接口,该接口就一个方法:getModel(),ModelDrivenInterceptor拦截器主要做的事就是调用Action的getModel()方法然后把返回的model压入值栈(如果不为null)。如果Action实现了ScopedModelDriven接口也就实现了ModelDriven接口,因为ScopedModelDrivenInterceptor在执行的过程肯定会返回一个model对象再调用Action的setModel(model)方法,如果Action对model进行了接收,那么在执行到ModelDrivenInterceptor拦截器的时候,Action的getModel()方法返回的就是ScopedModelDrivenInterceptor拦截器设置进去的值,已经不为null了,所以该model自然就会压入值栈。下面是该拦截器intercept方法源码:

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();//获取当前正在执行的Action
    	//如果Action实现了ModelDriven接口
        if (action instanceof ModelDriven) {
            ModelDriven modelDriven = (ModelDriven) action;
            ValueStack stack = invocation.getStack();
            Object model = modelDriven.getModel();//通过getModel方法获取model
            if (model !=  null) {//如果model不为null则把model压入值栈
            	stack.push(model);
            }
            if (refreshModelBeforeResult) {//在执行Result之前是否要更新model对象,默认为false
                invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
            }
        }
        return invocation.invoke();//调用下一个拦截器
    }


       该方法逻辑很简单,正如前所说的一样,就是把getModel方法返回的结果压入值栈而已,我们一般实现这个接口是利用压入值栈的model对象接收从页面提交过来的数据,有很多时候我们是在Action中写属性来接收参数的,因为Action也是在值栈中,而struts2在赋值参数的时候是在值栈从栈顶往栈底寻找有相应setter方法的对象,而这时model压入了值栈,它是处于栈顶的,所以从页面提交过来的参数也就被model对象接收了。这种方式呢model对象有点像struts1.X里面formbean对象的功能。

       ModelDrivenInterceptor拦截器中还有个名为refreshModelBeforeResult的属性,用于设置在执行Result之前是否要更新model对象,默认值是false也就不会去更新,我们有可能在Action的执行过程将model这个引用变量指向了另外一个对象,如果你把refreshModelBeforeResult设置了为true,那么在Result执行之前PreResultListener就会用这个新的对象将值栈中的对象替换,达到更新效果。

       PreResultListener是一种监听器由ActionInvocation对象进行注册,在Result执行之前会执行该种监听器的beforeResult方法。虽然在defaultStack中,struts2是不会在ActionInvocation中注册这个RefreshModelBeforeResult监听器的,我们还是去简单看一下:

    protected static class RefreshModelBeforeResult implements PreResultListener {
        private Object originalModel = null;
        protected ModelDriven action;
    
    
        public RefreshModelBeforeResult(ModelDriven action, Object model) {
            this.originalModel = model;
            this.action = action;
        }
    
        public void beforeResult(ActionInvocation invocation, String resultCode) {
            ValueStack stack = invocation.getStack();//获取值栈
            CompoundRoot root = stack.getRoot();//获取值栈的root对象
    
            boolean needsRefresh = true;
            Object newModel = action.getModel();//从Action中获取新的model对象
    
            // Check to see if the new model instance is already on the stack
            for (Object item : root) {
                if (item.equals(newModel)) {//如果新的model对象与旧的相同则不刷新
                    needsRefresh = false;
                }
            }
    
            // Add the new model on the stack
            if (needsRefresh) {//如果要刷新
    
                // Clear off the old model instance
                if (originalModel != null) {
                    root.remove(originalModel);//先移除旧model
                }
                if (newModel != null) {
                    stack.push(newModel);//将新model对象压入值栈
                }
            }
        }
    }


       RefreshModelBeforeResult实现了PreResultListener接口,是ModelDrivenInterceptor的一个静态内部类,在执行Result之前执行其beforeResult方法
    如何进行刷新的很简单相信大家都看得懂。

       intercept方法最后一句invocation.invoke();调用下一个拦截器......

  • 相关阅读:
    【转】C++11优化使用emplace,emplace_back
    面试经历总结
    Hive常用函数
    股票指标
    Visual Studio Code 可以翻盘成功主要是因为什么?
    openpyxl模块操作Excel
    JavaScript(二)
    前端之CSS
    ps导出ICO格式
    Qt 所有版本官方下载地址
  • 原文地址:https://www.cnblogs.com/riskyer/p/3402556.html
Copyright © 2011-2022 走看看