struts2.0.14对象注入的一个问题(姑且算是一个BUG)

1 问题的起因

    遇到这个问题的时间很悲剧,刚好在项目发布的当头.在运营修改一些业务数据的时候发现某一个参数无法修改!!!怎么传都传不了.注意,只有一个参数是无法修改的.其他的参数都可以

    我马上查看源码,发现这个参数的名字是

<input type="text"  value="<s:property value='couponBuy.bookPhone'/>" name="couponBuy.bookPhone" id="coupon-order-r3-desc" >

 但是通过修改代码debug发现,在Action中打印出这个参数信息却是是null.初步的判断是页面传到Action的时候造成了参数的丢失.然后通过firebug查看,发现'couponBuy.bookPhone'确实是有值的..线索由此断了.中间折腾了差不多两个小时,一直无法解决.最后通过修改参数传入名字

<input type="text"  value="<s:property value='couponBuy.bookPhone'/>" name="bookPhone" id="coupon-order-r3-desc" >

然后在Action中自己手工注入到couponBuy对象中..采取了这种临时的解决方案

2  后续的跟进

    新建了新的web工程,进行测试,努力模拟当时的情况,在什么情况下会出现这种无法注入的情况.经过一番折腾.终于发现元凶.元凶的代码是

public CouponBuy getCouponBuy() {
		if (couponBuy == null) {// 表示是新增操作,必须首先赋值CategoryId
			couponBuy = new CouponBuy();
			couponBuy.setCategoryId(CouponBuyUtil.getCategoryId());
			couponBuy.setPublishUserName(this.getUser().getUserName());
		}
		return couponBuy;
	}

 很明显,上面这个是couponBuy对象的get方法.一般来说,struts2在依赖注入的时候会先调用这个方法(由于业务逻辑需要,所以必须自己去创建couponBuy对象).但是我注意到,运营在修改couponBuy对象的时候是不需要登录的!!也就是说,照理来说,这里应该会报一个空指针异常..根据这个情况,进行模拟.

pojo类

/**
 * @author zhenghui 
 * @version 1.0 
 * @date 2011-6-2 下午04:57:47
 * 
 */
public class CouponBuy implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -3869627789513451015L;
	
	private String bookPhone;
	private String name;
	private String descrbtion;
	private String abc;
// get set 方法略
}

对应的Action

package com.koubei.action;

import com.koubei.pojo.CouponBuy;
import com.opensymphony.xwork2.ActionSupport;

/**
 * @author zhenghui E-mail: [email protected]
 * @version 1.0 
 * @date 2011-6-2 下午04:36:37
 * 
 */
public class SubmitAction extends ActionSupport {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6074612093907655532L;
	
	private CouponBuy couponBuy;
	
	
	@Override
	public String execute() throws Exception {
		System.out.println(couponBuy.getBookPhone());
		System.out.println(couponBuy.getName());
		System.out.println(couponBuy.getDescrbtion());
		System.out.println(couponBuy.getAbc());
		return super.execute();
	}

	public CouponBuy getCouponBuy() {
		if(couponBuy == null){
			couponBuy = new CouponBuy();
			throw new NullPointerException();
		}
		return couponBuy;
	}

	public void setCouponBuy(CouponBuy couponBuy) {
		this.couponBuy = couponBuy;
	}
	

}

 直接抛出空指针异常,然后传入对应的参数

http://localhost/WebTest/submit.html?couponBuy.name=name&couponBuy.descrbtion=desc&couponBuy.bookPhone=05714788339&couponBuy.abc=abc

 结果是

05714788339
name
desc
null

也就是说,abc参数丢失了!!.问题在于:

1 传入4个参数,但是couponBuy.abc 这个参数丢失了!其他都正常

2 最大的问题是,竟然没有报错的日志!!console下没有,结果页也是正常的,就是没这个参数而已...

    问题终于发现,就是由于struts2在给我们做对象的注入的时候,会把空指针异常给吃了.然后会把某一个参数注入为Null.但是其他的参数都注入正常.

3 继续查看问题

   这个问题虽然解决了,但是还是引出了其他几个问题.

(1)是否高版本的struts2还存在这个问题

(2)那个丢失的参数,规则是什么..

后续的解决

(1)这个问题我换成struts2.2.1版本来跑同样的程序.发现console日志输出里已经报了空指针异常.也就是说,高版本中这个吃异常的BUG已经修正了.但是还是会将某一个参数制空,其他参数正确传入.

(2)经过测试,struts2的规则是根据对象属性进行排序,在第一个注入的就会制空,后面注入的参数能正确被注入.比如上面的属性中 abc < bookPhone 所以abc首先被注入,所以丢失数据.如果我把abc属性删除,则bookPhone参数是最小的,则这个参数首先被注入,也就之前我在项目中遇到的丢失问题...

4 最后的总结.

struts2关于标签部分的代码没看,所以无法从根本上总结出这个BUG的所在..等待后人研究了..看源码的话没有这么快搞定..

猜你喜欢

转载自chenjingbo.iteye.com/blog/1071793