Getting Started with Forms in Spring MVC – 在Spring MVC中开始使用表单

最后修改: 2014年 8月 11日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this article, we will discuss Spring forms and data binding to a controller. Also, we will have a look at one of the main annotations in Spring MVC i.e. @ModelAttribute.

在这篇文章中,我们将讨论Spring表单和与控制器的数据绑定。此外,我们还将了解一下Spring MVC中的一个主要注释,即@ModelAttribute

Of course, Spring MVC is a complex topic with lots of things you need to understand to use it to its full potential, so definitely dig deeper into the framework here.

当然,Spring MVC是一个复杂的话题,你需要了解很多东西才能充分使用它,所以肯定要在这里深入挖掘框架的内容

2. The Model

2.模型

First – let’s define a simple entity that we’re going to display and bind to the form:

首先–让我们定义一个简单的实体,我们将显示并绑定到表单:

public class Employee {
    private String name;
    private long id;
    private String contactNumber;

    // standard getters and setters
}

This will be our form-backing object.

这将是我们的表单支持对象。

3. The View

3.The View

Next – let’s define the actual form, and of course, the HTML file that contains it. We’re going to be using a page where a new employee is created/registered:

接下来–让我们定义实际的表单,当然还有包含它的HTML文件。我们将使用一个创建/注册新员工的页面:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
    <head>
    </head>
    <body>
        <h3>Welcome, Enter The Employee Details</h3>
        <form:form method="POST" 
          action="/spring-mvc-xml/addEmployee" modelAttribute="employee">
             <table>
                <tr>
                    <td><form:label path="name">Name</form:label></td>
                    <td><form:input path="name"/></td>
                </tr>
                <tr>
                    <td><form:label path="id">Id</form:label></td>
                    <td><form:input path="id"/></td>
                </tr>
                <tr>
                    <td><form:label path="contactNumber">
                      Contact Number</form:label></td>
                    <td><form:input path="contactNumber"/></td>
                </tr>
                <tr>
                    <td><input type="submit" value="Submit"/></td>
                </tr>
            </table>
        </form:form>
    </body>
</html>

First – notice that we’re including a tag library into our JSP page – the form taglib – to help with defining our form.

<span style=”color:#首先–注意我们在JSP页面中加入了一个标签库–<em>form taglib–以帮助我们定义表单。

Next – the <form:form> tag plays an important role here; it’s very similar to the regular HTLM <form> tag but the modelAttribute attribute is the key which specifies a name of the model object that backs this form:

下一步–<form:form>标签在这里起着重要的作用;它与普通的HTLM <form>标签非常相似,但modelAttribute 属性是指定支持这个表单的模型对象名称的关键:

<form:form method="POST" 
  action="/SpringMVCFormExample/addEmployee" modelAttribute="employee">

This will correspond to the @ModelAttribute later on in the controller.

这将对应于后来控制器中的@ModelAttribute

Next – each input fields is using yet another useful tag from the Spring Form taglib – form: prefix. Each of these fields specifies a path attribute – this must correspond to a getter/setter of the model attribute (in this case, the Employee class). When the page is loaded, the input fields are populated by Spring, which calls the getter of each field bound to an input field. When the form is submitted, the setters are called to save the values of the form to the object.

接下来–每个输入字段都使用了Spring Form taglib中另一个有用的标签–form: prefix。每个字段都指定了一个path属性–这必须对应于模型属性的getter/setter(本例中是Employee类)。当页面被加载时,输入字段由Spring填充,Spring会调用与输入字段绑定的每个字段的getter。当表单被提交时,设置器被调用以将表单的值保存到对象中。

Finally – when the form is submitted, the POST handler in the controller is invoked and the form is automatically bound to the employee argument that we passed in.

最后–当表单被提交时,控制器中的POST处理程序被调用,表单被自动绑定到我们传入的employee参数。

Basic Forms with Spring MVC

Basic Forms with Spring MVC.

4. The Controller

4.控制器

Now, let’s look at the Controller that’s going to handle the back end:

现在,让我们看看将处理后端的控制器

@Controller
public class EmployeeController {

    @RequestMapping(value = "/employee", method = RequestMethod.GET)
    public ModelAndView showForm() {
        return new ModelAndView("employeeHome", "employee", new Employee());
    }

    @RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
    public String submit(@Valid @ModelAttribute("employee")Employee employee, 
      BindingResult result, ModelMap model) {
        if (result.hasErrors()) {
            return "error";
        }
        model.addAttribute("name", employee.getName());
        model.addAttribute("contactNumber", employee.getContactNumber());
        model.addAttribute("id", employee.getId());
        return "employeeView";
    }
}

The controller defines two simple operations – the GET for displaying data in the form, and the POST for the create operation, via form’s submit.

控制器定义了两个简单的操作–GET用于显示表单中的数据,POST用于创建操作,通过表单的提交。

Also note that if the object called “employee” is not added to the model, Spring would complain when we try to access the JSP because the JSP will be set up to bind the form to the “employee” model attribute:

还要注意,如果名为 “employee “的对象没有被添加到模型中,当我们试图访问JSP时,Spring会抱怨,因为JSP将被设置为将表单与 “employee “模型属性绑定:

java.lang.IllegalStateException: 
  Neither BindingResult nor plain target object 
    for bean name 'employee' available as request attribute
  at o.s.w.s.s.BindStatus.<init>(BindStatus.java:141)

To access our form backing object, we need to inject it via the @ModelAttribute annotation.

为了访问我们的表单支持对象,我们需要通过@ModelAttribute注解注入它。

An <em>@ModelAttribute </em>on a method argument indicates the argument will be retrieved from the model. If not present in the model, the argument will be instantiated first and then added to the model.

一个<em>@ModelAttribute </em>在一个方法参数上表示该参数将被从模型中获取。如果在模型中不存在,该参数将首先被实例化,然后被添加到模型中。

5. Handling Bind Errors

5.处理绑定错误

By default, Spring MVC throws an exception when errors occur during request binding. This usually not what we want, instead, we should be presenting these errors to the user. We’re going to use a BindingResult by adding one as an argument to our controller method:

默认情况下,当请求绑定过程中发生错误时,Spring MVC会抛出一个异常。这通常不是我们想要的,相反,我们应该将这些错误呈现给用户。我们将使用一个BindingResult,在我们的控制器方法中加入一个参数:

public String submit(
  @Valid @ModelAttribute("employee") Employee employee,
  BindingResult result,
  ModelMap model)

The BindingResult argument needs to be positioned right after our form backing object – it’s one of the rare cases where the order of the method arguments matters. Otherwise, we’ll run into the following exception:

BindingResult参数需要紧跟在我们的表单支持对象之后–这是方法参数顺序重要的罕见情况之一。否则,我们就会遇到以下异常:

java.lang.IllegalStateException: 
  Errors/BindingResult argument declared without preceding model attribute. 
    Check your handler method signature!

Now – an exception is no longer thrown; instead, errors will be registered on the BindingResult that is passed to the submit method. At this point, we can handle these errors in a variety of ways – for example, the operation can be canceled:

现在–一个异常不再被抛出;相反,错误将被注册在传递给submit方法的BindingResult上。在这一点上,我们可以通过各种方式来处理这些错误–例如,可以取消操作:

@RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public String submit(@Valid @ModelAttribute("employee")Employee employee, 
  BindingResult result,  ModelMap model) {
    if (result.hasErrors()) {
        return "error";
    }
    
    //Do Something
    return "employeeView";
}

Notice how, in case the result contains errors, we’re returning another view to the user in order to display these errors correctly. Let’s take a look at that view – error.jsp:

请注意,如果结果包含错误,我们将返回另一个视图给用户,以便正确显示这些错误。让我们看看这个视图–error.jsp

<html>
    <head>
    </head>

    <body>
        <h3>Please enter the correct details</h3>
        <table>
            <tr>
                <td><a href="employee">Retry</a></td>
            </tr>
        </table>
    </body>

</html>

6. Displaying an Employee

6.显示一个雇员

Finally, besides creating a new employee, we can also simply display one – here’s the quick view code for that:

最后,除了创建一个新的雇员,我们还可以简单地显示一个雇员–这里是快速查看代码。

<body>
    <h2>Submitted Employee Information</h2>
    <table>
        <tr>
            <td>Name :</td>
            <td>${name}</td>
        </tr>
        <tr>
            <td>ID :</td>
            <td>${id}</td>
        </tr>
        <tr>
            <td>Contact Number :</td>
            <td>${contactNumber}</td>
        </tr>
    </table>
</body>

The JSP page is simply using EL expressions to display values of properties of the Employee object in the model.

JSP页面只是使用EL表达式来显示模型中雇员对象的属性值。

7. Testing the Application

7.测试应用程序

The simple application can be deployed – for example in a Tomcat server – and accessed locally:

简单的应用程序可以被部署–例如在Tomcat服务器中–并在本地访问。

http://localhost:8080/spring-mvc-xml/employee

http://localhost:8080/spring-mvc-xml/employee

This is the view containing the main form – before the submit operation:

这是包含主表单的视图–在提交操作之前:

Spring MVC Form example - Submit

Spring MVC Form example – Submit

Spring MVC表单示例 – 提交

After the submit, the data is displayed:

提交后,显示的数据是:

Spring MVC Form example - View

Spring MVC Form example – View

Spring MVC表单示例 – 视图

And that’s it – a working example of a simple form with Spring MVC, with validation.

就是这样–一个使用Spring MVC的简单表单的工作实例,并带有验证功能

The implementation of this Spring MVC tutorial can be found in the GitHub project – this is a Maven-based project, so it should be easy to import and run as it is.

这个Spring MVC教程的实现可以在GitHub项目中找到–这是一个基于Maven的项目,所以应该很容易导入并按原样运行。

Finally, as I was saying right at the beginning of the article, you should definitely dig deeper into Spring MVC.

最后,正如我在文章开头所说,你应该肯定要深入研究Spring MVC