Spring MVC:在表单处理操作中有多个@ModelAttribute

2024-04-27

上下文

我在两个实体之间有一个简单的关联 -Category and Email(NtoM)。我正在尝试创建用于浏览和管理它们的网络界面。要浏览类别并将电子邮件添加到该类别中,我使用包含以下内容的控制器@RequestMapping带有类别 ID (UUID),因此所有控制器操作始终在路径指定的类别上下文中发生。

I use @ModelAttribute为整个控制器范围预加载上下文类别。

问题

这种方法对于列出和显示表单非常有效。然而,它在表单提交时失败 - 经过一些调试后,我发现表单数据覆盖了我的类别@ModelAttribute范围。

在我的代码中,在方法中save() the category并不是真正加载的模型属性addCategory()方法,但填充了表单数据(email模型也已填充,这是正确的)。

我正在寻找允许我将表单数据仅绑定到特定的解决方案@ModelAttribute.

我在 Spring MVC 文档中读到参数的顺序很重要,但我根据示例对它们进行了排序,但它仍然无法按预期工作。

The code

这是我的控制器:

@Controller
@RequestMapping("/emails/{categoryId}")
public class EmailsController
{
    @ModelAttribute("category")
    public Category addCategory(@PathVariable UUID categoryId)
    {
        return this.categoryService.getCategory(categoryId);
    }

    @InitBinder
    public void initBinder(WebDataBinder binder)
    {
        binder.registerCustomEditor(Set.class, "categories", new CategoriesSetEditor(this.categoryService));
    }

    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public String createForm(@ModelAttribute Category category, Model model)
    {
        // here everything works, as there is just a single @ModelAttribute

        return "emails/form";
    }

    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public String save(
        @ModelAttribute @Valid Email email,
        BindingResult result,
        Model model,
        @ModelAttribute("category") Category category
    ) {
        // saving entity, etc

        // HERE! problem is, that response is bound BOTH to `email' and `category' model attributes
        // and overrides category loaded in `addCategory()' method
        return String.format("redirect:/emails/%s/", category.getId().toString());
    }
}

以防万一,这里还有表单代码:

<form:form action="${pageContext.request.contextPath}/emails/${category.id}/save" method="post" modelAttribute="email">
    <form:hidden path="id"/>
    <fieldset>
        <label for="emailName"><spring:message code="email.form.label.Name" text="E-mail address"/>:</label>
        <form:input path="name" id="emailName" required="required"/>
        <form:errors path="name" cssClass="error"/>

        <label for="emailRealName"><spring:message code="email.form.label.RealName" text="Recipient display name"/>:</label>
        <form:input path="realName" id="emailRealName"/>
        <form:errors path="realName" cssClass="error"/>

        <label for="emailIsActive"><spring:message code="email.form.label.IsActive" text="Activation status"/>:</label>
        <form:checkbox path="active" id="emailIsActive"/>
        <form:errors path="active" cssClass="error"/>

        <form:checkboxes path="categories" element="div" items="${categories}" itemValue="id" itemLabel="name"/>
        <form:errors path="categories" cssClass="error"/>

        <button type="submit"><spring:message code="_common.form.Submit" text="Save"/></button>
    </fieldset>
</form:form>

Note:我不想要多个@ModelAttribute来自 POST,只是想以某种方式将表单模型与之前生成的属性区分开来。


我不确定我完全理解这个问题,但对我来说,您似乎希望在显示表单时模型中存在类别对象,但不希望它通过表单发布进行更改?

当您在参数列表中指定 @ModelAttribute("categories") 时,您基本上告诉 spring MVC 使用参数名称“categories”将表单数据绑定到带注释的对象。

如果您不想绑定该对象,只需将其从参数列表中删除即可。如果您需要处理程序方法中的原始对象,请通过调用 addCategory 并提供使用 @PathVariable 映射的 id 来手动获取它:

@RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(
    @ModelAttribute @Valid Email email,
    BindingResult result,
    Model model,
    @PathVaribale("categoryId") UUID categoryId
) {
    // saving entity, etc

    return String.format("redirect:/emails/%s/", categoryId.toString());
    //if category object is needed and not just id then fetch it with Category c = addCategory(categoryId).
}

(PS。如果您注册一个使用categoryService将Long转换为Category的转换器,您也可以将@PathVariable("categoryId") Category category将 Category 对象映射到路径变量而不是 UUID,如果您愿意,请查看7.5.5 配置转换服务 http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/validation.html)

(编辑:删除了以不同方式命名模型的建议,因为这不会有帮助,如评论中所述,并添加了示例)

就个人而言,如果我需要这种行为(在显示表单时需要在表单中出现的对象,但在发布表单时不绑定到它),我不会使用 ModelAttribute 带注释的方法来填充模型。相反,我会在显示表单时手动填充模型。这是多一点的代码(实际上是一行),但不那么神奇并且更容易理解。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring MVC:在表单处理操作中有多个@ModelAttribute 的相关文章

随机推荐

  • 在 IntelliJ 中创建新包

    我刚刚从使用 Eclipse 多年转向 IntelliJ 的美丽新世界 我正在努力解决那些拖慢我速度的小事情 当你知道如何去做时 最新的希望是显而易见的 我在源文件夹下创建一个新包 uk ac cam admin 我右键单击这个新包来创建另
  • 将仅限 HTTPS 的自定义域正确分配给 flex env

    将自定义域映射到 Google App Engine 项目的正确方法是什么 我已经添加了自定义域 设置了所有 DNS 记录等 并且它正在工作 但如何仅强制执行 HTTPS 就像生成的自定义域一样 从阅读周围many我看过的帖子secure
  • 当非特权用户运行 C/asm 程序时,会对 Linux 造成什么危害?

    我一直在考虑一种场景 让用户 可以是任何人 可能有恶意 提交在 Linux PC 我们称之为基准节点 上运行的代码 目标是为单线程例程创建一种自动化基准测试环境 假设一个网站向代理发布了一些代码 该代理将此代码交给基准节点 而基准节点仅与代
  • postgres union 是否保证调用有副作用的函数时的执行顺序?

    我正在使用 postgres 9 3 并尝试确保从 sql 语句调用时按顺序调用存储过程 以下操作是否有效 确保首先调用 foo 然后调用 bar select null void from select 1 from foo union
  • curl:(7)无法连接到192.168.99.100端口31591:连接被拒绝

    这些是我的豆荚 hello kubernetes 5569fb7d8f 4rkhs 0 1 ImagePullBackOff 0 5d2h hello minikube 5857d96c67 44kfg 1 1 Running 1 5d2h
  • “char *_EXFUN(index,(const char *, int));”的含义

    我发现这是 eclipse idexer intelisence 的一个命题 无论它叫什么 就是这样 char EXFUN index const char int 首先 它看起来像一个返回 char 指针的函数 但参数 如果它是一个函数
  • 使用 M1 在 dockerized Linux 上安装节点画布

    我有以下Dockerfile我在 MacBook Air M1 上运行 所以在 docker 中我有带有 M1 的 linux FROM node 16 7 0 WORKDIR work CMD while true do sleep 10
  • Spirit qi 解析为嵌套函数的抽象语法树

    我正在尝试使用 boost 的spirit qi 解析器创建一个解析器 它正在解析包含三种类型值的字符串 常量 变量或函数 这些函数可以相互嵌套 测试字符串是f a b f g z x g x h x c where a e是常数 f r是
  • 如何获得修改任何参数的函数?

    我的目标 我必须创建一个将两个分数相加的函数 我定义了一个新的struct typedef 称为fraction 该函数不能有返回类型fraction 它一定要是void 因此它必须修改输入的参数之一 我该如何实现这一点 也许是指点 您将如
  • 从状态栏中删除通知图标

    我在状态栏中显示一个图标 现在我想在打开该内容时立即删除该图标 一段时间后如果我们收到任何警报 该图标将再次显示 我怎样才能做到这一点 使用NotificationManager取消您的通知 您只需提供您的通知 ID https devel
  • 将一个表的所有行复制到另一个表

    我有两个数据库MySQL and SQL Server 我想在其中创建表SQL Server并复制表中的所有行MySQL到新表中SQL Server 我可以在中创建表SQL Server与 一样MySQL 使用以下代码 List
  • 自 2012 年以来,WinSock 注册 IO 性能是否有所下降?

    我最近使用 MS 为该 API 提供的稍微可接受的文档编写了基于 WinSock Registered IO RIO 的 UDP 接收 最终的性能非常令人失望 单套接字性能有些稳定 约为每秒 180k 数据包 使用多个 RSS 队列 即多个
  • 选择从查询中检索列名称的列

    我正在寻找一种优雅的方法来从表 A 中选择列 其中列名是从表 B 上的查询中检索的 对表 B 的查询结果 col01 表 A 有几个名为 col01 col02 col03 最终查询应该是为了结果 result from B effecti
  • 根据区域设置获取货币 ISO 4217 代码

    假设我用以下命令解析 HTTP Accept Language 标头Locale acceptFromHttp http www php net manual en locale acceptfromhttp php是否有一种简单可靠的方法
  • Java 中的字符串拆分:可变长度的前向和后向

    我想使用数字作为分隔符来破坏 Java 中的字符串 但保留数字 一些研究表明 使用 String 中的 split method 是合适的 但我不明白如何做到这一点 为了进一步解释我的问题 我将使用一个例子 Input 20 55 50 0
  • 使用 VBA 从分布生成随机数到内存

    我想从 VBA Excel 2007 中选定的分布生成随机数 我目前正在使用带有以下代码的分析工具库 Application Run ATPVBAEN XLAM Random A B C D E F Where A how many var
  • 如何在 POSIXct 中获取一天的开始

    我的一天开始于2016 03 02 00 00 00 Not 2016 03 02 00 00 01 我如何开始一天的工作POSIXct当地时间 我的困惑可能来自于 R 认为这是 2016 03 01 的结束日期这一事实 鉴于 R 使用 I
  • 如何减少基于位置的 Android 应用程序的功耗?

    如何减少应用程序的功耗 我可以使用什么代码来实现这个 有几种不同的方法可以减少尝试获取位置信息时所用的电量 Use the 最后已知位置 http developer android com reference android locati
  • HtmlAgilityPack 设置节点 InnerText

    我想用其他文本替换 HTML 标签的内部文本 我正在使用 HtmlAgilityPack我使用这段代码来提取所有文本 HtmlDocument doc new HtmlDocument doc Load some path foreach
  • Spring MVC:在表单处理操作中有多个@ModelAttribute

    上下文 我在两个实体之间有一个简单的关联 Category and Email NtoM 我正在尝试创建用于浏览和管理它们的网络界面 要浏览类别并将电子邮件添加到该类别中 我使用包含以下内容的控制器 RequestMapping带有类别 I