当前位置: 首页 > 技术随笔 > struts1处理ActionForm的一些细节

struts1处理ActionForm的一些细节

struts1在处理请求参数之前,首先会根据配置文件action节点的name属性创建对应的ActionForm。如果配置了name属性,却找不到对应的ActionForm类也不会报错,只是不会处理本次请求的请求参数。

如果找到了对应的ActionForm类,则先判断是否已经存在ActionForm的实例,如果不存在则创建实例,并将其存放在对应的作用域中。作用域由配置文件action节点的scope属性来指定,其值可以为request或session(存储在作用域中的属性名由action节点配置的attribute属性指定,如果没有该属性,则由name属性指定)。其部分源代码如下:

 //ClassName:org.apache.struts.action.RequestProcessor

 protected ActionForm processActionForm(HttpServletRequest request,
        HttpServletResponse response, ActionMapping mapping) {
        // Create (if necessary) a form bean to use
        ActionForm instance =
            RequestUtils.createActionForm(request, mapping, moduleConfig, servlet);

        if (instance == null) {
            return (null);
        }

        // Store the new instance in the appropriate scope
        if (log.isDebugEnabled()) {
            log.debug(" Storing ActionForm bean instance in scope '"
                + mapping.getScope() + "' under attribute key '"
                + mapping.getAttribute() + "'");
        }

        if ("request".equals(mapping.getScope())) {
            request.setAttribute(mapping.getAttribute(), instance);
        } else {
            HttpSession session = request.getSession();

            session.setAttribute(mapping.getAttribute(), instance);
        }

        return (instance);
    }

接着,struts1开始处理request请求参数,并将其放置在一个HashMap中,最后调用

//bean为ActionForm实例
//properties为存放请求参数的HashMap
BeanUtils.populate(bean, properties);

将请求参数中对应参数的值赋给ActionForm中对应的属性名,并且支持嵌套属性赋值。例如名为user.name的参数值,BeanUtils将会赋值给ActionForm中属性名为user的对象的name属性。

不过由于在struts1中为ActionForm的属性赋值几乎完全依赖于BeanUtils工具类,因此在默认情况下,struts1只能为Java中的简单数据类型进行正确的处理并赋值,例如int、double、String、HashMap等。而对于较为复杂的自定义对象或集合赋值则相对要麻烦一点。
例如ActionForm中存在属性名为user的自定义类型User(User对象具备name、age等属性),相关代码如下:

private User user;

public User getUser() {
	return user;
}

public void setUser(User user) {
	this.user = user;
}

这也是我们在JavaBean中最常见的属性代码编写方式。如果前端请求表单中包含名为user.name的参数,按照上面的写法,struts1无法为其正确赋值。因为实际上,struts1是通过类似于

User user = actionForm.getUser();
user.setName("user.name的参数值");

的方式来进行赋值的。
struts1在对于自定义类型或集合类型时,首先调用对应的get方法来获取对应的实例,然后为实例中的属性赋值。即使get方法返回的实例为null,struts1也不会自动创建实例,这样就导致了赋值出错(struts2在获取的实例为null时,将自动调用空的默认构造函数来创建对应的实例)。

对于集合类型List也是如此,如果ActionForm中定义了一个List<User>类型的集合属性users,而前端请求传来的参数名为users[0].name。struts1将会调用getUsers(0)来获取单个User实例,然后再调用该实例的setName方法来赋值。

对于这种比较特殊的自定义对象或集合类型,一般采用的解决方法是,单独编写一个供struts调用的获取对应实例的方法。例如为上面的User属性赋值,即可编写如下代码:

private User myUser;

/**
 * 为开发人员提供的获取user属性的方法
 * @return
 */
public User getMyUser() {
	return myUser;
}

/**
 * 为开发人员提供的设置user属性的方法
 * @param myUser
 */
public void setMyUser(User myUser) {
	this.myUser = myUser;
}

/**
 * 本方法提供给struts1调用
 * @return
 */
public User getUser() {
	if (this.myUser == null) {
		this.myUser = new User();
	}
	return this.myUser;
}

为上面List<User>类型的属性赋值,可以编写如下代码:

private List<User> myUsers;

/**
 * 为开发人员提供的获取users属性的方法
 * @return
 */
public List<User> getMyUsers() {
	return myUsers;
}

/**
 * 为开发人员提供的设置users属性的方法
 * @param myUsers
 */
public void setMyUsers(List<User> myUsers) {
	this.myUsers = myUsers;
}

/**
 * 提供给struts1调用的获取单个User实例的方法
 * @param index
 * @return
 */
public User getUsers(int index) {
	// 如果集合为空,创建集合
	if (this.myUsers == null) {
		this.myUsers = new ArrayList<User>();
	}
	int size = this.myUsers.size();
	if (index >= size) {
		// 索引序号大于当前集合的元素个数,则扩展该集合达到指定索引
		for (int i = size; i <= index; i++) {
			// 根据自己的实际需要确定这里添加的元素为null还是实例
			myUsers.add(new User());
		}
	}
	return myUsers.get(index);
}
4 0
我们认为: 用户的主要目的,是为了获取有用的信息,而不是来点击广告的。因此本站将竭力做好内容,并将广告和内容进行分离,确保所有广告不会影响到用户的正常阅读体验。用户仅凭个人意愿和兴趣爱好点击广告。
我们坚信:只有给用户带来价值,用户才会给我们以回报。
CodePlayer技术交流群1CodePlayer技术交流群1

帮朋友打一个硬广告:

P2P网贷系统(Java版本) 新年低价大促销,多年P2P技术积累,系统功能完善(可按需定制,可支持第三方存管、银行存管),架构稳定灵活、性能优异、二次开发快速简单。 另可提供二次开发、安装部署、售后维护、安全培训等一条龙服务。

外行看热闹,内行看门道。可以自信地认为,在系统设计上,比市面上的晓风、迪蒙、方维、绿麻雀、国融信、金和盛等P2P系统要好。
深圳地区支持自带技术人员现场考察源代码、了解主要技术架构,货比三家,再决定是否购买。

也可推荐他人购买,一旦完全成交,推荐人可获得实际售价 10% 的返现。
有意向者,详情请 点击这里 联系,工作时间立即回复。