之前使用的查詢數據列表一直是datatable,Back bean裏面的屬性用的是ListDataModel類型。被上面的commandLink鏈接無效困擾了許久。最終找到解決方法了:使用HtmlDataTable替代ListDataModel,頁面使用binding屬性綁定該HtmlDataTable.關於HtmlDataTable 和ListDataModel的特點及差別,由於本人時間有限尚未做深究。 現將本人看到的原文轉載如下:
聲明:以下文字是本人轉載於http://www.gzsec.com/bbs/dispbbs.asp?boardID=6&ID=629&page=1 若侵犯了你的權益,請與本人聯繫。
1. 環境
Myfaces1.4 + tomahawk-1.1.3 + tomcat5.x + JDK5
下載:http://myfaces.apache.org
2. 問題描述
假設場景,首先顯示用戶列表(用dataTable來實現列表顯示),然後可以點擊用戶的名字導航到用戶詳細信息頁面。
3. 嘗試實現以及出現的問題
UserInfo.java
package com.wide.jsf.model;
/** * 用戶信息 * * @author cydooo * */ public class UserInfo { private Long userId; private String username; private String userdesc; public UserInfo() { } public UserInfo(Long userId, String username) { this.userId = userId; this.username = username; } public UserInfo(Long userId, String username, String userdesc) { this(userId, username); this.userdesc = userdesc; } //省略getter和setter } |
UserInfoAction.java
package com.wide.jsf.web;
import java.util.Arrays; import java.util.List;
import javax.faces.context.FacesContext;
import com.wide.jsf.model.UserInfo;
public class UserInfoAction {
/* * 用於顯示詳細信息 */ private UserInfo userInfo;
/* * 用於顯示用戶列表 */ private List<UserInfo> userInfos;
public UserInfo getUserInfo() { return userInfo; }
public void setUserInfo(UserInfo userInfo) { this.userInfo = userInfo; }
public List<UserInfo> getUserInfos() { return userInfos; }
public void setUserInfos(List<UserInfo> userInfos) { this.userInfos = userInfos; }
public String listUser() { userInfos = Arrays.asList(new UserInfo[] { new UserInfo(1L, "Tom"),new UserInfo(2L, "John"), new UserInfo(3L, "Lily") }); return "listUser"; }
public String showDetail() { FacesContext context = FacesContext.getCurrentInstance(); Long userId = Long.parseLong((String) context.getExternalContext() .getRequestParameterMap().get("userId")); System.out.println("==>" + userId); switch (userId.intValue()) { case 1: userInfo = new UserInfo(1L, "Tom", "I am Tom"); break; case 2: userInfo = new UserInfo(2L, "John", "I am John"); break; case 3: userInfo = new UserInfo(3L, "Lily", "I am Lily"); } return "userdetail"; } } |
Backingbean和navigation的配置
<managed-bean> <managed-bean-name>userInfoAction</managed-bean-name> <managed-bean-class> com.wide.jsf.web.UserInfoAction </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <navigation-rule> <from-view-id>/listUser.jsp</from-view-id> <navigation-case> <from-outcome>userdetail</from-outcome> <to-view-id>/userdetail.jsp</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <from-view-id>/userdetail.jsp</from-view-id> </navigation-rule> |
Jsp頁面內容
A. listUser.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> <%@ page contentType="text/html; UTF-8" pageEncoding="UTF-8"%>
<f:view> <html> <head> <title>userlist</title> </head>
<body> <h:form> <h:dataTable var="user" value="#{userInfoAction.userInfos}"> <h:column> <h:commandLink value="#{user.username}" action="#{userInfoAction.showDetail}"> <f:param value="#{user.userId}" name="userId"/> </h:commandLink> </h:column> </h:dataTable> </h:form> </body> </html> </f:view> |
B. userdetail.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> <%@ page contentType="text/html; UTF-8" pageEncoding="UTF-8"%>
<f:view> <html> <head> <title>userDetail</title> </head>
<body> <h:form> <h:outputText value="#{userInfoAction.userInfo.userdesc}"/> </h:form> </body> </html> </f:view> |
編碼結束,啓動tomcat測試,進入userlist頁面之後,我們可以看到用戶列表,但點擊用戶查看詳細信息的時候,發現並沒有調用showDetail方法。
4. 解決辦法
A. 將<managed-bean-scope>request</managed-bean-scope>改爲<managed-bean-scope>session</managed-bean-scope>。這是最簡單的做法,改了之後重起Tomcat之後馬上就看到效果了。但是很明顯的使用session scope不好,比如這個例子,用戶列表在當前seesion有效的情況下將一直保留,多窗口瀏覽器中也容易發生意想不到的問題。沒有必要不要用session。
B. 將用戶列表綁定到dataTable控件。
首先修改UserInfo類,讓他實現Serializable接口,其他代碼完全一樣,實現Serializable接口是必須的,否則會拋出java.io.NotSerializableException異常。
public class UserInfo implements Serializable{…} |
UserInfoAction.java的修改
package com.wide.jsf.web;
import java.util.Arrays; import java.util.List;
import javax.faces.component.html.HtmlDataTable; import javax.faces.context.FacesContext;
import com.wide.jsf.model.UserInfo;
public class UserInfoAction {
/* * 用於顯示詳細信息 */ private UserInfo userInfo;
/* * 綁定用戶列表 */ private HtmlDataTable dataTable = new HtmlDataTable();
public UserInfo getUserInfo() { return userInfo; }
public void setUserInfo(UserInfo userInfo) { this.userInfo = userInfo; }
public String listUser() { List<UserInfo> userInfos = Arrays.asList(new UserInfo[] { new UserInfo(1L, "Tom"), new UserInfo(2L, "John"), new UserInfo(3L, "Lily") }); dataTable.setValue(userInfos); return "listUser"; }
public String showDetail() { FacesContext context = FacesContext.getCurrentInstance(); Long userId = Long.parseLong((String) context.getExternalContext() .getRequestParameterMap().get("userId")); System.out.println("==>" + userId); switch (userId.intValue()) { case 1: userInfo = new UserInfo(1L, "Tom", "I am Tom"); break; case 2: userInfo = new UserInfo(2L, "John", "I am John"); break; case 3: userInfo = new UserInfo(3L, "Lily", "I am Lily"); } return "userdetail"; }
public HtmlDataTable getDataTable() { return dataTable; }
public void setDataTable(HtmlDataTable dataTable) { this.dataTable = dataTable; } } |
listUser.jsp的修改
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> <%@ page contentType="text/html; UTF-8" pageEncoding="UTF-8"%>
<f:view> <html> <head> <title>userlist</title> </head>
<body> <h:form> <h:dataTable var="user" binding="#{userInfoAction.dataTable}"> <h:column> <h:commandLink value="#{user.username}" action="#{userInfoAction.showDetail}"> <f:param value="#{user.userId}" name="userId"/> </h:commandLink> </h:column> </h:dataTable> </h:form> </body> </html> </f:view> |
重起Tomcat一切OK,不需要非得在session scope下了。