自訂轉換器


除了使用標準的轉換器之外,您還可以自行定製您的轉換器,您可以實作 javax.faces.convert.Converter介面,這個介面有兩個要實作的方法:
 public Object getAsObject(FacesContext context,
                           UIComponent component,
                           String str);
 public String getAsString(FacesContext context,
                           UIComponent component,
                           Object obj);
 
簡單的說,第一個方法會接收從客戶端經由HTTP傳來的字串資料,您在第一個方法中將之轉換為您的自訂物件,這個自訂物件將會自動設定給您指定的Bean 物件;第二個方法就是將從您的Bean物件得到的物件轉換為字串,如此才能藉由HTTP傳回給客戶端。

直接以一個簡單的例子來作說明,假設您有一個User類別:
  • User.java
package onlyfun.caterpillar;

public class User {
private String firstName;
private String lastName;

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}
}

這個User類別是我們轉換器的目標物件,而您有一個GuestBean類別:
  • GuestBook.java
package onlyfun.caterpillar;

public class GuestBean {
private User user;

public void setUser(User user) {
this.user = user;
}

public User getUser() {
return user;
}
}

這個Bean上的屬性直接傳回或接受User型態的參數,我們來實作一個簡單的轉換器,為HTTP字串與User物件進行轉換:
  • UserConverter.java
package onlyfun.caterpillar;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;

public class UserConverter implements Converter {
public Object getAsObject(FacesContext context,
UIComponent component,
String str)
throws ConverterException {
String[] strs = str.split(",");

User user = new User();

try {
user.setFirstName(strs[0]);
user.setLastName(strs[1]);
}
catch(Exception e) {
// 轉換錯誤,簡單的丟出例外
throw new ConverterException();
}

return user;
}

public String getAsString(FacesContext context,
UIComponent component,
Object obj)
throws ConverterException {
String firstName = ((User) obj).getFirstName();
String lastName = ((User) obj).getLastName();

return firstName + "," + lastName;
}
}

實作完成這個轉換器,我們要告訴JSF這件事,這是在faces-config.xml中完成註冊:
  • faces-config.xml
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

<faces-config>
<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>show</from-outcome>
<to-view-id>/pages/index.jsp</to-view-id>
</navigation-case>
</navigation-rule>

<converter>
<converter-id>onlyfun.caterpillar.User</converter-id>
<converter-class>
onlyfun.caterpillar.UserConverter
</converter-class>
</converter>

<managed-bean>
<managed-bean-name>guest</managed-bean-name>
<managed-bean-class>
onlyfun.caterpillar.GuestBean
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>

註冊轉換器時,需提供轉換器識別(Converter ID)與轉換器類別,接下來要在JSF頁面中使用轉換器的話,就是指定所要使用的轉換器識別,例如:
  • index.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;charset=Big5"%>

<f:view>

<html>
<head>
<title>自訂轉換器</title>
</head>
<body>

Guest名稱是:<b>
<h:outputText value="#{guest.user}"
converter="onlyfun.caterpillar.User"/>
</b>

<h:form>
<h:inputText id="userField"
value="#{guest.user}"
converter="onlyfun.caterpillar.User"/>
<h:message for="userField" style="color:red"/>
<br>
<h:commandButton value="送出" action="show"/>
</h:form>
</body>
</html>

</f:view>

您也可以<f:converter>標籤並使用converterId屬性來指定轉換器,例如:
 <h:inputText id="userField" value="#{guest.user}">
     <f:converter converterId="onlyfun.caterpillar.User"/>
 </h:inputText>     
 
除了向JSF註冊轉換器之外,還有一個方式可以不用註冊,就是直接在Bean上提供一個取得轉換器的方法,例如:
  • GuestBean.java
package onlyfun.caterpillar;

import javax.faces.convert.Converter;

public class GuestBean {
private User user;
private Converter converter = new UserConverter();

public void setUser(User user) {
this.user = user;
}

public User getUser() {
return user;
}

public Converter getConverter() {
return converter;
}
}

之後可以直接結合 JSF Expression Language 來指定轉換器:
 <h:inputText id="userField"
     value="#{guest.user}"
     converter="#{guest.converter}"/>