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();调用下一个拦截器......

struts2 18拦截器详解(十)的更多相关文章

  1. struts2 18拦截器详解(七)

    ChainingInterceptor 该拦截器处于defaultStack第六的位置,其主要功能是复制值栈(ValueStack)中的所有对象的所有属性到当前正在执行的Action中,如果说Valu ...

  2. struts2 18拦截器详解(九)

    ScopedModelDrivenInterceptor 该拦截器处于defaultStack第八的位置,其主要功能是从指定的作用域内检索相应的model设置到Action中,该类中有三个相关的属性: ...

  3. struts2 18拦截器详解(五)

    I18nInterceptor 该拦截器处理defaultStack第四的位置,是用来方便国际化的,如果说我们的一个Web项目要支持国际化的话,通常的做法是给定一个下拉框列出所支持的语言,当用户选择了 ...

  4. 通俗易懂之SpringMVC&Struts2前端拦截器详解

    直接进入主题吧!一,配置Struts2的拦截器分两步走1配置对应的拦截器类:2在配置文件Struts.xml中进行配置拦截器同时在Strust2中配置拦截器类有三种方法1实现Interceptor接口 ...

  5. struts2内置拦截器和自定义拦截器详解(附源码)

    一.Struts2内置拦截器 Struts2中内置类许多的拦截器,它们提供了许多Struts2的核心功能和可选的高级特 性.这些内置的拦截器在struts-default.xml中配置.只有配置了拦截 ...

  6. Struts2 之 modelDriven & prepare 拦截器详解

    struts2 ModelDriven & Prepareable 拦截器 前面对于 Struts2 的开发环境的搭建.配置文件以及 Struts2 的值栈都已经进行过叙述了!这次博文我们讲解 ...

  7. Struts2拦截器详解

    一.Struts2拦截器原理: Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的    拦截器对象,然后串成一个列 ...

  8. Struts2中的拦截器详解

    exception:异常拦截器,拦截异常aliasservletConfig18nprepare:预备拦截器,这个拦截器就是为了ModelDriven准备对象的,若Action类实现了preparab ...

  9. [转]SpringMVC拦截器详解[附带源码分析]

      目录 前言 重要接口及类介绍 源码分析 拦截器的配置 编写自定义的拦截器 总结 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:ht ...

随机推荐

  1. linux系统中的进程状态分析

    转载地址:https://blog.csdn.net/shenwansangz/article/details/51981459 linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程序, ...

  2. Windows下的PHP 5.3.x安装 Zend Guard Loader

    PHP5.3之后不再使用Zend Optimizer而是由Zend Guard Loader替换,而Zend Guard Loader安装比前者方便了很多,只有一个dll: 址:http://down ...

  3. JSR 规范目录

    JSR 规范目录 一.Servlet 规范 1.1 Servlet 2.x 规范 1.2 Servlet 3.x 规范 - 注解和异步请求规范 每天用心记录一点点.内容也许不重要,但习惯很重要!

  4. Netty Reator(二)Scalable IO in Java

    Netty Reator(二)Scalable IO in Java Netty 系列目录 (https://www.cnblogs.com/binarylei/p/10117436.html) Do ...

  5. 微信小程序播放视频发送弹幕效果

    首先.先来看一下效果图 然后.再看一下官方文档API对video的说明 相关属性解析: danmu-list:弹幕列表 enable-danmu:是否显示弹幕 danmu-btn:弹幕按钮 contr ...

  6. 网上流行的linux内核漫画

  7. Django之auth模块用户认证模块

    一.Auth模块 1)auth模块是什么.登录后台使用的账号密码,则就是使用的auth模块创建的表 Auth模块是Django自带的用户认证模块: 我们在开发一个网站的时候,无可避免的需要设计实现网站 ...

  8. kbmmw 与extjs 的初次结合

    前面写了extjs 的安装,今天写一下kbmmw 与extjs 的结合,参照delphi 产品经理marco文章 . 由于extjs 设计时要读取服务器端的数据,所以先要做一个rest 服务器. 先要 ...

  9. Codeforces 1106 简要题解

    文章目录 A题 B题 C题 D题 E题 F题 传送门 A题 传送门 读错题还能过样例我给自己点个赞. 题意简述:给一个010101网格SSS,问满足Si,j=Si+1,j+1=Si+1,j−1=Si− ...

  10. 百度地图足迹demo(多点轨迹生成)

    不要忘记引用JQuery//~~~<script src="jquery-1.7.1.min.js" type="text/javascript"> ...