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

最后修改: 2016年 3月 7日


1. Overview


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


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


<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


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


This tag renders an HTML textarea:


<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


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.


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


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:


String[] hobbies;

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


<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:


List<String> favouriteLanguageItem = new ArrayList<String>();

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


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’:


<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:


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

7. The select Tag


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:


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.


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:


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

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:


List<String> fruit;

8. The hidden Tag


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


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:


<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:


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

This renders the error messages within a div element:


<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


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


public class PersonValidator implements Validator {

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

    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.


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" />

Or in a pure Java configuration style:


public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    return messageSource;

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


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:


@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中的依赖关系。


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配置文件中启用以下内容。


Or use the corresponding annotation @EnableWebMvc in a Java 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:


@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:


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:


NotEmpty.person.password = Password is required!

10. Conclusion


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


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.


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