有没有办法让JSF与Generic setter和getter一起使用

有没有办法让JSF与generics实体一起工作,如下所述:

Property.java

public interface MyProperty { void setMyValue(T value); T getMyValue(T value); } 

在我的应用程序中, T只能是DateStringIntegerLong

MyObject.java

  public class MyObject { List<MyProperty> properties; public List<MyProperty> getProperties() { return properties; } } 

MyController.java

 @Named("controller") @RequestScoped public class MyController { MyObject myObject; public void setMyObject(MyObject myObject) { this.myObject = myObject; }; public MyObject getMyObject() { return myObject; } ; } 

edit.xhtml

           

不幸的是,这不起作用,因为JSF尝试使用签名在myObject上找到一个setter:

 void setMyValue(String value); 

这显然不存在,因为类型擦除导致该方法具有以下签名:

 void setMyValue(Object value); 

有没有办法绕过这个?

你的答案不清楚,但答案肯定是肯定的,JSF可以附带generics。

但是,这取决于你使用generics的方式,以及最终是否完全理解generics的问题。

据我所知,您将使用通用接口作为实现类中包含的对象的包装器

使用包含getter / setter的类

使用这种方法,您不直接处理MyInterface实现,而是直接处理接口方法定义的内容。

基础界面:

 public interface MyInterface { void setMyValue(T value); T getMyValue(); } 

实施class级:

 public class MyString implements MyInterface { private String myValue; public MyString(String myValue) { this.myValue = myValue; } public void setMyValue(String value) { this.myValue = value; } public String getMyValue() { return myValue; } @Override public String toString() { return myValue; } } 

 public class MyInteger implements MyInterface { private Integer myValue; public MyInteger(Integer myValue) { this.myValue = myValue; } public void setMyValue(Integer value) { this.myValue = value; } public Integer getMyValue() { return myValue; } @Override public String toString() { return Integer.toString(myValue); } } 

托管bean(带匿名类 ):

 @ManagedBean @RequestScoped public class MyInterfaceBean { private MyString myString; private MyInteger myInteger; private MyInterface myFloat; public MyInterfaceBean() { myString = new MyString("String"); myInteger = new MyInteger(1); myFloat = new MyInterface() { private Float myValue; public void setMyValue(Float value) { this.myValue = value; } public Float getMyValue() { return myValue; } @Override public String toString() { return Float.toString(myValue); } }; myFloat.setMyValue(3.1f); } public String getMyString() { return myString.getMyValue(); } public void setMyString(String myString) { this.myString.setMyValue(myString); } public Integer getMyInteger() { return myInteger.getMyValue(); } public void setMyInteger(Integer myInteger) { this.myInteger.setMyValue(myInteger); } public Float getMyFloat() { return myFloat.getMyValue(); } public void setMyFloat(Float myFloat) { this.myFloat.setMyValue(myFloat); } public String action() { return null; } } 

风景:

  





使用@FacesConverter的

另一种方法是使用@FacesConverter以便JSF知道如何将输入字段中的字符串转换为实现MyInterface对象。

托管bean(带匿名类 ):

 @ManagedBean @RequestScoped public class MyInterfaceBean { private MyString myString; private MyInteger myInteger; private MyInterface myFloat; public MyInterfaceBean() { myString = new MyString("String"); myInteger = new MyInteger(1); myFloat = new MyInterface() { private Float myValue; public void setMyValue(Float value) { this.myValue = value; } public Float getMyValue() { return myValue; } @Override public String toString() { return Float.toString(myValue); } }; myFloat.setMyValue(3.1f); } public MyString getMyString() { return myString; } public void setMyString(MyString myString) { this.myString = myString; } public MyInteger getMyInteger() { return myInteger; } public void setMyInteger(MyInteger myInteger) { this.myInteger = myInteger; } public MyInterface getMyFloat() { return myFloat; } public void setMyFloat(MyInterface myFloat) { this.myFloat.setMyValue(myFloat.getMyValue());//not to lose this anonymous class, can substitute for other implementation directly } public String action() { return null; } } 

转换器:

 @FacesConverter(value = "myStringConverter") public class MyStringConverter implements Converter { public Object getAsObject(FacesContext context, UIComponent component, String value) { if(value == null || value.equals("")) { return null; } MyString obj = new MyString(value); return obj; } public String getAsString(FacesContext context, UIComponent component, Object value) { if (!(value instanceof MyString) || (value == null)) { return null; } return ((MyString)value).getMyValue(); } } 

 @FacesConverter(value = "myIntegerConverter") public class MyIntegerConverter implements Converter { public Object getAsObject(FacesContext context, UIComponent component, String value) { if(value == null || value.equals("")) { return null; } MyInteger obj = null; try { Integer integer = Integer.valueOf(value); obj = new MyInteger(integer); } catch(NumberFormatException nfe) { throw new ConverterException(new FacesMessage("Integer could not be parsed from string: " + value)); } return obj; } public String getAsString(FacesContext context, UIComponent component, Object value) { if (!(value instanceof MyInteger) || (value == null)) { return null; } return ((MyInteger)value).getMyValue().toString(); } } 

 @FacesConverter(value = "myFloatConverter") public class MyFloatConverter implements Converter { public Object getAsObject(FacesContext context, UIComponent component, String value) { if(value == null || value.equals("")) { return null; } MyInterface obj = null; try { Float floatValue = Float.valueOf(value); obj = new MyInterface() { private Float myValue; public void setMyValue(Float value) { this.myValue = value; } public Float getMyValue() { return myValue; } @Override public String toString() { return Float.toString(myValue); } }; obj.setMyValue(floatValue); } catch(NumberFormatException nfe) { throw new ConverterException(new FacesMessage("Float could not be parsed from string: " + value)); } return obj; } public String getAsString(FacesContext context, UIComponent component, Object value) { if (!(value instanceof MyInterface) || (value == null)) { if(!(((MyInterface)value).getMyValue() instanceof Float)) { return null; } } return ((MyInterface)value).getMyValue().toString(); } } 

风景: