有没有办法让JSF与Generic setter和getter一起使用 [英] Is there a way to get JSF to work with Generic setters and getters
问题描述
有没有办法让JSF与通用实体一起使用,如下所述:
Is there a way to get JSF to work with generic entities as described below:
Property.java
public interface MyProperty<T> {
void setMyValue(T value);
T getMyValue(T value);
}
在我的申请中 T
可以日期
,字符串
,整数
或长
仅
In my application T
could Date
, String
, Integer
or Long
only
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
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head><title></title></h:head><h:body>
<h:form>
<ui:repeat var="property" value="#{controller.myObject.properties}">
<h:inputText value="#{property.myValue}"/>
</ui:repeat>
<h:commandButton action="#{controller.save}" value="save"/>
</h:form>
</h:body>
</html>
不幸的是,这不起作用,因为JSF试图在myObject上找到带有签名的setter:
Unfortunately this doesn't work as JSF tries to find a setter on myObject with the signature:
void setMyValue(String value);
由于类型擦除导致该方法具有以下签名,因此显然不存在:
Which obviously doesn't exist since type erasure results in the method having the following signature:
void setMyValue(Object value);
有没有办法绕过这个?
推荐答案
您的答案不清楚,但答案肯定是是,JSF可以附带仿制药。
Your answer is unclear, but, the answer is definitely YES, JSF can be accompanied with generics.
但是,这取决于你使用泛型的明智的方式,最终取决于你是否真的理解泛型。
Though, it depends on how wise you are using generics and, ultimately, on the question whether you do understand generics at all.
据我所知,您将使用通用接口作为包装器到实现类中包含的对象。
As far as I can tell from your example, you are going to use generic interface as a wrapper to the object contained in the implemented class.
使用这种方法你不直接处理 MyInterface
实现,而不是其内容,由接口方法定义。
With this approach you do not directly deal with MyInterface
implementations, but rather with its contents, as defined by the interface methods.
基本接口:
public interface MyInterface<T> {
void setMyValue(T value);
T getMyValue();
}
实施班级:
public class MyString implements MyInterface<String> {
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<Integer> {
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<Float> myFloat;
public MyInterfaceBean() {
myString = new MyString("String");
myInteger = new MyInteger(1);
myFloat = new MyInterface<Float>() {
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;
}
}
视图:
<h:outputText value="String: #{myInterfaceBean.myString}"/>
<br/>
<h:outputText value="Integer: #{myInterfaceBean.myInteger}"/>
<br/>
<h:outputText value="Float: #{myInterfaceBean.myFloat}"/>
<br/>
<h:form>
<h:outputText value="String: "/><h:inputText value="#{myInterfaceBean.myString}"/>
<br/>
<h:outputText value="Integer: "/><h:inputText value="#{myInterfaceBean.myInteger}"/>
<br/>
<h:outputText value="Float: "/><h:inputText value="#{myInterfaceBean.myFloat}"/>
<br/>
<h:commandButton value="Submit" action="#{myInterfaceBean.action}"/>
</h:form>
使用 @FacesConverter 的类
另一种方法是使用 @FacesConverter
,以便JSF知道如何将输入字段中的字符串转换为实现 MyInterface的对象
。
Use classes with @FacesConverter
Another approach is to use a @FacesConverter
so that JSF would know how to convert strings in input fields to objects that implement MyInterface
.
托管bean(匿名类):
@ManagedBean
@RequestScoped
public class MyInterfaceBean {
private MyString myString;
private MyInteger myInteger;
private MyInterface<Float> myFloat;
public MyInterfaceBean() {
myString = new MyString("String");
myInteger = new MyInteger(1);
myFloat = new MyInterface<Float>() {
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<Float> getMyFloat() {
return myFloat;
}
public void setMyFloat(MyInterface<Float> 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<Float> obj = null;
try {
Float floatValue = Float.valueOf(value);
obj = new MyInterface<Float>() {
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();
}
}
视图:
<h:outputText value="String: #{myInterfaceBean.myString}"/>
<br/>
<h:outputText value="Integer: #{myInterfaceBean.myInteger}"/>
<br/>
<h:outputText value="Float: #{myInterfaceBean.myFloat}"/>
<br/>
<h:form>
<h:outputText value="String: "/><h:inputText value="#{myInterfaceBean.myString}" converter="myStringConverter"/>
<br/>
<h:outputText value="Integer: "/><h:inputText value="#{myInterfaceBean.myInteger}" converter="myIntegerConverter"/>
<br/>
<h:outputText value="Float: "/><h:inputText value="#{myInterfaceBean.myFloat}" converter="myFloatConverter"/>
<br/>
<h:commandButton value="Submit" action="#{myInterfaceBean.action}"/>
</h:form>
这篇关于有没有办法让JSF与Generic setter和getter一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!