Exploring SpringMVC’s Form Tag Library – 探索SpringMVC’的表单标签库

最后修改: 2016年 3月 7日

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

1. Overview

1.概述

In the first article of this series we introduced the use of the form tag library and how to bind data to a controller.

在本系列的第一篇文章中,我们介绍了表单标签库的使用以及如何将数据绑定到控制器中。

In this article, we’ll cover the various tags that Spring MVC provides to help us create and validate forms.

在这篇文章中,我们将介绍Spring MVC提供的各种标签,以帮助我们创建和验证表单

2. The input Tag

2.input标签

We’ll get started with the input tag. This tag renders an HTML input tag using the bound value and type=’text’ by default:

我们将从input标签开始。这个标签默认使用绑定的值和type=’text’来渲染一个HTMLinput标签。

<form:input path="name" />

Starting with Spring 3.1 you can use other HTML5-specific types, such as email, date, and others. For example, if we wanted to create an email field, we can use type=’email’:

从Spring 3.1开始,你可以使用其他HTML5特有的类型,如电子邮件、日期和其他。例如如果我们想 创建一个电子邮件 我们可以使用 type=’email’。

<form:input type="email" path="email" />

Similarly, to create a date field, we can use type=’date’, which will render a date picker in many browsers compatible with HTML5:

类似地要创建 一个日期字段,我们可以使用type=’date’ ,这将在许多兼容HTML5的浏览器中呈现一个日期选择器。

<form:input type="date" path="dateOfBirth" />

3. The password Tag

3.密码标签

This tag renders an HTML input tag with type=’password’ using the bound value. This HTML input masks the value typed into the field:

这个标签使用绑定的值渲染了一个HTML input标签,type=’password’。这个HTML输入掩盖了打入字段的值。

<form:password path="password" />

4. The textarea Tag

4、textarea标签

This tag renders an HTML textarea:

这个标签渲染了一个HTMLtextarea

<form:textarea path="notes" rows="3" cols="20"/>

We can specify the number of rows and columns in the same way we would an HTML textarea.

我们可以用与HTML textarea相同的方式指定rowscolumns的数量。

5. The checkbox and checkboxes Tag

5.勾选框和勾选框标签

The checkbox tag renders an HTML input tag with type=’checkbox’. Spring MVC’s form tag library provides different approaches to the checkbox tag which should meet all our checkbox needs:

checkbox标签渲染了一个HTML input标签,type=’checkbox’。Spring MVC的表单标签库为checkbox标签提供了不同的方法,应该可以满足我们所有checkbox的需求。

<form:checkbox path="receiveNewsletter" />

The above example generate a classic single checkbox, with a boolean value. If we set the bound value to true, this checkbox will be checked by default.

上面的例子生成了一个经典的单一复选框,有一个boolean值。如果我们将绑定的值设置为true,这个复选框将被默认选中。

The following example generates multiple checkboxes. In this case, the checkbox values are hard-coded inside the JSP page:

下面的例子生成了多个复选框在这种情况下,复选框的值是在JSP页面内硬编码的。

Bird watching: <form:checkbox path="hobbies" value="Bird watching"/>
Astronomy: <form:checkbox path="hobbies" value="Astronomy"/>
Snowboarding: <form:checkbox path="hobbies" value="Snowboarding"/>

Here, the bound value is of type array or java.util.Collection:

这里,绑定的值是arrayjava.util.Collection类型。

String[] hobbies;

The purpose of the checkboxes tag is used to render multiple checkboxes, where the checkbox values are generated at runtime:

checkboxes标签的目的是用来渲染多个复选框,其中复选框的值是在运行时生成的。

<form:checkboxes items="${favouriteLanguageItem}" path="favouriteLanguage" />

To generate the values we pass in an Array, a List or a Map containing the available options in the items property. We can initialize our values inside the controller:

为了生成数值,我们在ArrayListMap中传递一个items属性,包含可用的选项。我们可以在控制器内初始化我们的值。

List<String> favouriteLanguageItem = new ArrayList<String>();
favouriteLanguageItem.add("Java");
favouriteLanguageItem.add("C++");
favouriteLanguageItem.add("Perl");

Typically the bound property is a collection so it can hold multiple values selected by the user:

通常情况下,绑定的属性是一个集合,所以它可以容纳用户选择的多个值。

List<String> favouriteLanguage;

6. The radiobutton and radiobuttons Tag

6、radiobuttonradiobuttons标签

This tag renders an HTML input tag with type=’radio’:

这个标签渲染了一个HTML input标签,type=’radio’:

Male: <form:radiobutton path="sex" value="M"/>
Female: <form:radiobutton path="sex" value="F"/>

A typical usage pattern will involve multiple tag instances with different values bound to the same property:

一个典型的使用模式会涉及多个标签实例,这些实例有不同的值绑定到同一个属性。

private String sex;

Just like the checkboxes tag, the radiobuttons tag renders multiple HTML input tags with type=’radio’:

就像checkboxes标签一样,radiobuttons标签用type=’radio’渲染了多个HTMLinput标签。

<form:radiobuttons items="${jobItem}" path="job" />

In this case, we might want to pass in the available options as an Array, a List or a Map containing the available options in the items property:

在这种情况下,我们可能想以ArrayListMap的形式传入可用的选项,在items属性中包含可用选项。

List<String> jobItem = new ArrayList<String>();
jobItem.add("Full time");
jobItem.add("Part time");

7. The select Tag

7.select标签

This tag renders an HTML select element:

这个标签渲染了一个HTML select元素。

<form:select path="country" items="${countryItems}" />

To generate the values we pass in an Array, a List or a Map containing the available options in the items property. Once again, we can initialize our values inside the controller:

为了生成这些值,我们传入一个ArrayListMap,其中包含items属性中的可用选项。再一次,我们可以在控制器中初始化我们的值。

Map<String, String> countryItems = new LinkedHashMap<String, String>();
countryItems.put("US", "United States");
countryItems.put("IT", "Italy");
countryItems.put("UK", "United Kingdom");
countryItems.put("FR", "France");

The select tag also support the use of nested option and options tags.

选择标签还支持使用嵌套的optionoptions标签。

While the option tag renders a single HTML option, the options tag renders a list of HTML option tags.

option标签渲染了一个单一的HTML option,而options标签渲染了一个HTML option标签的列表。

The options tag takes an Array, a List or a Map containing the available options in the items property, just like the select tag:

options标签接收一个ArrayListMap,其中包含items属性中的可用选项,就像select标签。

<form:select path="book">
    <form:option value="-" label="--Please Select--"/>
    <form:options items="${books}" />
</form:select>

When we have the need to select several items at once, we can create a multiple list box. To render this type of list, just add the multiple=”true” attribute in the select tag.

我们有 需要 选择 几个项目一次。我们可以创建一个 多个列表框。要呈现这种类型的列表,只需在select标签中添加multiple=”true”属性。

<form:select path="fruit" items="${fruit}" multiple="true"/>

Here the bound property is an array or a java.util.Collection:

这里绑定的属性是一个array或者一个java.util.Collection

List<String> fruit;

8. The hidden Tag

8、hidden标签

This tag renders an HTML input tag with type=’hidden’ using the bound value:

这个标签使用绑定的值渲染一个HTML input标签,type=’hidden’

<form:hidden path="id" value="12345" />

9. The Errors Tag

9.错误标签

Field error messages are generated by validators associated with the controller. We can use The Errors Tag to render those field error messages:

字段错误信息是由与控制器相关的验证器产生的。我们可以使用The Errors Tag来呈现这些字段错误信息。

<form:errors path="name" cssClass="error" />

This will display errors for the field specified in the path property. The error messages are rendered within a span tag by default, with .errors appended to the path value as the id, and optionally a CSS class from the cssClass property, which can be used to style the output:

这将显示path属性中指定字段的错误。默认情况下,错误信息在spantag内呈现,.errors应用于path值作为id,还可以从cssClass属性中选择一个CSS类,它可以用来为输出设置样式。

<span id="name.errors" class="error">Name is required!</span>

To enclose the error messages with a different element instead of the default span tag, we can specify the preferred element inside the element attribute:

要用不同的元素来包围错误信息,而不是默认的span标签,我们可以在element属性中指定首选元素。

<form:errors path="name" cssClass="error" element="div" />

This renders the error messages within a div element:

这在div元素中渲染了错误信息。

<div id="name.errors" class="error">Name is required!</div>

In addition to having the capability to show errors for a specific input element, we can display the entire list of errors (regardless of field) for a given page. This is achieved by the use of the wildcard *:

I除了拥有 显示错误的能力 特定输入 元素。我们可以显示一个给定页面的整个错误列表(无论哪个字段)。这是通过使用通配符 *实现的。

<form:errors path="*" />

9.1. The Validator

9.1.验证器

To display errors for a given field we need to define a validator:

为了显示一个给定字段的错误,我们需要定义一个验证器。

public class PersonValidator implements Validator {

    @Override
    public boolean supports(Class clazz) {
        return Person.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object obj, Errors errors) {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required.name");
    }
}

In this case, if the field name is empty, the validator returns the error message identified by required.name from the resource bundle.

在这种情况下,如果字段name是空的,验证器会返回资源包中由required.name标识的错误信息。

The resource bundle is defined in the Spring XML configuration file as follows:

资源包在Spring XML 配置文件中定义如下。

<bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource">
     <property name="basename" value="messages" />
</bean>

Or in a pure Java configuration style:

或者以纯Java的配置风格。

@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasenames("messages");
    return messageSource;
}

The error message is defined inside the messages.properties file:

错误信息在messages.properties文件内定义。

required.name = Name is required!

To apply this validation, we need to include a reference to the validator in our controller and call the method validate in the controller method which is called when user submits the form:

为了应用这个验证,我们需要在控制器中包含一个对验证器的引用,并在控制器方法中调用validate方法,当用户提交表单时调用该方法。

@RequestMapping(value = "/addPerson", method = RequestMethod.POST)
public String submit(
  @ModelAttribute("person") Person person, 
  BindingResult result, 
  ModelMap modelMap) {

    validator.validate(person, result);

    if (result.hasErrors()) {
        return "personForm";
    }
    
    modelMap.addAttribute("person", person);
    return "personView";
}

9.2. JSR 303 Bean Validation

9.2.JSR 303 Bean验证

Starting from Spring 3, we can use JSR 303 (via the @Valid annotation) for bean validation. To do this we need a JSR303 validator framework on the classpath. We will use the Hibernate Validator (the reference implementation). Following is the dependency that we need to include in the POM:

从Spring 3开始,我们可以使用JSR303(通过@Valid注解)进行bean验证。要做到这一点,我们需要在classpath上有一个JSR303验证器框架。我们将使用Hibernate Validator(参考实现)。以下是我们需要包含在POM中的依赖关系。

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.1.1.Final</version>
</dependency>

To make Spring MVC support JSR 303 validation via the @Valid annotation, we need to enable the following in our Spring configuration file:

为了使Spring MVC通过@Valid 注解支持JSR 303验证,我们需要在Spring配置文件中启用以下内容。

<mvc:annotation-driven/>

Or use the corresponding annotation @EnableWebMvc in a Java configuration:

或者在Java配置中使用相应的注解@EnableWebMvc

@EnableWebMvc
@Configuration
public class ClientWebConfigJava implements WebMvcConfigurer {
    // All web configuration will go here
}

Next, we need to annotate the controller method that we want to validate with the @Valid annotation:

接下来,我们需要为控制器方法我们想要validate加注@Valid

@RequestMapping(value = "/addPerson", method = RequestMethod.POST)
public String submit(
  @Valid @ModelAttribute("person") Person person, 
  BindingResult result, 
  ModelMap modelMap) {
 
    if(result.hasErrors()) {
        return "personForm";
    }
     
    modelMap.addAttribute("person", person);
    return "personView";
}

Now we can annotate the entity’s property to validate it with Hibernate validator annotation:

现在我们可以用Hibernate验证器注解对实体的属性进行验证。

@NotEmpty
private String password;

By default, this annotation will display “may not be empty” if we leave the password input field empty.

默认情况下,如果我们让密码输入字段为空,该注释将显示“不一定为空”

We can override the default error message by creating a property in the resource bundle defined in the validator example. The key of the message follows the rule AnnotationName.entity.fieldname:

我们可以通过在验证器示例中定义的资源包中创建一个属性来覆盖默认的错误信息。该消息的关键遵循AnnotationName.entity.fieldname规则。

NotEmpty.person.password = Password is required!

10. Conclusion

10.结论

In this tutorial we explored the various tags that Spring provides for working with forms.

在本教程中,我们探讨了Spring提供的用于处理表单的各种标签。

We also had a look at the tag for validation error displaying and the configuration needed to display custom error messages.

我们也看了一下显示验证错误的标签和显示自定义错误信息所需的配置。

All the examples above can be found in a GitHub project. This is an Eclipse-based project, so it should be easy to import and run as it is.

上述所有的例子都可以在GitHub项目中找到。这是一个基于Eclipse的项目,所以应该很容易导入并按原样运行。

When the project runs locally, the form example can be accessed at:

当项目在本地运行时,可以通过以下网址访问该表格实例。

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

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