- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我在理解 Spring 3 MVC 中的表单提交是如何工作时遇到问题。
我想做的是创建一个 Controller ,它将获取用户的姓名并将其显示给他。不知何故,我做到了,但我真的不明白它是如何工作的。所以..
我有一个如下所示的表单:
<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 :
@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 变量(在它们的“路径”属性中设置)。但是看起来,它的工作方式非常不同。如果我删除该行
model.addAttribute("person", new Person());
从“showHelloPage”方法我得到一个(常见的)异常“既没有 BindingResult 也没有......”。
另外,一开始,“sayHello”方法看起来像:
(...)
public String sayHello(@ModelAttribute("person") Person person, Model model) {
(...)
我的意思是,它有“ModelAttribute”注解。我添加了它,因为在我阅读的教程中,它总是存在的。但是在我删除它之后,一切都运行良好,就像以前一样。
所以我的问题是 - “ModelAttribute”注释有什么用?是否有某种方式可以省略表单中的“modelAttribute”属性?第二部分,使表单自动将输入值绑定(bind)到正确 bean 的属性(将被声明为方法参数)的方式(可能是一些注释)是什么?无需在发送表单之前添加一个空 bean(我现在必须这样做)。
感谢您的回复(不是 Spring 文档的链接,因为我已经阅读过)。
最佳答案
@ModelAttribute
在这种情况下,注释用于标识 Spring 应添加为模型属性的对象。模型属性是 HttpServletRequest
的抽象。属性。基本上,它们是由某个键标识的对象,它们将进入HttpServletRequest
。属性。您可以通过手动添加属性来完成此操作 Model#addAttribute(String, Object)
,有一个@ModelAttribute
注释方法,或通过使用 @ModelAttribute
注释方法参数.
您需要了解的是 Spring 如何解析您的处理程序方法参数并注入(inject)参数。它使用 HandlerMethodArgumentResolver
界面这样做。有许多实现类(参见 javadoc),每个类都负责 resolveArgument()
通过将 Spring 将使用的参数返回到 invoke()
您的处理程序方法通过反射。 Spring 只会调用 resolveArgument()
方法如果 HandlerMethodArgumentResolver
supportsParameter()
方法返回 true
对于具体参数。
HandlerMethodArgumentResolver
这里有问题的实现是 ServletModelAttributeMethodProcessor
从 ModelAttributeMethodProcessor
延伸哪些国家
Resolves method arguments annotated with @ModelAttribute and handles return values from methods annotated with @ModelAttribute.
Spring (3.2)将register这个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
有一个 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
参数是否被注释。一个 ModelAttributeMethodProcessor
将解决它并绑定(bind)表单字段,即。请求参数,到实例的字段。您甚至不需要将其添加到 model
作为ModelAttributeMethodProcessor
类将处理。
在您的showHelloPage()
方法
model.addAttribute("person", new Person());
<form>
需要
标签库。这就是它如何解决它的input
字段。
So my question is - what is the use of the "ModelAttribute" anonnatation?
将指定的参数(或方法返回值)自动添加到模型中。
Is it some way to omit a "modelAttribute" attribute in a form?
不,form
绑定(bind)在 Model
中查找对象并将其字段绑定(bind)到 html input
元素。
And the second part, what is the way (maybe some annotation) to make a form automatically bind inputs' values to the proper bean's properties (which would be declared as a method parameter)? Without a need of adding an empty bean before sending a form (as I have to do it now).
一个 Spring <form>
标签锁定模型属性对象并使用其字段创建input
和 label
元素。只要对象最终出现在模型中,它并不重要。如果它找不到具有您指定的名称(键)的模型属性,它会抛出异常,如您所见。
<form:form method="post" modelAttribute="person">
提供空 bean 的替代方法是自己创建 html。所有 Spring 的<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
将请求参数绑定(bind)到实例字段属性。
关于java - Spring MVC 3中的表单提交-解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18944627/
我尝试阅读有关 Spring BOM、Spring Boot 和 Spring IO 的文档。 但是没有说明,我们应该如何一起使用它们? 在我的项目中,我们已经有了自己的 Parent POM ,所以
我正在开发的很酷的企业应用程序正在转向 Spring。这对所有团队来说都是非常酷和令人兴奋的练习,但也是一个巨大的压力源。我们所做的是逐渐将遗留组件移至 Spring 上下文。现在我们有一个 huuu
我正在尝试使用 @Scheduled 运行 Spring 批处理作业注释如下: @Scheduled(cron = "* * * * * ?") public void launchMessageDi
我对这两个概念有点困惑。阅读 Spring 文档,我发现,例如。 bean 工厂是 Spring 容器。我还读到“ApplicationContext 是 BeanFactory 的完整超集”。但两者
我们有一个使用 Spring BlazeDS 集成的应用程序。到目前为止,我们一直在使用 Spring 和 Flex,它运行良好。我们现在还需要添加一些 Spring MVC Controller 。
假设我有一个类(class) Person带属性name和 age ,它可以像这样用 Spring 配置: 我想要一个自定义的 Spring 模式元素,这很容易做到,允许我在我的 Sp
如何在 Java 中以编程方式使用 Spring Data 创建 MongoDB 复合索引? 使用 MongoTemplate 我可以创建一个这样的索引:mongoTemplate.indexOps(
我想使用 spring-complex-task 执行我的应用程序,并且我已经构建了复杂的 spring-batch Flow Jobs,它执行得非常好。 你能解释一下spring批处理流作业与spr
我实现了 spring-boot 应用程序,现在我想将它用作非 spring 应用程序的库。 如何初始化 lib 类,以便 Autowiring 的依赖项按预期工作?显然,如果我使用“new”创建类实
我刚开始学习 spring cloud security,我有一个基本问题。它与 Spring Security 有何不同?我们是否需要在 spring boot 上构建我们的应用程序才能使用 spr
有很多人建议我使用 Spring Boot 而不是 Spring 来开发 REST Web 服务。我想知道这两者到底有什么区别? 最佳答案 总之 Spring Boot 减少了编写大量配置和样板代码的
您能向我解释一下如何使用 Spring 正确构建 Web 应用程序吗?我知道 Spring 框架的最新版本是 4.0.0.RELEASE,但是 Spring Security 的最新版本是 3.2.0
我如何才能知道作为 Spring Boot 应用程序的一部分加载的所有 bean 的名称?我想在 main 方法中有一些代码来打印服务器启动后加载的 bean 的详细信息。 最佳答案 如spring-
我有一个使用 Spring 3.1 构建的 RESTful API,也使用 Spring Security。我有一个 Web 应用程序,也是一个 Spring 3.1 MVC 应用程序。我计划让移动客
升级到 Spring 5 后,我在 Spring Rabbit 和 Spring AMQP 中遇到错误。 两者现在都设置为 1.5.6.RELEASE 有谁知道哪些版本应该与 Spring 5 兼容?
我现在已经使用 Spring Framework 3.0.5 和 Spring Security 3.0.5 多次了。我知道Spring框架使用DI和AOP。我还知道 Spring Security
我收到错误 Unable to Location NamespaceHandler when using context:annotation-config running (java -jar) 由
在 Spring 应用程序中嵌入唯一版本号的策略是什么? 我有一个使用 Spring Boot 和 Spring Web 的应用程序。 它已经足够成熟,我想对其进行版本控制并在运行时看到它显示在屏幕上
我正在使用 spring data jpa 进行持久化。如果存在多个具有相同名称的实体,是否有一种方法可以将一个实体标记为默认值。类似@Primary注解的东西用来解决多个bean的依赖问题 @Ent
我阅读了 Spring 框架的 DAOSupport 类。但是我无法理解这些 DAOSuport 类的优点。在 DAOSupport 类中,我们调用 getXXXTemplate() 方法来获取特定的
我是一名优秀的程序员,十分优秀!