从String转换为Spring MVC表单的自定义对象数据绑定?

Jam*_*hon 22 forms data-binding spring persistence spring-mvc

我使用Spring MVC的SimpleFormController与Spring MVC的表单JTL一起创建一个表单来编辑Generic对象.

在我的表单上,我有一个下拉列表,用户可以通过下拉列表指定服务器.

<form:form commandName="generic">
    <form:select path="server">
        <form:options items="${servers}" itemValue="id" itemLabel="name"/>
    </form:select>
</form:form>
Run Code Online (Sandbox Code Playgroud)

这里的服务器通过数据库调用传播所有可用的服务器.server是Server ORM pojo,它是另一个ORM pojo(Generic)的子对象,用作我的表单后备对象.

我的目标是更改Generic的服务器引用,该引用在数据库级别表示为服务器表的外键.

我使用JPA作为我的持久层,JPA生成的实体类作为我的ORM pojos.

不幸的是,当我的表单提交时,这似乎没有正确绑定,因为它无法从String转换为Server.

Field error in object 'generic' on field 'server': rejected value [1]; codes [typeMismatch.generic.server,typeMismatch.server,typeMismatch.com.generic.orm.jpa.Server,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [generic.server,server]; arguments []; default message [server]]; default message [Failed to convert property value of type [java.lang.String] to required type [com.generic.orm.jpa.Server] for property 'server'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [com.generic.orm.jpa.Server] for property 'server': no matching editors or conversion strategy found], generic=com.generic.orm.jpa.generic[id=3]} and static attributes {}
Run Code Online (Sandbox Code Playgroud)

我一直在寻找一个如何在没有运气的情况下实现这一目标的例子.我相信我需要在SimpleFormController中覆盖一些东西,就像我在这个问题中所做的那样,但Spring MVC的文档很清楚细节.有人可以帮我从这里出去吗?

Jam*_*hon 21

作为Mark答案的补充,这就是我最终在我的控制器中做的事情.

@Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
    binder.registerCustomEditor(Server.class, "serverId", new PropertyEditorSupport() {
        @Override
        public void setAsText(String text) {
            Server type = (Server) em.createNamedQuery("Server.findById")
                .setParameter("id", Short.parseShort(text)).getSingleResult();
            setValue(type);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

您也可以使用Spring注入,而不是匿名类.这由Mark的回答中的链接概述.

您也可以扩展ClassEditor(见下文)而不是PropertyEditorSupport.贾瓦多克说;

java.lang.Class的属性编辑器,用于启用Class属性的直接填充,而无需使用String类名属性作为桥.

不知道我是否完全理解这一点的好处,但要记住一些事情.

有用的Javadocs


Fır*_*ÇÜK 18

使用"server.id"可能是一种可能的解决方案.因此spring会自动绑定选定的值,反之亦然.

<form:form commandName="generic">
    <form:select path="server.id">
        <form:options items="${servers}" itemValue="id" itemLabel="name"/>
    </form:select>
</form:form>
Run Code Online (Sandbox Code Playgroud)


Mar*_*ark 5

我认为你是对的.您需要像以前一样在绑定器上注册自定义编辑器,以便将String转换为Server实例.有一个自定义的属性编辑器的例子在这里的应该让你开始了Spring参考文档.

我同意MVC文档并不是最好的.我不得不在Spring论坛上做很多谷歌搜索和搜索.

  • 请注意,PropertyEditor是statefull,因此它不是线程安全的.看起来Spring以某种方式处理它,它永远不会在不同的线程中同时调用相同的属性编辑器,但这会导致请求处理速度变慢,因为它一次只处理单个请求.我今天做了这个观察.春季3.1.2.所以我决定不使用PropertyEditor,而是使用Formatters方法 (2认同)