锁定老帖子 主题:关于webwork字段值自动邦定的困惑
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2004-07-08
引用 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做出并不能通用,所以和第二种方案还是同一回事. 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2004-07-08
其实你只要将你传递的参数userId更改成user.userId就行了
user = userService.getUserById(user.getUserId(););; |
|
返回顶楼 | |
发表时间:2004-07-08
我认为你的方法行不通,因为user对象的userId还没有被ParameterInteceptor邦定到user中, 除非有两个ParameterInteceptor, 前一个负责邦定id, 后一个负责邦定其它参数, 或者ParameterInteceptor在邦定参数时能设定顺序, 也就是能先邦定id, 再邦定其它参数. 不过都是瞎想,行不通.
|
|
返回顶楼 | |
发表时间: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(););;就行了 |
|
返回顶楼 | |
发表时间:2004-07-08
不知能不能把你的getUser()的代码贴出来,我们对着代码好说话一点, 这样空谈半天, 可能都说的不是同一回事.
能把getUser()的代码贴出来吗? 而且你测试至少应该传两个参数:user.userId,user.name |
|
返回顶楼 | |
发表时间:2004-07-08
zgd为什么把回复给删掉了? 我还正在想总算有人看得懂我的问题呢(很担心我表达不清) ^_^
|
|
返回顶楼 | |
发表时间: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),这也并不优雅 |
|
返回顶楼 | |
发表时间:2004-07-08
你的意思是否是user_detail.jsp 中可以进行用户资料的更改,但是保存是在另外一个页面user_save,
问题是当从user_detail导航到user_save的时候,user_save如何取到user_detail页更改过的user,由user_save负责将这个user存储到数据库。对吗? 不知道我的理解是不是正确? |
|
返回顶楼 | |
发表时间:2004-07-08
不完全正确.
1.user_save是一个action类,不是页面 2.不是说user_save如何取到user_detail中的user, 而是说user_detail中的字段值如何自动邦定到user_save中的一个user对象, 其实邦定是webwork自动完成的, 关键是userid如何转换为数据库中的user对象. 如果你没用过webwork,可能不太能理解我提的问题, 如果你愿意的话我可以发一段代码给你.(还是代码好说话) |
|
返回顶楼 | |
发表时间: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; } } |
|
返回顶楼 | |