SpringMVC Checkbox: Custom Binding / PropertyEdito

2019-09-07 02:14发布

问题:

It's something really simple but I couldn't find a good example:

I have a custom data type that I'd like to bind to a SpringMVC checkbox, it looks like this: YES/NO:

public enum YesNoDataType {
   YES("Yes"), 
   NO("No");
}

SpringMVC checkboxes auto-map to Booleans, now I need to map Selected->YES, Empty->NO.

I know I have to implement one of these 4 PropertyEditorSupport methods, but which ones, and how?

<form:checkbox path="testYesNo"></form:checkbox>

Model

private YesNoDataType testYesNo; 

Controller

binder.registerCustomEditor(YesNoDataType.class, new PropertyEditorSupport() {

          // Which ones to override?

            @Override
            public void setValue(Object value) {
                // TODO Auto-generated method stub
                super.setValue(value);
            }

            @Override
            public Object getValue() {
                // TODO Auto-generated method stub
                return super.getValue();
            }

            @Override
            public String getAsText() {
                // TODO Auto-generated method stub
                return super.getAsText();
            }

            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                // TODO Auto-generated method stub
                super.setAsText(text);
            }

});

回答1:

I tried defining and registering some Converters (YesNoDataType / Boolean), but I see in SpringMVC's CheckboxTag.java that they're all useless. No converters or binding tweaks will work because the tag explicitly checks for Booleans and Strings only:

protected void writeTagDetails(TagWriter tagWriter) throws JspException {
    tagWriter.writeAttribute("type", getInputType());

    Object boundValue = getBoundValue();
    Class<?> valueType = getBindStatus().getValueType();

    if (Boolean.class.equals(valueType) || boolean.class.equals(valueType)) {
        // the concrete type may not be a Boolean - can be String
        if (boundValue instanceof String) {
            boundValue = Boolean.valueOf((String) boundValue);
        }
        Boolean booleanValue = (boundValue != null ? (Boolean) boundValue : Boolean.FALSE);
        renderFromBoolean(booleanValue, tagWriter);
    }

    else {
        Object value = getValue();
        if (value == null) {
            throw new IllegalArgumentException("Attribute 'value' is required when binding to non-boolean values");
        }
        Object resolvedValue = (value instanceof String ? evaluate("value", value) : value);
        renderFromValue(resolvedValue, tagWriter);
    }
}

The String binding is irrelevant to me. In the getValue() String binding (Clause #2), a checkbox is selected if its value="" attribute matches the string in the model. What I need is a True/False boolean binding, but my Converter needs to be plugged into Clause #1 to obtain a Boolean from a custom type. Just very frustrated that Spring is so restrictive as soon as you try to go outside the narrow parameters of what's common. The issue is still outstanding.