[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
搞不定啊,也许是行上面加按钮的事,但是这个是很常用的方式啊
Global site tag (gtag.js) - Google Analytics