今天重构以前代码过程中发现一个struts2设置参数的问题,前后足足追了半天,顺便看了OGNL的源码,在这里记录下原因和解决方案:
在struts2的action中接收参数时,通常我是不喜欢写getter,只写setter。这样可以更加清楚的表示这是一个输入参数,比如
public class XXAction{
private int size;
public viod setSize(int size){
this.size=size;
}
}
当只接收普通类型时没有问题,可对于如下复杂类型
public class PageBean{
int pageSize;
int pageNo;
String orderBy;
// getter &setter
// ...
}
如果不写getter
public class XXAction{
private PageBean page;
public void setPage(PageBean page){
this.page=page;
}
}
前端传过来的参数 page.pageSize=10&page.pageNo=1&page.orderBy=name
在execute()方法中会发现page对象只有 pageSize被赋值了(10),pageNo和orderBy都为null。而且无论怎么调整传入参数的顺序结果都是一样的。
这个问题让我很费解,网上找了半天也没找到答案,老老实实的去跟OGNL的源码,最后发现原因是这样的:
1) OGNL 首先收集所有需要赋值的属性( page.pageSize, page.pageNo, page.orderBy)
2) 如果是复杂对象(如这里的PageBean),OGNL并不是首先构造好这个PageBean,赋上所有的值(pageSize,pageNo,orderBy),然后再把整个对象赋给action.page;而是通过一个循环依次往action.page这个对象上追加值。循环中每次执行时并不知道action.page对象是否已经执行过初始化,所以每次都要用以下方法测试action.page是否存在,若不存在则会初始化它 (action.page=new PageBean()), 然后完成本次赋值
if (OgnlRuntime.hasSetProperty(ognlContext, o, name)) {
OgnlRuntime.setProperty(ognlContext, o, name, value);
return;
}
由于我没有在Action中对page属性写setter,所以.hasSetPropertyf方法每次都会返回false,然后OGNL就会傻傻的重新初始化并赋值, 对于以上三个属性,它一共会初始化page对象三遍,而只保留下最后赋值的属性pageSize。
至于为什么每次都是pageSize排在最后呢? 这是因为OGNL在步骤1)中收集对象时用的是 TreeMap, 而前段穿过来的这三个key(page.pageSize, page.pageNo, page.orderBy) 按照String.compareTo()的实现总是page.pageSize排在最后一个。
知道了原因,解决方法当然很简单,只要加上 page属性的setter就行了。不过这里还是要对Struts的设计吐个槽,如果是我来设计,输入参数肯定不会要求实现者提供getter,而是用一个Map保存对象的中间状态,最后统一调用setter赋给action。 现在这种拿action当临时对象用的方法看起来简化了一些实现,但作为框架来说,强制要求使用者提供getter完全是过分的要求。
分享到:
相关推荐
Struts 2无须继承任何类型或实现任何接口,表单数据包含在Action中,通过Getter和Setter获取。 虽然,在理论上Struts2的Action无须实现任何接口或者是继承任何的类,但是,在实际编程过程中,为了更加方便的实现...
2.Struts2和Struts1.x的差别, 最明显的就是Struts2是一个pull-MVC架构。 这是什么意思呢?从开发者角度看, ... Struts 2无须继承任何类型或实现任何接口,表单数据包含在Action中,通过Getter和Setter获取。
Apache官方已针对该漏洞发布安全公告,ApacheStruts 2.3.5 – 2.3.31版本及2.5 – 2.5.10版本存在远程代码执行漏洞(CNNVD-201703-152 ,CVE-2017-5638)。该漏洞是由于上传功能的异常处理函数没有正确处理用户输入...
允许POJO(Plain Old Java Objects,简单javabean对象,没有继承,没有实现,getter,setter方法)对象 作为Action,没有耦合 Action的execute 默认方法不再与Servlet API耦合,更易测试 支持更多视图技术(JSP(转译java...
在File Name中输入struts.xml(必须为此名),单击Finish。Struts.xml的代码为: <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" ...
eclipse中的setter与getter注释,实体的编写,在代码编写工程中能清晰了解此意
·关闭时保存编辑现场,包括当前排版助手中的文本以及光标位置 ·小工具箱里增加“去掉汉字间的空格”、“生成随机字符串”两项功能 功能改进: ·快捷工具条增加排版设置按钮 ·更换了玻璃质感的图标 ·其它显示上...
java 的eclipse或idea等 定义变量时 直接引入lombok.jar包 在类外部 引入@AllArgsConstructor @NoArgsConstructor @Data 简便方法引入getter/setter/tostring等方法
1.通过对象初始化器在创建对象的时候指明(也可以称为通过字面值创建对象时声明) (function () { var o = { a : 7, get b(){return this.a +1;},//通过 get,set的 b,c方法间接性修改 a 属性 set c(x){this.a =...
排版助手gidot typesetter 是一款比较受欢迎的智能文章排版软件,这款排版软件不大,且不需要安装即可轻松实现编辑排版。 排版助手gidot typesetter主要功能:段落智能修正、去掉某些防拷贝的干扰符、修正段落首尾...
eclipse 自动为getter和setter添加中文注释 详细参见 http://blog.csdn.net/kongguoan/article/details/38293137
Laravel开发-setter 将数据库设置与Laravel集成的简单方法。
Typesetter CMS简介 TypesetterCMS是一个功能全面的网站内容管理系统,其嵌入式的管理接口可以让用户在一个简单的浏览器窗口中看到网站的改变。 Typesetter CMS特色功能: 真正的所见即所得编辑器 (CKEditor) ...
Gidot TypeSetter是一款广受编辑追捧的智能排版整理文章的软件,该软件短小精悍,无需安装即可使用。适合新闻采集员、编辑、文摘网及有文章排版需求者。 软件主要功能:段落智能修正、去掉某些防拷贝的干扰符、修正...
java普通类编译成json但只是当前类的有getter、setter方法的版本
软件名称:排版助手 GIDOT TYPESETTER 当前版本:3.0.6 作者:GIDOT 邮箱:GIDOT@VIP.QQ.COM 网站:WWW.GIDOT.CN/TYPESETTER 新增功能: ·批量排版功能 ·多文本文件合并成单一文本文件 功能改进: ·将排版工具...
主要介绍了Vue getter setter,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
这个gem允许您定义“不可变的”对象,使用它时,您的对象将仅具有getter而没有setter。 因此,如果更改[ ] [ ]对象的属性,则将有一个新的对象实例。 也就是说,您可以变换对象而不是对其进行修改。文献资料版本...
Gidot TypeSetter文章自动排版工具