有没有办法让JSF与Generic setter和getter一起使用 [英] Is there a way to get JSF to work with Generic setters and getters

查看:161
本文介绍了有没有办法让JSF与Generic setter和getter一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法让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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆