关于struts2的modelDriven



今天做毕业设计,前台往后台赋值,习惯性的用了modelDriven。但是刚写完就奇怪它的机理是怎样的,它怎么知道我前台传的参是哪个Model的属性(之前用servlet都是手动),于是手贱的ctrl点进去,简单了解了一下



之前记得要使用modelDriven必须使用modelDriven的拦截器,但是我没加这个拦截器也实现了功能,看默认拦截器defaultStack原来所谓的默认拦截器就是一系列拦截器的集合

看modelDriven的源码可以看到

 1     @Override
 2
 3 public String intercept(ActionInvocation invocation) throws Exception {
 4
 5 //获取 Action 对象: EmployeeAction 对象, 此时该 Action 已经实现了 ModelDriven 接口
 6
 7     //public class EmployeeAction implements RequestAware, ModelDriven<Employee>
 8
 9         Object action = invocation.getAction();
10
11 //判断 action 是否是 ModelDriven 的实例
12
13         if (action instanceof ModelDriven) {
14
15 //强制转换为 ModelDriven 类型
16
17             ModelDriven modelDriven = (ModelDriven) action;
18
19 //获取值栈
20
21             ValueStack stack = invocation.getStack();
22
23 //调用 ModelDriven 接口的 getModel() 方法
24
25             //即调用 EmployeeAction 的 getModel() 方法
26
27             /*
28
29             public Employee getModel() {
30
31               employee = new Employee();
32
33               return employee;
34
35            }
36
37             */
38
39             Object model = modelDriven.getModel();
40
41             if (model !=  null) {
42
43 //把 getModel() 方法的返回值压入到值栈的栈顶. 实际压入的是 EmployeeAction 的 employee 成员变量
44
45               stack.push(model);
46
47             }
48
49             if (refreshModelBeforeResult) {
50
51                 invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
52
53             }
54
55         }
56
57         return invocation.invoke();

发现它什么也没实现,就是modelDriven接口,如果实现了就调用了它的getModel方法,然后把得到的压入栈顶。没有赋值操作

那么流程图应该是这样:


那么setName()赋值操作是谁做的?ParametersInterceptor

那么结论是:

1)ModelDrivenInterceptor只是将实现了ModelDriven的action的model放入值栈而已,所以你才可以直接使用
<input type="text" name="type" />传值。
2)如果action没有实现此接口,那么配置ModelDrivenInterceptor没有任何意义
3)ModelDrivenInterceptor并不负责注入值,赋值的是ParametersInterceptor



如果还要深究的话

ParametersInterceptor拦截器继承自MethodFilterInterceptor,其主要功能是把ActionContext中的请求参数设置到ValueStack中,如果栈顶是当前Action则把请求参数设置到了Action中,如果栈顶是一个model(Action实现了ModelDriven接口)则把参数设置到了model中。

ParametersInterceptor拦截器主要源码:

 1 @Override
 2 public String doIntercept(ActionInvocation invocation) throws Exception {
 3     Object action = invocation.getAction();//获取当前执行的Action对象
 4     if (!(action instanceof NoParameters)) {//判断Action是否实现了NoParameters接口,实现该接口表示该Action没有任何请求参数
 5         ActionContext ac = invocation.getInvocationContext();//获取ActionContext对象
 6         final Map<String, Object> parameters = retrieveParameters(ac);//获取请求参数Map
 7         //省略...
 8         if (parameters != null) {//如果请求参数不为null
 9             Map<String, Object> contextMap = ac.getContextMap();//获取ActionContext内部的context Map,即OgnlContext对象
10             try {
11                 //省略...
12                 ValueStack stack = ac.getValueStack();//获取值栈
13                 setParameters(action, stack, parameters);//为值栈设置参数
14             } finally {
15                 //省略...
16             }
17         }
18     }
19     return invocation.invoke();//调用下一个拦截器
20 }  

可以知道为什么要实现自动赋值,只需要实现modelDriven接口就行了

其中最重要逻辑代码是setParometers()方法

 1 protected void setParameters(Object action, ValueStack stack, final Map<String, Object> parameters) {
 2     ParameterNameAware parameterNameAware = (action instanceof ParameterNameAware)
 3             ? (ParameterNameAware) action : null;//判断Action有无实现ParameterNameAware接口
 4
 5     Map<String, Object> params;
 6     Map<String, Object> acceptableParameters;//合法参数集合
 7     //判断参数设置是否有序,ordered默认为false,即无序
 8     if (ordered) {
 9         params = new TreeMap<String, Object>(getOrderedComparator());//如果有序则要获取比较器
10         acceptableParameters = new TreeMap<String, Object>(getOrderedComparator());
11         params.putAll(parameters);
12     } else {
13         params = new TreeMap<String, Object>(parameters);
14         acceptableParameters = new TreeMap<String, Object>();
15     }
16     //迭代请求参数
17     for (Map.Entry<String, Object> entry : params.entrySet()) {
18         String name = entry.getKey();
19         //判断参数是否合法,如果Action实现了ParameterNameAware则acceptableName(name)返回true且parameterNameAware.acceptableParameterName(name)
20         //也返回true该参数才是合法的;如果Action没有实现ParameterNameAware则参数是否合法由acceptableName(name)方法决定
21         boolean acceptableName = acceptableName(name)  && (parameterNameAware == null  || parameterNameAware.acceptableParameterName(name));
22         //如果参数合法
23         if (acceptableName) {
24             acceptableParameters.put(name, entry.getValue());//把合法参数添加到合法参数集合中
25         }
26     }
27
28     ValueStack newStack = valueStackFactory.createValueStack(stack);
29     //省略...
30     for (Map.Entry<String, Object> entry : acceptableParameters.entrySet()) {//迭代合法参数
31         String name = entry.getKey();//参数名
32         Object value = entry.getValue();//参数值
33         try {
34             newStack.setValue(name, value);//将该参数设置到ValueStack中
35         } catch (RuntimeException e) {
36             //省略...
37         }
38     }
39     //省略...
40     //看该方法的名称是将合法参数添加到ActionContext中,但在该拦截器中,该方法为空实现,无任何代码
41     //该方法被声明为protected,即子类可以覆盖该方法以改变行为
42     addParametersToContext(ActionContext.getContext(), acceptableParameters);
43 }  

先判断提交过来的参数是否合法,因为提交过来的参数会影响到值栈所以struts2要对提交过来的参数进行合法性检查,以防止恶意用户的攻击,凡是请求参数中表达式中含有等号(=),逗号(,),#号(#)的都是非法表达式

至于怎么判断是否合法,我已经没兴趣了,知道是acceptableName(name)方法决定的。



了解了这么多感觉用的更随心所欲了。急需做无聊的毕业设计



关于struts2的modelDriven

时间: 2024-08-29 15:47:25

关于struts2的modelDriven的相关文章

Struts2实现ModelDriven进行属性驱动

1. 实现ModelDriven的作用 ModelDriven,属性驱动十分有用,form表单提交的的name,和类中的set方法名称想对应,就可以实现自动注入. 2. Struts2实现ModelDriven 3. 属性注入,必须要字段的set方法是public修饰的 原文地址:https://www.cnblogs.com/xyyz/p/8446816.html

Struts2之ModelDriven的使用

Java代码 我们可以根据Action属性的不同将它分为两类:Field-Driven(属性驱动)Action和Model-Driven(模型驱动)Action. 一.Field-Driven(属性驱动)Action,Action拥有自己的属性,这些属性一般是Java的基本类型.表单字段直接和Action的属性对应. 二.实现了modelDriven接口可以在action中直接获得例如User对象,它会将ObjectgetModel()取得的User放到ValueStack中.可以理解为将这个U

Struts2 的ModelDriven理解

以UserAction为例,当UserAction实现了ModelDriven接口之后,与该接口相关的默认配置的拦截器会在拦截请求之后判断该请求是将要被UserAction处理而且UserAction实现了ModelDriven接口,因此就会在执行UserAction的相应方法之前,调用getModel方法,将UserAction中的Model类(比如Use)r的对象(假设为u)压入ValueStack中,作为root对象.这时候如果提交的表单或者url中传值过来,比如username,pass

Struts2使用ModelDriven后JSON数据返回不正确

在struts.xml中加入<param name="root">action</param> <result name="exist" type="json"> <param name="root">action</param> </result>

[JavaWeb基础] 018.Struts2 MVC架构之ModelDriven

用过struts1的人接触struts2的时候,通常会产生一个疑惑,明明struts1已经把action的form分开了,为什么struts2确把模型放在action中定义.其实这个方式只是想让action更加直观,但是如果表单数据过多的话,action类就会出现过于冗长,所以struts2的ModelDriven就要出来解决问题了.下面讲讲ModelDriven的机制 1.工作原理 ModelDriven的机制背后就是ValueStack.界面可以通过直接指定对象的属性名就能给对象进行赋值.

struts2学习笔记之五:表单数据收集的几种方式

方法一:struts2对ModelDriven模式的支持(模型驱动模式) Struts2可以采用类似于Struts1中的ActionForm方式收集数据,这样方式叫ModelDriven模式 Action需要实现ModelDriven接口,实现getModel()方法,返回Bean对象,这样struts2会通过getModel()方法拿到对象,使用set方法把数据填充到对象中 创建User类(Bean对象,包含geter方法和seter方法的纯java类) User类 package com.d

Struts2表单数据接收方式

1.将Action类作为一个POJO,直接进行接收 在Action类内部定义字段名称,并为之声明get/set方法.页面表单name属性与定义字段名称相同. package com.common.login; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class LoginAction extends ActionSupport{ private String n

struts2理解

(1) Struts2(一)---struts2的环境搭建及实例 (2) struts2(二)---ModelDriven模型驱动 (3) Struts2属性驱动与模型驱动 (4)

struts2进阶篇(2)

一.Action与MVC struts2是一个基于MVC的web应用框架,它将应用程序分为三个组件:模型,视图,控制器. 模型:包含了应用程序的业务逻辑和业务数据,由封装数据和处理业务的javaBean组成. 视图:封装了应用程序的输出形式,也就是页面,如jsp,html. 控制器:负责接收用户的http请求,再调用模型中响应的方法来处理业务,然后调用响应的视图作为显示. 三者共同协同处理响应客户端的请求. 在struts2中控制器分为两部分: 1.核心控制器:它就是在web.xml中配置的St