论坛首页 Java企业应用论坛

关于webwork字段值自动邦定的困惑

浏览 25726 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-07-08  
下面是我向moxie请教时的提问:
引用
moxie,您好!

看了你的<webwork教程>获益良多,我使用webwork也有一段时间了,但最近一直碰到一个问题,总无法解决,特向你请教:

在你的教程中讲到了Field driven action, 并举了一个用户注册的例子, 其中页面上的user.name值可以被WW自动邦定到action中的user对象中. 在你的例子中,getUser()方法返回的是一个new User()对象,但如果是修改用户属性,此时getUser()应该返回用户正在编辑的user, 那么getUser()如何得到该对象呢? 在我想来有两个方法:
一是当要修改用户属性时,先将要修改的user保存在session中,那么getUser()方法就可以从session中取得正在编辑的user, 这种方法有其局限性, 我不太喜欢;
第二种方法是在getUser()方法内部,直接从ActionContext中取得userId参数,并调用service的getUserById()方法来取得user, 但这种做法我总感觉不够优雅, 这个问题困扰我很久了,一直不知如何是好? 不知你有没有更好的方法?


下面是moxie的回复:
引用
jxb,您好!
    我想你应该是没有完全理解ValueStack(值堆栈,在XWork中,它是OgnlValueStack)。当你提交一个表单到action中,在它执行之前,由框架去取得你的Action,并实例化这个Action对象,再将这个Action对象放入它的值堆栈中。
    这时候,你在做编辑的时候,它一定会有原始的数据,假设这个数据对象就是user,同时假设这个数据就是从数据库中取得的。
   你要编辑这个user对象的数据,当然你的视图(也许是页面)要获取原始的数据。如何获取?你可以通过EL(表达式语言)从OgnlValueStack中获取。你的EL:user.username,它就是相当于调用Action对象的getUser().getUsername();方法。通过这种方式,你可以在视图中取得原始数据。
  到这里,我想你都能明白。但请注意下面:
  在你对原始数据进行更新时,你希望这个更新的数据同步到user对象中。这时,你仍然是通过EL,进行值的设置(注意:前面是值的获取)。你的EL:user.username,它这是相当于调用代码:getUse.setUsername(你更新的值)。

WebWork的简洁、灵活,很多都是来源于EL和ValueStack。

不知道我的回答是否能解决你的问题,更好的解决方式是通过简单的代码来实现,你可以写一些程序来验证,当然,如果有疑问我也可以帮忙完善。


谢谢moxie的及时回复, 但可能我没有表达清楚我的问题,我想再用代码重新说明一下,同时为了再次得到moxie的及时回复,我特地将这个问题拿到论坛中请大家帮我解域,也免得邮件来邮件去的,等得我心焦^_^
	//user.detail.vm

	<input type="text" name="user.name" value="$!user.name"/>
	<input type="hidden" name="userId" value="$!user.id"/>

	//ViewUserAction.java

	private User user;
	private String userId;

	public String execute(); {
		return SUCCESS;
	}
	public void setUserId(String userId); { this.userId = userId; }

	public User getUser(); { 
		if (user == null); {
			user = userService.getUserById(userId);;
			//采用第一种方法时才需要下面的语句
			ActionContext.getActionContext();.getSession();.put("__user__", user);;
		}
		return user;
	}

	//CreateUserAction.java

	//创建一个空的用户对象
	private User user = userService.createUser();;

	public String execute(); {
		userService.save(user);;
		return SUCCESS;
	}

	public User getUser(); { return user;}

	//ModifyUserAction.java

	private User user;
	
	public String execute(); {
		userService.save(user);;
		return SUCCESS;
	}

	public User getUser(); {
		//方法1:
		//当用户进入user.detail.vm时,ViewUserAction.java已将用户
		//正在查看的对象保存到了session中所以现在可以取出
		return (User);ActionContext.getActionContext();.getSession();.get("__user__");;

		//方法2:
		if (user == null); {
			String userId = getParameter("userId");;
			user = userService.getUserById(userId);;
		}
		return user;
	}

    我的问题是: 在ModifyUserAction.java中getUser()方法应该如何实现?
    我给出的方法1有特定的限制,比如只能允许用户在一个页面中一次只能修改一个用户的信息, 另外ViewUserAction与ModifyUserAction也有一种隐含的藕合,所以我不愿意采用该方法,第二种方法要我自己从parameters中取出userId这个参数,然后转换为user对象, 因为页面中有许多参数存在于parameters中,其它参数都可以由webwork自动邦定,可为什么userId这个参数要这么特殊呢? 这就是我觉得不爽的地方. 另外我也想到能不能用interceptor解决,感觉这个interceptor做出并不能通用,所以和第二种方案还是同一回事.
   发表时间:2004-07-08  
其实你只要将你传递的参数userId更改成user.userId就行了
         user = userService.getUserById(user.getUserId(););; 

0 请登录后投票
   发表时间:2004-07-08  
我认为你的方法行不通,因为user对象的userId还没有被ParameterInteceptor邦定到user中, 除非有两个ParameterInteceptor, 前一个负责邦定id, 后一个负责邦定其它参数, 或者ParameterInteceptor在邦定参数时能设定顺序, 也就是能先邦定id, 再邦定其它参数. 不过都是瞎想,行不通.
0 请登录后投票
   发表时间:2004-07-08  
jxb8901 写道
我认为你的方法行不通,因为user对象的userId还没有被ParameterInteceptor邦定到user中, 除非有两个ParameterInteceptor, 前一个负责邦定id, 后一个负责邦定其它参数, 或者ParameterInteceptor在邦定参数时能设定顺序, 也就是能先邦定id, 再邦定其它参数. 不过都是瞎想,行不通.


我都测试过了,怎会不行呢?
比如因为你修改一个用户的资料时候,肯定要有ID传过来,如果你传的是userId,那你肯定要自己转换,如果你传的是user.userId,系统会自动帮你将这参数绑定到你的变量user中去。
例如
http://localhost:8080/edit_user.action?user.userId=12345
你在edit_user.action中
直接写
user = getUserById(user.getUserId(););;
就行了
0 请登录后投票
   发表时间:2004-07-08  
不知能不能把你的getUser()的代码贴出来,我们对着代码好说话一点, 这样空谈半天, 可能都说的不是同一回事.

能把getUser()的代码贴出来吗? 而且你测试至少应该传两个参数:user.userId,user.name
0 请登录后投票
   发表时间:2004-07-08  
zgd为什么把回复给删掉了? 我还正在想总算有人看得懂我的问题呢(很担心我表达不清) ^_^
0 请登录后投票
   发表时间:2004-07-08  
给你抓到了
我看了后来你的回帖
觉得我的问题跟你的问题好像有出入
所以自己开了一篇新帖了

下面是删掉的原贴
--------------------------------------------------------
如果User是一个hibernate的PO的话
把它放在httpSession里不失为一种好方法
页面里直接对httpSession里的user操作
当进行saveAction的时候
从httpSession里拿到的user就能直接用hibernateSession.update回数据库
这也是那个webwork2+hiberate的demo adminapp里的做法
ps,adminapp在这里http://wiki.opensymphony.com/display/WW/Examples

但是比较严重的问题就是不能同时打开两个修改user的页面,另外就是如果不在使用完以后立刻删除该httpSession变量的话就是持续占有服务器内存

如果不用httpSession的话,就必须把user里不需要显示到页面的属性用hidden记录下来,但是如果user有list(一对多或多对多关系)那怎么办呢?这似乎无法解决,折中的解决办法就是把主键id写到hidden里,然后在saveAction里使用select&update的方法(这里可以构造一个formBean),这也并不优雅
0 请登录后投票
   发表时间:2004-07-08  
你的意思是否是user_detail.jsp 中可以进行用户资料的更改,但是保存是在另外一个页面user_save,
问题是当从user_detail导航到user_save的时候,user_save如何取到user_detail页更改过的user,由user_save负责将这个user存储到数据库。对吗?
不知道我的理解是不是正确?
0 请登录后投票
   发表时间:2004-07-08  
不完全正确.
1.user_save是一个action类,不是页面
2.不是说user_save如何取到user_detail中的user, 而是说user_detail中的字段值如何自动邦定到user_save中的一个user对象, 其实邦定是webwork自动完成的, 关键是userid如何转换为数据库中的user对象.
如果你没用过webwork,可能不太能理解我提的问题, 如果你愿意的话我可以发一段代码给你.(还是代码好说话)
0 请登录后投票
   发表时间:2004-07-08  
To:jxb8901
你的问题我能明白,我想是我的回答太抽象,让你误解了。现写的演示代码如下:

//xwork.xml:
    <package name="cuid" extends="webwork-default" namespace="/cuid">
    	<default-interceptor-ref name="params"/>
    	
    	<action name="listAllUsers" class="example.cuid.ListAllUsersAction" >
    		<result name="success" type="velocity">
    			<param name="location">/cuid/listAllUsers.vm</param>
    		</result>
    	</action>
    	<action name="viewUser" class="example.cuid.ViewUserAction" >
    		<result name="success" type="velocity">
    			<param name="location">/cuid/editUser.vm</param>
    		</result>
    	</action>
    	<action name="updateUser" class="example.cuid.UpdateUserAction" >
    		<result name="success" type="chain">
    			<param name="actionName">listAllUsers</param>
				<param name="namespace">/cuid</param>
    		</result>
    	</action>
    </package>




ListAllUsersAction.java

/*
 * Created on 2004-7-8
 * ListAllUsersAction.java
 */
package example.cuid;

import com.opensymphony.xwork.Action;

import example.register.User;

/**
 * @author moxie-qac
 *         achqian@yahoo.com.cn
 * 
 */
public class ListAllUsersAction implements Action{
	private User[] users;

	/* (non-Javadoc);
	 * @see com.opensymphony.xwork.Action#execute();
	 */
	public String execute(); throws Exception {
		UserService userService = UserService.getUserService();;
		users = userService.ListAllUsers();;
		return SUCCESS;
	}
	
	public User[] getUsers();{
		return users;
	}

}


ViewUserAction.java
/*
 * Created on 2004-7-8
 * ViewUserAction.java
 */
package example.cuid;

import com.opensymphony.xwork.Action;

import example.register.User;

/**
 * @author moxie-qac
 *         achqian@yahoo.com.cn
 * 
 */
public class ViewUserAction implements Action{
	private String userId;
	private User user;

	/* (non-Javadoc);
	 * @see com.opensymphony.xwork.Action#execute();
	 */
	public String execute(); throws Exception {
		UserService userService = UserService.getUserService();;
		user = userService.getUserById(userId);;
		return SUCCESS;
	}
	
	public void setUserId(String userId);{
		this.userId = userId;
	}
	
	public User getUser();{
		return user;
	}

}



UpdateUserAction.java
/*
 * Created on 2004-7-8
 * UpdateUserAction.java
 */
package example.cuid;

import com.opensymphony.xwork.Action;

import example.register.User;

/**
 * @author moxie-qac
 *         achqian@yahoo.com.cn
 * 
 */
public class UpdateUserAction implements Action{
	private User user = new User();;

	/* (non-Javadoc);
	 * @see com.opensymphony.xwork.Action#execute();
	 */
	public String execute(); throws Exception {
		UserService userService = UserService.getUserService();;
		userService.update(user);;
		return SUCCESS;
	}
	
	public User getUser();{
		return user;
	}
}

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics