p:orderList 转换器 getAsObject() 不调用 Object.toString()
p:orderList converter getAsObject() doesn't call Object.toString()
我写了一个自定义转换器如下:
@FacesConverter(value = "orderListConverter")
public class OrderListConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
Object ret = null;
if (component instanceof OrderList) {
Object list = ((OrderList) component).getValue();
ArrayList<ExampleEntity> al = (ArrayList<ExampleEntity>) list;
for (Object o : al) {
String name = "" + ((ExampleEntity) o).getName();
if (value.equals(name)) {
ret = o;
break;
}
}
}
return ret;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value)
{
String str = "";
if (value instanceof ExampleEntity) {
str = "" + ((ExampleEntity) value).getNumber();
}
return str;
}
}
我的ExampleEntity实现如下:
public class ExampleEntity {
private String name;
private int number;
public ExampleEntity(String name, int number) {
this.name = name;
this.number = number;
}
@Override
public String toString() {
return "toString(): [name=" + name + ", number=" + number + "]";
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
Primefaces 的 orderList-Component 看起来像这样:
<p:orderList value="#{orderListBean.exampleList}"
var="exampleEntity" itemValue="#{exampleEntity}"
converter="orderListConverter">
<p:column style="width:25%">
#{exampleEntity.number}
</p:column>
<p:column style="width:75%;">
#{exampleEntity.name}
</p:column>
</p:orderList>
bean 实现如下:
@SessionScoped
@ManagedBean(name = "orderListBean")
public class OrderListBean {
private List<ExampleEntity> exampleList;
@PostConstruct
public void init() {
exampleList = new ArrayList<ExampleEntity>();
exampleList.add(new ExampleEntity("nameOne", 1));
exampleList.add(new ExampleEntity("nameTwo", 2));
exampleList.add(new ExampleEntity("nameThree", 3));
exampleList.add(new ExampleEntity("nameFour", 4));
exampleList.add(new ExampleEntity("nameFive", 5));
}
public List<ExampleEntity> getExampleList() {
return exampleList;
}
public void setExampleList(List<ExampleEntity> exampleList) {
this.exampleList = exampleList;
}
}
1)调试时,getAsObject()
的value
参数包含
ExampleEntity
的 number
,但我预料到了
toString()
方法 ExampleEntity
被调用!
2) itemValue
属性的正确内容是什么?
这是一种优于配置的约定吗?或者组件如何
'know',要使用整个对象,当将 exampleEntity
插入 itemValue
时
希望一切都清楚!非常感谢任何解释!
转换器主要用于在两个方向上转换值:
- 服务器到客户端,当值被呈现时。
- 客户端到服务器,提交值时。
在您的 getAsString
中,您建立了客户使用的字符串表示形式,即 exampleEntity
的号码。这就是作为价值呈现给客户的东西。稍后,当客户端提交其值时,该值是 number
。要将其转换为对象(服务器)表示,使用 number
作为参数调用 getAsObject
。
服务器不可能用 exampleEntity.toString()
调用 getAsObject
,因为此时它没有 exampleEntity
实例,只有提交的 number
.
为了说明,这应该成立:
obj.equals(conv.getAsObject(ctx, comp, conv.getAsString(ctx, comp, obj)));
getAsObject
和 getAsString
的输入和输出应该是可逆的。
回答你的第二个问题:这取决于你的需要。你可以说 itemValue="#{exampleEntity.number}"
,但只有当你对 exampleEntity
本身不感兴趣时,这才有意义,即在提交时你会从客户那里得到 number
,这就是你所需要的用于您的服务器端逻辑。
@FacesConverter(value = "EntityConverter")
public class EntityConverter implements Converter, Serializable {
private static final long serialVersionUID = 1L;
public EntityConverter() {
super();
}
@Override
public Object getAsObject(final FacesContext context, final UIComponent component, final String value) {
if (value == null) {
return null;
}
return fromSelect(component, value);
}
/**
* @param currentcomponent
* @param objectString
* @return the Object
*/
private Object fromSelect(final UIComponent currentcomponent, final String objectString) {
if (currentcomponent.getClass() == UISelectItem.class) {
final UISelectItem item = (UISelectItem) currentcomponent;
final Object value = item.getValue();
if (objectString.equals(serialize(value))) {
return value;
}
}
if (currentcomponent.getClass() == UISelectItems.class) {
final UISelectItems items = (UISelectItems) currentcomponent;
final List<Object> elements = (List<Object>) items.getValue();
for (final Object element : elements) {
if (objectString.equals(serialize(element))) {
return element;
}
}
}
if (!currentcomponent.getChildren().isEmpty()) {
for (final UIComponent component : currentcomponent.getChildren()) {
final Object result = fromSelect(component, objectString);
if (result != null) {
return result;
}
}
}
if (currentcomponent instanceof OrderList) {
Object items = ((OrderList) currentcomponent).getValue();
List<Object> elements = (List<Object>) items;
for (final Object element : elements) {
if (objectString.equals(serialize(element))) {
return element;
}
}
}
return null;
}
/**
* @param object
* @return the String
*/
private String serialize(final Object object) {
if (object == null) {
return null;
}
return object.getClass() + "@" + object.hashCode();
}
@Override
public String getAsString(final FacesContext arg0, final UIComponent arg1, final Object object) {
return serialize(object);
}
}
我写了一个自定义转换器如下:
@FacesConverter(value = "orderListConverter")
public class OrderListConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
Object ret = null;
if (component instanceof OrderList) {
Object list = ((OrderList) component).getValue();
ArrayList<ExampleEntity> al = (ArrayList<ExampleEntity>) list;
for (Object o : al) {
String name = "" + ((ExampleEntity) o).getName();
if (value.equals(name)) {
ret = o;
break;
}
}
}
return ret;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value)
{
String str = "";
if (value instanceof ExampleEntity) {
str = "" + ((ExampleEntity) value).getNumber();
}
return str;
}
}
我的ExampleEntity实现如下:
public class ExampleEntity {
private String name;
private int number;
public ExampleEntity(String name, int number) {
this.name = name;
this.number = number;
}
@Override
public String toString() {
return "toString(): [name=" + name + ", number=" + number + "]";
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
Primefaces 的 orderList-Component 看起来像这样:
<p:orderList value="#{orderListBean.exampleList}"
var="exampleEntity" itemValue="#{exampleEntity}"
converter="orderListConverter">
<p:column style="width:25%">
#{exampleEntity.number}
</p:column>
<p:column style="width:75%;">
#{exampleEntity.name}
</p:column>
</p:orderList>
bean 实现如下:
@SessionScoped
@ManagedBean(name = "orderListBean")
public class OrderListBean {
private List<ExampleEntity> exampleList;
@PostConstruct
public void init() {
exampleList = new ArrayList<ExampleEntity>();
exampleList.add(new ExampleEntity("nameOne", 1));
exampleList.add(new ExampleEntity("nameTwo", 2));
exampleList.add(new ExampleEntity("nameThree", 3));
exampleList.add(new ExampleEntity("nameFour", 4));
exampleList.add(new ExampleEntity("nameFive", 5));
}
public List<ExampleEntity> getExampleList() {
return exampleList;
}
public void setExampleList(List<ExampleEntity> exampleList) {
this.exampleList = exampleList;
}
}
1)调试时,getAsObject()
的value
参数包含
ExampleEntity
的 number
,但我预料到了
toString()
方法 ExampleEntity
被调用!
2) itemValue
属性的正确内容是什么?
这是一种优于配置的约定吗?或者组件如何
'know',要使用整个对象,当将 exampleEntity
插入 itemValue
希望一切都清楚!非常感谢任何解释!
转换器主要用于在两个方向上转换值:
- 服务器到客户端,当值被呈现时。
- 客户端到服务器,提交值时。
在您的 getAsString
中,您建立了客户使用的字符串表示形式,即 exampleEntity
的号码。这就是作为价值呈现给客户的东西。稍后,当客户端提交其值时,该值是 number
。要将其转换为对象(服务器)表示,使用 number
作为参数调用 getAsObject
。
服务器不可能用 exampleEntity.toString()
调用 getAsObject
,因为此时它没有 exampleEntity
实例,只有提交的 number
.
为了说明,这应该成立:
obj.equals(conv.getAsObject(ctx, comp, conv.getAsString(ctx, comp, obj)));
getAsObject
和 getAsString
的输入和输出应该是可逆的。
回答你的第二个问题:这取决于你的需要。你可以说 itemValue="#{exampleEntity.number}"
,但只有当你对 exampleEntity
本身不感兴趣时,这才有意义,即在提交时你会从客户那里得到 number
,这就是你所需要的用于您的服务器端逻辑。
@FacesConverter(value = "EntityConverter")
public class EntityConverter implements Converter, Serializable {
private static final long serialVersionUID = 1L;
public EntityConverter() {
super();
}
@Override
public Object getAsObject(final FacesContext context, final UIComponent component, final String value) {
if (value == null) {
return null;
}
return fromSelect(component, value);
}
/**
* @param currentcomponent
* @param objectString
* @return the Object
*/
private Object fromSelect(final UIComponent currentcomponent, final String objectString) {
if (currentcomponent.getClass() == UISelectItem.class) {
final UISelectItem item = (UISelectItem) currentcomponent;
final Object value = item.getValue();
if (objectString.equals(serialize(value))) {
return value;
}
}
if (currentcomponent.getClass() == UISelectItems.class) {
final UISelectItems items = (UISelectItems) currentcomponent;
final List<Object> elements = (List<Object>) items.getValue();
for (final Object element : elements) {
if (objectString.equals(serialize(element))) {
return element;
}
}
}
if (!currentcomponent.getChildren().isEmpty()) {
for (final UIComponent component : currentcomponent.getChildren()) {
final Object result = fromSelect(component, objectString);
if (result != null) {
return result;
}
}
}
if (currentcomponent instanceof OrderList) {
Object items = ((OrderList) currentcomponent).getValue();
List<Object> elements = (List<Object>) items;
for (final Object element : elements) {
if (objectString.equals(serialize(element))) {
return element;
}
}
}
return null;
}
/**
* @param object
* @return the String
*/
private String serialize(final Object object) {
if (object == null) {
return null;
}
return object.getClass() + "@" + object.hashCode();
}
@Override
public String getAsString(final FacesContext arg0, final UIComponent arg1, final Object object) {
return serialize(object);
}
}