您的位置:首页 > 编程语言 > Java开发

Struts2整合Json插件时的一个隐蔽BUG-----struts2-json-plugin-2.1.8

2010-02-24 15:56 429 查看
结论:

在使用了Json插件的所有Struts2的Action中,

1. 避免使用get开头的action方法(用来转发的方法),

2. 严格的为json类型的result配置includeProperties, excludeProperties等参数.



/**
 * @modifier: selfimpr
 * @blog: http://blog.csdn.net/lgg201  * @email: lgg860911@yahoo.com.cn
 */
private void bean(Object object) throws JSONException {
	this.add("{");

	BeanInfo info;

	try {
		Class clazz = object.getClass();

		info = ((object == this.root) && this.ignoreHierarchy) ? Introspector.getBeanInfo(clazz, clazz
				.getSuperclass()) : Introspector.getBeanInfo(clazz);

		//这里得到的是指定的根对象中所有的get开头的方法对应的描述对象
		PropertyDescriptor[] props = info.getPropertyDescriptors();

		boolean hasData = false;
		for (int i = 0; i < props.length; ++i) {
			PropertyDescriptor prop = props[i];
			//getter对应的属性名称
			String name = prop.getName();
			//getter方法自己
			Method accessor = prop.getReadMethod();
			Method baseAccessor = null;
			if (clazz.getName().indexOf("$$EnhancerByCGLIB$$") > -1) {
				try {
					baseAccessor = Class.forName(
							clazz.getName().substring(0, clazz.getName().indexOf("$$"))).getMethod(
							accessor.getName(), accessor.getParameterTypes());
				} catch (Exception ex) {
					LOG.debug(ex.getMessage(), ex);
				}
			} else
				baseAccessor = accessor;

			if (baseAccessor != null) {

				JSON json = baseAccessor.getAnnotation(JSON.class);
				if (json != null) {
					if (!json.serialize())
						continue;
					else if (json.name().length() > 0)
						name = json.name();
				}

				// ignore "class" and others
				if (this.shouldExcludeProperty(clazz, prop)) {
					continue;
				}
				String expr = null;
				//这里会检查通过给result配置includeProperties, excludeProperties等参数进行的属性过滤
				//所以, 如果有严格的过滤配置, 也不存在问题.
				if (this.buildExpr) {
					expr = this.expandExpr(name);
					if (this.shouldExcludeProperty(expr)) {
						continue;
					}
					expr = this.setExprStack(expr);
				}

				//如果上面没有过滤, 那么这个getter会被调用.
				//问题就出在这个地方.
				//如果你的Action中有以get开头的响应方法, 这里也会被当作是属性的getter拿进来.
				//如果没有在includeProperties, excludeProperties等参数中过滤掉, 会被下面这句去执行.
				//这个问题一般情况下是不会有表象的, 仅仅是"悄悄的"多执行了一些数据库操作
				//但是, 特殊情况如下: 
				//1. 假设请求的Action为: user!findAll.action, 用来响应获取所有的用户
				//2. 假设UserAction中还有一个响应方法, getAllUserByGroup, 这个用来响应获取某个组的用户
				//3. 假设返回json, 而没有过滤掉getAllUserByGroup对应的名称allUserByGroup
				//4. 假设UserAction中有一个属性List users, 并且findAll和getAllUserByGroup都用这个属性存储
				//结果是很严重的, 当你请求findAll这个Action的时候, findAll中的代码首先加载users, 得到
				//了所有的用户.     返回result 交给JSONWritter解析, 它会把getAllUserByGroup作为
				//一个属性的getter方法来解析并调用, 这样, getAllUserByGroup中的代码就会再次运行, 修改users
				//的值.
				//这个问题一旦出现, 非常不易察觉......
				
				//如果没有使用只有getter和setter方法而没有属性的代码习惯, 那么请修改struts2-json插件这个位置, 
				//加入下面代码
				//if(object.getDeclaredField(name)  == null) continue;
				Object value = accessor.invoke(object, new Object[0]);
				boolean propertyPrinted = this.add(name, value, accessor, hasData);
				hasData = hasData || propertyPrinted;
				if (this.buildExpr) {
					this.setExprStack(expr);
				}
			}
		}

		// special-case handling for an Enumeration - include the name() as
		// a property */
		if (object instanceof Enum) {
			Object value = ((Enum) object).name();
			this.add("_name", value, object.getClass().getMethod("name"), hasData);
		}
	} catch (Exception e) {
		throw new JSONException(e);
	}

	this.add("}");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: