有没有办法让JSF与Generic setter和getter一起使用
有没有办法让JSF与generics实体一起工作,如下所述:
Property.java
public interface MyProperty { void setMyValue(T value); T getMyValue(T value); }
在我的应用程序中, T
只能是Date
, String
, Integer
或Long
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(); } }
风景: