[Ajax4JSF] 对于JSF的表格真的是无语了
kimmking
2008-05-20
一般来说 大数据量 下
我们每次都只取一页的数据 而已。 如果你没有翻页 并且刷了页面 你又不想缓存数据的话 你的数据必须重取 !!! 我们不缓存数据 我们缓存获取数据的条件和状态而已 |
|
terryzhou
2008-05-20
风之狐 写道 to:terryzhou
1.这个例子很简单,贴出来的页面代码是显示所有User的,点击的时候往后台传一个User的id参数,后台取得User数据后转发到新页面去编辑User信息,那个list页面应该是没有用了。 2.1这个代码就是测试用的,我试试看能不能获得id参数,还有就是不想去查数据库了,就自己构造了模拟的数据,用的时候肯定是判断list是否为空才查数据库的。有分页的时候,方法会调用两次 。不过判断为空的方法有个问题,就是列表中直接删除数据的时候(就是在列表中每行加个删除按钮),获得整个列表的方法会在删除方法之前进行,然后删除操作完成后数据就不再取得,页面中还会显示该记录实际上它已经删除了。我现在用的是加了一个更新变量,每次删除或者保存后就吧flag=true,取数据根据flag和list是否为空。但是这样也有问题,如果默认值为true的话,删除的时候还是先取得数据,删除,然后再取得所有数据,如果默认为false的话,在第一次打开页面的时候会不取数据。现在郁闷死了,不知道那些用jsf做工程的是怎么处理的。 2.2list放到savestate是不可能,数据太大,影响性能,如果只能用这种方式处理,还不如不用jsf。 感觉jsf的表格总是在自作聪明的想帮你做所有的事,像上面说的估计就是jsf在判断你点击了那一行,所以才要再次取得数据。你老老实实的做好你的局部刷新页面就好了(这是jsf唯一吸引我的地方),管那么多干什么啊,我点哪一行我自己知道,不需要你来告诉我。 1.可以肯定一点.JSF绝对不会执行你不需要的Bean(和他的方法),所以你最好好查下.从经验来看..你一定是哪用到了#{userList.users}这个变量,才会去调它的get方法. 2.list只放一页数据..你放全部的记录..迟早out of memory. 如果jsf唯一吸引你的地方是局部刷新..你大可以另寻它路了..JSP里面一样可以做到..刷新div而已.没什么fresh |
|
xiao0556
2008-05-20
你写的代码虽然不太合理但主要是jsf的机制造成的,在你提交的时候 它会再一次取你绑定的模型在你的程序里就是userList.users==》getUsers()方法。为什么会再取一次呢 它要看看这个模型有没有变化(我估计还有定位的关系 真正的原因没有仔细研究) 它判断的条件也很简单首先是个能让它认出来的列表,然后大小一致不 也就是说你两次给它的列表不一样 但是大小相同通过就OK。
|
|
xiao0556
2008-05-20
请问你的按钮放在哪儿了?
|
|
风之狐
2008-05-21
好吧,给你们最开始appfuse提供的例子,图片发不了,你们想看演示的话,到appfuse去看看吧,http://demo.appfuse.org/appfuse-jsf,登陆名用admin/admin,到系统管理-》查看用户菜单
重新取数就发生在你点击编辑按钮的时候,后台会再次把列表从数据库取一次,这让我感觉很不可接受,因为编辑的时候页面转发到新的页面UserEdit。jsf页面了,原有列表再取一次没有任何意义。 列表的样式就是 表格头 --------- 用户名| ..... |编辑按钮 | 删除按钮<我后来自己改动的把删除按钮直接放列表上面了,所以发现有上面的删除问题> ---------- 表格尾 import java.io.Serializable; import java.util.List; public class UserList extends BasePage implements Serializable { private static final long serialVersionUID = 972359310602744018L; public UserList() { setSortColumn("username"); } public List getUsers() { return sort(userManager.getUsers(null)); } } public class UserForm extends BasePage implements Serializable { private static final long serialVersionUID = -1141119853856863204L; private RoleManager roleManager; private String id; private User user = new User(); private Map<String, String> availableRoles; private String[] userRoles; public void setId(String id) { this.id = id; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } public void setRoleManager(RoleManager roleManager) { this.roleManager = roleManager; } public String add() { user = new User(); user.addRole(new Role(Constants.USER_ROLE)); return "editProfile"; } public String cancel() { if (log.isDebugEnabled()) { log.debug("Entering 'cancel' method"); } if (!"list".equals(getParameter("from"))) { return "mainMenu"; } else { return "cancel"; } } public String edit() { HttpServletRequest request = getRequest(); String idd=request.getParameter("id"); Map m=request.getParameterMap(); System.out.println(m.size()); System.out.println(idd); // if a user's id is passed in if (id != null) { // lookup the user using that id user = userManager.getUser(id); } else { user = userManager.getUserByUsername(request.getRemoteUser()); } if (user.getUsername() != null) { user.setConfirmPassword(user.getPassword()); if (isRememberMe()) { // if user logged in with remember me, display a warning that they can't change passwords log.debug("checking for remember me login..."); log.trace("User '" + user.getUsername() + "' logged in with cookie"); addMessage("userProfile.cookieLogin"); } } return "editProfile"; } /** * Convenience method for view templates to check if the user is logged in with RememberMe (cookies). * @return true/false - false if user interactively logged in. */ public boolean isRememberMe() { if (user != null && user.getId() == null) return false; // check for add() AuthenticationTrustResolver resolver = new AuthenticationTrustResolverImpl(); SecurityContext ctx = SecurityContextHolder.getContext(); if (ctx != null) { Authentication auth = ctx.getAuthentication(); return resolver.isRememberMe(auth); } return false; } public String save() throws IOException { // workaround for plain ol' HTML input tags that don't seem to set // properties on the managed bean setUserRoles(getRequest().getParameterValues("userForm:userRoles")); for (int i = 0; (userRoles != null) && (i < userRoles.length); i++) { String roleName = userRoles[i]; user.addRole(roleManager.getRole(roleName)); } Integer originalVersion = user.getVersion(); try { user = userManager.saveUser(user); } catch (AccessDeniedException ade) { // thrown by UserSecurityAdvice configured in aop:advisor userManagerSecurity log.warn(ade.getMessage()); getResponse().sendError(HttpServletResponse.SC_FORBIDDEN); return null; } catch (UserExistsException e) { addError("errors.existing.user", new Object[] { user.getUsername(), user.getEmail() }); // reset the version # to what was passed in user.setVersion(originalVersion); return "editProfile"; } if (!"list".equals(getParameter("from"))) { // add success messages addMessage("user.saved"); // return to main Menu return "mainMenu"; } else { // add success messages if ("".equals(getParameter("userForm:version"))) { addMessage("user.added", user.getFullName()); try { sendUserMessage(user, getText("newuser.email.message", user.getFullName()), RequestUtil.getAppURL(getRequest())); } catch (MailException me) { addError(me.getCause().getLocalizedMessage()); } return "list"; // return to list screen } else { addMessage("user.updated.byAdmin", user.getFullName()); return "editProfile"; // return to current page } } } public String delete() { userManager.removeUser(getUser().getId().toString()); addMessage("user.deleted", getUser().getFullName()); return "list"; } /** * Convenience method to determine if the user came from the list screen * @return String */ public String getFrom() { if ((id != null) || (getParameter("editUser:add") != null) || ("list".equals(getParameter("from")))) { return "list"; } return ""; } // Form Controls ========================================================== @SuppressWarnings("unchecked") public Map<String, String> getAvailableRoles() { if (availableRoles == null) { List roles = (List) getServletContext().getAttribute(Constants.AVAILABLE_ROLES); availableRoles = ConvertUtil.convertListToMap(roles); } return availableRoles; } public String[] getUserRoles() { userRoles = new String[user.getRoles().size()]; int i = 0; if (userRoles.length > 0) { for (Role role : user.getRoles()) { userRoles[i] = role.getName(); i++; } } return userRoles; } public void setUserRoles(String[] userRoles) { this.userRoles = userRoles; } public String getCountry() { return getUser().getAddress().getCountry(); } // for some reason, the country drop-down won't do // getUser().getAddress().setCountry(value) public void setCountry(String country) { getUser().getAddress().setCountry(country); } <html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="http://java.sun.com/jstl/core" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:t="http://myfaces.apache.org/tomahawk"> <f:view> <f:loadBundle var="text" basename="#{userList.bundleName}"/> <head> <title>#{text['userList.title']}</title> <meta name="heading" content="#{text['userList.heading']}"/> <meta name="menu" content="AdminMenu"/> </head> <h:form id="editUser"> <h:commandButton value="#{text['button.add']}" action="#{userForm.add}" id="add" styleClass="button"> <f:param name="from" value="list"/> </h:commandButton> <h:commandButton value="#{text['button.done']}" action="mainMenu" id="cancel" immediate="true" styleClass="button" style="margin-left: 5px"/> <!-- Error from this table is caused by http://issues.apache.org/jira/browse/TOMAHAWK-466 --> <t:dataTable id="users" var="user" style="margin-top: 10px" value="#{userList.users}" rows="25" sortColumn="#{userList.sortColumn}" sortAscending="#{userList.ascending}" styleClass="scrollerTable table" headerClass="standardTable_Header" rowClasses="standardTable_Row1,standardTable_Row2" columnClasses="standardTable_Column,standardTable_Column,standardTable_Column,standardTable_Column,standardTable_ColumnCentered"> <t:column width="25%"> <f:facet name="header"> <t:commandSortHeader columnName="username" arrow="true"> <h:outputText value="#{text['user.username']}" /> </t:commandSortHeader> </f:facet> <h:commandLink action="#{userForm.edit}" value="#{user.username}" > <f:param name="id" value="#{user.id}"/> </h:commandLink> </t:column> <t:column width="34%"> <f:facet name="header"> <t:commandSortHeader columnName="fullName" arrow="true"> <h:outputText value="#{text['activeUsers.fullName']}" /> </t:commandSortHeader> </f:facet> <h:outputText value="#{user.fullName}" /> </t:column> <t:column width="25%"> <f:facet name="header"> <t:commandSortHeader columnName="email" arrow="true"> <h:outputText value="#{text['user.email']}" /> </t:commandSortHeader> </f:facet> <h:outputLink value="mailto:#{user.email}"> <h:outputText value="#{user.email}" /> </h:outputLink> </t:column> <t:column width="16%"> <f:facet name="header"> <t:commandSortHeader columnName="enabled" arrow="true"> <h:outputText value="#{text['user.enabled']}" /> </t:commandSortHeader> </f:facet> <h:selectBooleanCheckbox value="#{user.enabled}" disabled="true"/> </t:column> </t:dataTable> <ui:include src="/common/tableFooter.xhtml"> <ui:param name="tableName" value="users"/> </ui:include> <script type="text/javascript"> highlightTableRows("editUser:users"); // doesn't currently work to allow clicking row </script> </h:form> </f:view> </html> 我觉得这已经够简单了,分页没有,当前页面刷新也没有,纯粹的页面转发,出这个情况只能使jsf框架的问题,不知道你门做的时候是没有这个问题还是没发现。 还有再说一次,我试这个就是想看看jsf在做工程的时候能否处理常见的事情,所以说什么分页,性能啊没什么意思,如果做一个列表数据还得来回捣腾的,其他都不再重要。所以我上面写的就是排除了分页或者数据库的影响,就是想看看jsf能否不多次取数据(分页那个不改动数据,判断是否为空可以解决),但是现在发现这个问题我解决不了,所以才看看大家是怎么解决的。 |
|
kimmking
2008-05-21
一次交互操作 取一次数据 (数据量不大)的情形是可以接受的。
不缓存数据 只有刷新数据。web是无状态的。 你用其他的web框架也是一样。 |
|
terryzhou
2008-05-21
哪儿能下那个war?
t:dataTable 还有两个tag preserveDataModel="true" preserveRowStates="true" |
|
风之狐
2008-05-21
kimmking 写道 一次交互操作 取一次数据 (数据量不大)的情形是可以接受的。
不缓存数据 只有刷新数据。web是无状态的。 你用其他的web框架也是一样。 我们目前用的底层框架是ssh,现在我想把他转到用seam,jsf。现在正在试验可行性,用ssh的话,分页,无刷我门都已经完善好了,已经实施了几个项目了,像我上面说的多次取数的问题,在我用过的其他任何非jsf框架都不会存在,只要你不是故意的。我上面的例子在实际实用中肯定不会有这么少的数据量,所以肯定是要分页,要是每次都刷新肯定不行。 你们试了自己的么,有没有我上次说的情况 |
|
terryzhou
2008-05-21
很明确的说。。没有这种情况。。
偶是t+rich+ajax4jsf |
|
风之狐
2008-05-21
搞不定啊,也许是行上面加按钮的事,但是这个是很常用的方式啊
|