0

我正在使用 Spring 来填充表单中的项目,使用控制器和视图之间传递的对象:

领域对象

public class Client {
private String name;
private int id;
private Bar bar;
// getters and setters omitted
}


public class Bar {
private Integer id;
private String name;
// getters and setters omitted

}

控制器

@RequestMapping(method = RequestMethod.GET, value = "/")
public String index(Model m) {
m.addAttribute("Client", new Client());
Bar o1 = new Bar();
o1.setName("n 1");
o1.setId(1);
Bar o2 = new Bar();
o2.setName("n 2");
o2.setId(2);
Bar o3 = new Bar();
o3.setName("n 3");
o3.setId(3);
Bar o4 = new Bar();
o4.setName("n 4");
o4.setId(4);
Bar o5 = new Bar();
o5.setName("n 5");
o5.setId(5);
List<Bar> orders = new ArrayList<Bar>();
orders.add(o1);
orders.add(o2);
orders.add(o3);
orders.add(o4);
orders.add(o5);
m.addAttribute("ordersList", orders);
return "index";
}

@RequestMapping(method = RequestMethod.POST, value = "/")
public String indexPost(@ModelAttribute("Client") Client g, BindingResult r) {
log.info(g.getId() + " " + g.getName());
log.info(g.getBar().getName());
return "index";
}

查看 (index.jsp)

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<form:form method="POST" modelAttribute="Client">
<form:label path="name">Name</form:label>
<form:input path="name" />
<form:label path="id">Id</form:label>
<form:input path="id" />
<form:label path="orders">Order</form:label>
<form:select path="bar" items="${ordersList}" />    
<form:button>Insert</form:button>
</form:form>
</body>
</html>

问题

当我填写表格并提交时,控制器抛出 NullPointerExceptionlog.info(g.getBar().getName()); 我认为这是因为 getBar() 返回null。这个数据绑定我哪里错了?

4

3 回答 3

1

您正在Client为模型设置一个新对象,但该对象是空的。首先尝试创建完整的Client对象,然后在index()方法中将其设置为模型。

编辑: 因此您需要该字段的属性编辑器。调整以下方法并将其添加到您的控制器:

@InitBinder
protected void initBinder(WebDataBinder binder) {

    binder.registerCustomEditor(Bar.class, "bar", new PropertyEditorSupport(Bar.class) {
        @Override
        public String getAsText() {
            if(null != getValue()) {
                return ((Bar) getValue()).getId();
            } else {
                return StringUtils.EMPTY;
            }
        }
        @Override
        public void setAsText(String text) {
            if(!StringUtils.isEmpty(text)) {
                setValue(UtilityClassUtils.getBarById(text));
            }
        }
    });
}
于 2013-01-02T20:24:09.957 回答
0

我认为form:select标签没有正确定义。你能试试这个吗?

 <form:select path="bar"> 
  <form:options items="${ordersList}" itemValue="id" itemLabel="name" />
 </form:select>
于 2013-01-02T20:39:18.323 回答
0

首先,您的表单只会将所选酒吧的 ID 发布回您的服务器端。因此,如果没有额外的工作,Spring 将无法自动填充 Bar 的名称字段。

其次,为了帮助 Spring 将 ID 转换为 Bar 或 Bar 转换为 ID,您需要将 Bar 对象存储在某个地方。您可以将 Bar 保存在缓存、会话、数据库或 HTML Form 的隐藏输入等中。假设我们将 Bar 存储在服务器端,存储的接口定义如下:

package com.example;

public interface BarStore {

    Bar getBar(Integer id);

    void putBar(Bar bar);

}

并将您的 Bar 对象存储在您的公共字符串索引(模型 m)方法中,如下所示:

...
@Autowired
private BarStore barStore;
...
@RequestMapping(method = RequestMethod.GET, value = "/")
public String index(Model m) {
    ...
    barStore.putBar(o1);
    barStore.putBar(o2);
    barStore.putBar(o3);
    barStore.putBar(o4);
    barStore.putBar(o5);
    ...
}

最后,您可以注册一些转换器来将 Bar 转换为 ID 并将 ID 转换为 Bar。这是一个例子:

package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.support.FormattingConversionServiceFactoryBean;

@Configurable
public class ApplicationConversionServiceFactoryBean extends FormattingConversionServiceFactoryBean {

    @Autowired
    private BarStore barStore;

    public Converter<Bar, String> getBarToStringConverter() {
        return new Converter<Bar, String>() {
            public String convert(Bar bar) {
                return new StringBuilder().append(bar.getId()).append(' ').append(bar.getName()).toString();
            }
        };
    }

    public Converter<Integer, Bar> getIdToBarConverter() {
        return new Converter<Integer, Bar>() {
            public Bar convert(Integer id) {
                return barStore.getBar(id);
            }
        };
    }

    public Converter<String, Bar> getStringToBarConverter() {
        return new Converter<String, Bar>() {
            public Bar convert(String id) {
                return getObject().convert(getObject().convert(id, Integer.class), Bar.class);
            }
        };
    }

    public void installLabelConverters(FormatterRegistry registry) {
        registry.addConverter(getBarToStringConverter());
        registry.addConverter(getIdToBarConverter());
        registry.addConverter(getStringToBarConverter());
    }

    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        installLabelConverters(getObject());
    }

}
于 2013-01-03T06:43:10.680 回答