Spring MVC 3 中的表单提交 - 说明

2024-05-07

我在理解 Spring 3 MVC 中的表单提交如何工作时遇到问题。

我想做的是创建一个控制器,它将获取用户的名字并将其显示给他。不知怎的,我已经做到了,但我不太明白它是如何工作的。所以..

我有一个看起来像这样的表格:

<form:form method="post" modelAttribute="person">
    <form:label path="firstName">First name</form:label>
    <form:input path="firstName" />
    <br />

    <form:label path="lastName">Last name</form:label>
    <form:input path="lastName" />
    <br />

    <input type="submit" value="Submit" />
</form:form>

我还有一个控制器,如下所示:

@Controller
public class HomeController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String showHelloPage(Model model) {
        model.addAttribute("person", new Person());
        return "home";
    }

    @RequestMapping(value = "/", method = RequestMethod.POST)
    public String sayHello(Person person, Model model) {
        model.addAttribute("person", person);
        return "home";
    }
}

为了向用户显示欢迎消息,我在 JSP 页面中使用以下代码:

<c:if test="${not empty person.firstName and not empty person.lastName}">
    Hello ${person.firstName} ${person.lastName}!
</c:if>

它有效(我省略了 XML 配置文件,因为它们与问题无关)。

我认为表单中的“modelAttribute”属性指向应该用输入值填充的 bean 变量(如在“path”属性中设置的那样)。但看起来,它的工作方式非常不同。如果我删除该行

model.addAttribute("person", new Person());

从“showHelloPage”方法中,我得到一个(常见)异常“BindingResult 也不是...”。

另外,一开始,“sayHello”方法如下所示:

(...)
public String sayHello(@ModelAttribute("person") Person person, Model model) {
(...)

我的意思是,它有“ModelAttribute”注释。我添加了它,因为在我读过的教程中,它始终存在。但当我把它取下来后,一切都运转良好,就像以前一样。

所以我的问题是- “ModelAttribute”注释有什么用?是否可以通过某种方式省略表单中的“modelAttribute”属性?第二部分,使表单自动将输入值绑定到正确 bean 的属性(将被声明为方法参数)的方法(可能是一些注释)是什么?无需在发送表单之前添加空 bean(因为我现在必须这样做)。

感谢您的回复(这不是 Spring 文档的链接,因为我已经阅读过它)。


The @ModelAttribute http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/web/bind/annotation/ModelAttribute.html在这种情况下,注释用于标识 Spring 应添加为模型属性的对象。模型属性是从HttpServletRequest属性。基本上,它们是由某个键标识的对象,它们会找到进入HttpServletRequest属性。您可以通过手动添加属性来完成此操作Model#addAttribute(String, Object), 有一个@ModelAttribute带注释的方法,或者通过注释方法参数@ModelAttribute.

您需要了解的是 Spring 如何解析处理程序方法参数并注入参数。它使用HandlerMethodArgumentResolver http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/web/method/support/HandlerMethodArgumentResolver.html%60接口来执行此操作。有许多实现类(参见 javadoc),每个类都有责任resolveArgument()通过返回 Spring 将使用的参数invoke()通过反射你的处理程序方法。 Spring只会调用resolveArgument()方法如果HandlerMethodArgumentResolver supportsParameter()方法返回true对于具体参数。

The HandlerMethodArgumentResolver这里有问题的实施是ServletModelAttributeMethodProcessor http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ServletModelAttributeMethodProcessor.html它延伸自ModelAttributeMethodProcessor http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/web/method/annotation/ModelAttributeMethodProcessor.html其中指出

解析用 @ModelAttribute 注释的方法参数和句柄 从使用 @ModelAttribute 注释的方法返回值。

春天(3.2)将register http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.html this HandlerMethodArgumentResolver和别的

private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
        List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();

    // Annotation-based argument resolution
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
    resolvers.add(new RequestParamMapMethodArgumentResolver());
    resolvers.add(new PathVariableMethodArgumentResolver());
    resolvers.add(new ServletModelAttributeMethodProcessor(false));
    resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
    resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
    resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new RequestHeaderMapMethodArgumentResolver());
    resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));

    // Type-based argument resolution
    resolvers.add(new ServletRequestMethodArgumentResolver());
    resolvers.add(new ServletResponseMethodArgumentResolver());
    resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));
    resolvers.add(new RedirectAttributesMethodArgumentResolver());
    resolvers.add(new ModelMethodProcessor());
    resolvers.add(new MapMethodProcessor());
    resolvers.add(new ErrorsMethodArgumentResolver());
    resolvers.add(new SessionStatusMethodArgumentResolver());
    resolvers.add(new UriComponentsBuilderMethodArgumentResolver());

    // Custom arguments
    if (getCustomArgumentResolvers() != null) {
        resolvers.addAll(getCustomArgumentResolvers());
    }

    // Catch-all
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
    resolvers.add(new ServletModelAttributeMethodProcessor(true));

    return resolvers;
}

当 Spring 需要调用您的处理程序方法时,它将遍历参数类型和上面的列表,并使用第一个supportsParameter().

请注意,两个实例ServletModelAttributeMethodProcessor添加(一个后一个//catch all评论)。这ModelAttributeMethodProcessor has a annotationNotRequired字段告诉它是否应该寻找@ModelAttribute或不。第一个实例必须寻找@ModelAttribute,第二个没有。 Spring 这样做是为了让你可以注册你自己的HandlerMethodArgumentResolver实例,请参阅// Custom arguments评论。


具体来说

@RequestMapping(value = "/", method = RequestMethod.POST)
public String sayHello(Person person, Model model) {
    model.addAttribute("person", person);
    return "home";
}

在这种情况下,您是否Person参数是否带注释。 AModelAttributeMethodProcessor将解决它并绑定表单字段,即。请求参数,到实例的字段。您甚至不需要将其添加到model as the ModelAttributeMethodProcessor类会处理这个问题。

In your showHelloPage() method

model.addAttribute("person", new Person());

需要与<form>标签库。这就是它解决的方式input fields.


所以我的问题是 - “ModelAttribute”有什么用 注释?

自动将指定的参数(或方法返回值)添加到模型中。

是否可以通过某种方式省略表单中的“modelAttribute”属性?

No, the form绑定在中查找对象Model并将其字段绑定到 htmlinput元素。

第二部分,制作一个的方法是什么(也许是一些注释) 表单自动将输入的值绑定到正确的 bean 属性 (这将被声明为方法参数)?无需添加 在发送表单之前一个空bean(因为我现在必须这样做)。

一个春天<form>标签锁定模型属性对象并使用其字段来创建input and label元素。对象如何最终出现在模型中并不重要,只要它存在即可。如果它找不到具有您指定的名称(键)的模型属性,则会抛出异常,如您所见。

 <form:form method="post" modelAttribute="person">

提供空 bean 的替代方法是自己创建 html。都是春天的<form>所做的就是使用 bean 的字段名称来创建input元素。所以这

<form:form method="post" modelAttribute="person">
    <form:label path="firstName">First name</form:label>
    <form:input path="firstName" />

创建类似的东西

<form method="post" action="[some action url]">
    <label for="firstName">First name<label>
    <input type="text" name="firstName" value="[whatever value firstName field had]" />
    ...

Spring使用以下方法将请求参数绑定到实例字段name属性。

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

Spring MVC 3 中的表单提交 - 说明 的相关文章

  • laravel 正则表达式验证不起作用

    我刚刚开始使用 laravel 正在努力验证我的表单之一中的文本区域 文本区域用于用户简介 因此我只想允许使用字母 数字 空格和以下字符 这就是我所拥有的 validator Validator make Input all array b
  • 清空变量不会使方法引用无效[重复]

    这个问题在这里已经有答案了 为什么代码不抛出NullPointerException当我使用与变量绑定的方法引用时dog我后来分配了null to 我正在使用 Java 8 import java util function Functio
  • 当前平台不支持桌面 API

    我遇到过这个错误 java lang UnsupportedOperationException 当前平台不支持桌面 API 我将从我的 java 应用程序中打开一个文件 我用这个方法 Desktop getDesktop open new
  • 在 doxygen 中使用 @see 或 @link

    我之前用 Javadoc 记录并使用了标签 see link or see foo and link foo 在我的描述中链接到其他课程 现在我尝试了doxygen 似乎这些标签不兼容 如果我运行 doxygen 完整的标签将被简单地解释为
  • 递归取消 allOf CompletableFuture

    如果我有 CompletableFuture
  • 如何检查单词是否在wordNet中

    我开始了解wordNet直到我知道我找到了synonymous对于一个特定的词 现在我有一个文件 我想使用标记化该文本n gram例如 String s I like to wear tee shirt 使用后n gram这将是 I lik
  • 生成一定长度的所有排列

    假设我们有一个字母表 abcdefghiklimnop 如何以有效的方式以五个一组的形式重复该字母表来递归生成排列 几天来我一直在为此苦苦挣扎 任何反馈都会有帮助 本质上这与 生成给定字符串的所有排列 https stackoverflow
  • java.exe 以非零退出值 1 结束

    只是为了开始 我并不是真正尝试从 Android 中的 xlsx 文件中读取单元格 我已经尝试了几乎所有我在 Google 上搜索到的内容 但是每次 在两台不同的 PC 上 都是 Java 1 7 0 79 当我尝试构建 运行 这个应用程序
  • 扩展多个类

    我知道 Java 不支持多重继承 因为不允许扩展多个类 我只是想知道我的问题是否有解决方法 我有一个名为CustomAction需要扩展两个抽象类 BaseAction and QuoteBaseAction 我无法更改这些抽象类中的任何一
  • 获取接收者的设备令牌以在 Firebase 中发送通知

    所以我正在学习如何使用 firebase 发送设备到设备的通知 我看到了这个answer https stackoverflow com a 42548586 5237289发送通知 看起来很简单 现在 我知道要获取发件人的令牌 它应该如下
  • 如何在 JASPIC 中保存经过身份验证的用户?

    我开发了一个安全认证模块 SAM 并实现了validateRequest方法 我还有一个简单的 Web 应用程序配置为使用此 SAM In my validateRequest方法 我检查 clientSubject 并设置一个Caller
  • 难以理解 通配符

    我有一个非常基本的问题 下面的代码无法编译 假设 Apple Extends Fruit List
  • 如何更改 JAX-WS Web 服务的地址位置

    我们目前已经公开了具有以下 URL 的 JAX RPC Web 服务 http xx xx xx xx myservice MYGatewaySoapHttpPort wsdl http xx xx xx xx myservice MYGa
  • 如何在不使用 -cp 开关的情况下在 Groovy 中自动加载数据库 jar?

    我想简化调用 Oracle 数据库的 Groovy 脚本的执行 如何将 ojdbc jar 添加到默认类路径以便我可以运行 groovy RunScript groovy 代替 groovy cp ojdbc5 jar RunScript
  • Spring MVC:通用 DAO 和服务类

    我正在 Spring MVC 中编写网页 我使用 Generic DAO 编写了所有 DAO 现在我想重写我的服务类 我该如何写 通用服务 我的 DAO 如下 DAO package net example com dao import j
  • ebean 映射到 BYTEA 的数据类型是什么?

    我有一个游戏 2 0 2 需要在数据库中存储一些文件的应用程序 我们使用 Ebean 作为 ORM 我相信我的数据库中需要一个 BYTEA 列来存储该文件 但我不确定在我的模型中使用什么数据类型 我应该使用某种Blob 或者只是一个byte
  • Axis2 的 wsdl2java 在 RPC/Encoded 样式 Web 服务上失败

    Axis2 有替代方案吗 或者让它工作的方式 例如不同的数据绑定 Retrieving document at Exception in thread main org apache axis2 wsdl codegen CodeGener
  • JPA ManyToMany 产生的空联接表

    我有一个应用程序 其中我尝试使用 Hibernate 作为 JPA 提供程序来实现两个实体之间的多对多关系 我正在尝试的例子是一个单向的 其中一个相机可以有多个镜头 而镜头可以安装到多个相机中 以下是我的实体类 只需粘贴其中的相关部分 Ca
  • Graphics2D setfont() 严重减慢了 java 应用程序的启动速度

    我正在用java制作一个游戏 它每秒刷新60次 每次执行循环时 我都会使用 g2d 来绘制图像和字符串 如果我这样做的话一切都会很好g2d setFont new Font Arial Font PLAIN 8 和抽绳 这将是正常的 但如果
  • MyBatis 枚举的使用

    我知道以前有人问过这个问题 但我无法根据迄今为止找到的信息实施解决方案 所以也许有人可以向我解释一下 我有一个表 状态 它有两列 id 和 name id是PK 我不想使用 POJO Status 而是使用枚举 我创建了这样一个枚举 如下所

随机推荐