JSP and JSTL
Spring Framework 为将 Spring MVC 与 JSP 和 JSTL 一起使用提供了内置集成。
The Spring Framework has a built-in integration for using Spring MVC with JSP and JSTL.
View Resolvers
在使用 JSP 进行开发时,您通常声明一个 InternalResourceViewResolver
bean。
When developing with JSPs, you typically declare an InternalResourceViewResolver
bean.
InternalResourceViewResolver
可用于调度到任何 Servlet 资源,但特别用于 JSP。作为最佳实践,我们强烈建议您将 JSP 文件放在“WEB-INF”目录下的某个目录中,以便客户端无权直接访问。
InternalResourceViewResolver
can be used for dispatching to any Servlet resource but in
particular for JSPs. As a best practice, we strongly encourage placing your JSP files in
a directory under the ’WEB-INF'` directory so there can be no direct access by clients.
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
JSPs versus JSTL
在使用 JSP 标准标记库 (JSTL) 时,您必须使用一个特殊视图类 JstlView
,因为 JSTL 在 I18N 等功能可以正常使用之前需要进行一些准备。
When using the JSP Standard Tag Library (JSTL) you must use a special view class, the
JstlView
, as JSTL needs some preparation before things such as the I18N features can
work.
Spring’s JSP Tag Library
如前几章所述,Spring 提供了将请求参数数据绑定到命令对象的功能。为了促进 JSP 页面的开发与那些数据绑定功能的结合,Spring 提供了几个标签,让事情变得更简单。所有 Spring 标签都具有 HTML 转义功能,可以启用或禁用字符的转义。
Spring provides data binding of request parameters to command objects, as described in earlier chapters. To facilitate the development of JSP pages in combination with those data binding features, Spring provides a few tags that make things even easier. All Spring tags have HTML escaping features to enable or disable escaping of characters.
`spring.tld`标记库描述符(TLD)包含在 `spring-webmvc.jar`中。要获得各个标记的全面参考,请浏览 API 参考 或查看标记库描述。
The spring.tld
tag library descriptor (TLD) is included in the spring-webmvc.jar
.
For a comprehensive reference on individual tags, browse the
API reference
or see the tag library description.
Spring’s form tag library
从版本 2.0 开始,Spring 提供了一组全面的数据绑定感知标签,用于在使用 JSP 和 Spring Web MVC 时处理表单元素。每个标记都为其对应的 HTML 标记对应项的属性集提供支持,使这些标记很熟悉且直观。标签生成的 HTML 是 HTML 4.01/XHTML 1.0 兼容的。
As of version 2.0, Spring provides a comprehensive set of data binding-aware tags for handling form elements when using JSP and Spring Web MVC. Each tag provides support for the set of attributes of its corresponding HTML tag counterpart, making the tags familiar and intuitive to use. The tag-generated HTML is HTML 4.01/XHTML 1.0 compliant.
与其他表单/输入标记库不同,Spring 的表单标记库与 Spring Web MVC 集成,使这些标记能够访问您的控制器所处理的命令对象和参考数据。正如我们在以下示例中所示,表单标记使 JSP 更易于开发、阅读和维护。
Unlike other form/input tag libraries, Spring’s form tag library is integrated with Spring Web MVC, giving the tags access to the command object and reference data your controller deals with. As we show in the following examples, the form tags make JSPs easier to develop, read, and maintain.
我们将详细了解这些表单标记,并看一个示例来说明如何使用每个标记。我们已经包含了生成的 HTML 代码段,而某些标记需要进一步说明。
We go through the form tags and look at an example of how each tag is used. We have included generated HTML snippets where certain tags require further commentary.
Configuration
表单标记库捆绑在 spring-webmvc.jar
中。库描述符称为 spring-form.tld
。
The form tag library comes bundled in spring-webmvc.jar
. The library descriptor is
called spring-form.tld
.
要使用此库中的标记,请将以下指令添加到 JSP 页面的顶部:
To use the tags from this library, add the following directive to the top of your JSP page:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
其中,form
是您想在此库中用于这些标记的标记名称前缀。
where form
is the tag name prefix you want to use for the tags from this library.
The Form Tag
这个标记呈现一个 HTML “form”元素,并为用于绑定的内部标记公开一个绑定路径。它将命令对象放入 PageContext
中,以便内部标记可以访问该命令对象。此库中的所有其他标记都是 form
标记的嵌套标记。
This tag renders an HTML 'form' element and exposes a binding path to inner tags for
binding. It puts the command object in the PageContext
so that the command object can
be accessed by inner tags. All the other tags in this library are nested tags of the
form
tag.
假设我们有一个名为 User
的域对象。它是一个包含诸如 firstName
和 lastName
之类的属性的 JavaBean。我们可以将其用作我们表单控制器的表单支持对象,该控制器返回 form.jsp
。以下示例展示了 form.jsp
的样子:
Assume that we have a domain object called User
. It is a JavaBean with properties
such as firstName
and lastName
. We can use it as the form-backing object of our
form controller, which returns form.jsp
. The following example shows what form.jsp
could
look like:
<form:form>
<table>
<tr>
<td>First Name:</td>
<td><form:input path="firstName"/></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Save Changes"/>
</td>
</tr>
</table>
</form:form>
firstName
和 lastName
值是从页控制器放置在 PageContext
中的命令对象中检索的。继续阅读以了解使用 form
标记时如何使用内部标记的更复杂的示例。
The firstName
and lastName
values are retrieved from the command object placed in
the PageContext
by the page controller. Keep reading to see more complex examples of
how inner tags are used with the form
tag.
以下清单显示了生成的 HTML,看上去像一个标准表单:
The following listing shows the generated HTML, which looks like a standard form:
<form method="POST">
<table>
<tr>
<td>First Name:</td>
<td><input name="firstName" type="text" value="Harry"/></td>
</tr>
<tr>
<td>Last Name:</td>
<td><input name="lastName" type="text" value="Potter"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Save Changes"/>
</td>
</tr>
</table>
</form>
前一个 JSP 假设表单支持对象的变量名为“command”。如果您已将表单支持对象放入模型中并使用了另一个名称(绝对是最佳实践),您就可以将表单绑定到命名的变量,如下面的示例所示:
The preceding JSP assumes that the variable name of the form-backing object is
command
. If you have put the form-backing object into the model under another name
(definitely a best practice), you can bind the form to the named variable, as the
following example shows:
<form:form modelAttribute="user">
<table>
<tr>
<td>First Name:</td>
<td><form:input path="firstName"/></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Save Changes"/>
</td>
</tr>
</table>
</form:form>
The input
Tag
此标签会默认渲染带有绑定值和`type='text'`的 HTML input`元素。有关此标签的示例,请参阅The Form Tag。你还可以使用 HTML5 特定的类型,例如`email
、tel
、`date`等。
This tag renders an HTML input
element with the bound value and type='text'
by default.
For an example of this tag, see The Form Tag. You can also use
HTML5-specific types, such as email
, tel
, date
, and others.
The checkbox
Tag
此标记呈现一个 type
设置为 checkbox
的 HTML input
标记。
This tag renders an HTML input
tag with the type
set to checkbox
.
假设我们的`User`有首选项,比如时事通讯订阅和爱好列表。以下示例展示了`Preferences`类:
Assume that our User
has preferences such as newsletter subscription and a list of
hobbies. The following example shows the Preferences
class:
-
Java
-
Kotlin
public class Preferences {
private boolean receiveNewsletter;
private String[] interests;
private String favouriteWord;
public boolean isReceiveNewsletter() {
return receiveNewsletter;
}
public void setReceiveNewsletter(boolean receiveNewsletter) {
this.receiveNewsletter = receiveNewsletter;
}
public String[] getInterests() {
return interests;
}
public void setInterests(String[] interests) {
this.interests = interests;
}
public String getFavouriteWord() {
return favouriteWord;
}
public void setFavouriteWord(String favouriteWord) {
this.favouriteWord = favouriteWord;
}
}
class Preferences(
var receiveNewsletter: Boolean,
var interests: StringArray,
var favouriteWord: String
)
相应的`form.jsp`然后可类似于以下内容:
The corresponding form.jsp
could then resemble the following:
<form:form>
<table>
<tr>
<td>Subscribe to newsletter?:</td>
<%-- Approach 1: Property is of type java.lang.Boolean --%>
<td><form:checkbox path="preferences.receiveNewsletter"/></td>
</tr>
<tr>
<td>Interests:</td>
<%-- Approach 2: Property is of an array or of type java.util.Collection --%>
<td>
Quidditch: <form:checkbox path="preferences.interests" value="Quidditch"/>
Herbology: <form:checkbox path="preferences.interests" value="Herbology"/>
Defence Against the Dark Arts: <form:checkbox path="preferences.interests" value="Defence Against the Dark Arts"/>
</td>
</tr>
<tr>
<td>Favourite Word:</td>
<%-- Approach 3: Property is of type java.lang.Object --%>
<td>
Magic: <form:checkbox path="preferences.favouriteWord" value="Magic"/>
</td>
</tr>
</table>
</form:form>
有 3 种方法来使用`checkbox`标签,这应该能满足你对复选框的所有需求。
There are three approaches to the checkbox
tag, which should meet all your checkbox needs.
-
Approach One: When the bound value is of type
java.lang.Boolean
, theinput(checkbox)
is marked aschecked
if the bound value istrue
. Thevalue
attribute corresponds to the resolved value of thesetValue(Object)
value property. -
Approach Two: When the bound value is of type
array
orjava.util.Collection
, theinput(checkbox)
is marked aschecked
if the configuredsetValue(Object)
value is present in the boundCollection
. -
Approach Three: For any other bound value type, the
input(checkbox)
is marked aschecked
if the configuredsetValue(Object)
is equal to the bound value.
请注意,无论使用哪种方法,所生成的 HTML 结构都是相同的。下面的 HTML 片段定义了一些复选框:
Note that, regardless of the approach, the same HTML structure is generated. The following HTML snippet defines some checkboxes:
<tr>
<td>Interests:</td>
<td>
Quidditch: <input name="preferences.interests" type="checkbox" value="Quidditch"/>
<input type="hidden" value="1" name="_preferences.interests"/>
Herbology: <input name="preferences.interests" type="checkbox" value="Herbology"/>
<input type="hidden" value="1" name="_preferences.interests"/>
Defence Against the Dark Arts: <input name="preferences.interests" type="checkbox" value="Defence Against the Dark Arts"/>
<input type="hidden" value="1" name="_preferences.interests"/>
</td>
</tr>
你可能没有想到会在每个复选框之后看到额外的隐藏字段。当 HTML 页面中某个复选框未勾选时,一旦提交表单,表单不会将其值作为 HTTP 请求参数的一部分发送到服务器,因此我们需要解决 HTML 此特性的问题,以便 Spring 表单数据绑定才能工作。checkbox`标签遵循现有的 Spring 惯例,包括一个带下划线前缀(`_
)的隐藏参数,用于每个复选框。通过执行此操作,你实际上是告诉 Spring “复选框在表单中可见,我希望我的对象(表单数据绑定到其上)反映复选框的状态,无论其状态如何.
”
You might not expect to see the additional hidden field after each checkbox.
When a checkbox in an HTML page is not checked, its value is not sent to the
server as part of the HTTP request parameters once the form is submitted, so we need a
workaround for this quirk in HTML for Spring form data binding to work. The
checkbox
tag follows the existing Spring convention of including a hidden parameter
prefixed by an underscore (_
) for each checkbox. By doing this, you are effectively
telling Spring that “the checkbox was visible in the form, and I want my object to
which the form data binds to reflect the state of the checkbox, no matter what.”
The checkboxes
Tag
此标签呈现出多个 HTML input`标签,其中`type`设置为`checkbox
。
This tag renders multiple HTML input
tags with the type
set to checkbox
.
本节基于前一个`checkbox`标签部分的示例。有时,你可能不喜欢在 JSP 页面中列出所有可能的爱好。你更愿意在运行时为可用选项提供一个列表并将其传递到标签中。这就是`checkboxes`标签的用途。你可以在`items`属性中传入包含可用选项的`Array`、List`或`Map
。通常,绑定属性是一个集合,以便它可以保存用户选择的多个值。以下示例显示了一个使用此标签的 JSP:
This section build on the example from the previous checkbox
tag section. Sometimes, you prefer
not to have to list all the possible hobbies in your JSP page. You would rather provide
a list at runtime of the available options and pass that in to the tag. That is the
purpose of the checkboxes
tag. You can pass in an Array
, a List
, or a Map
that contains
the available options in the items
property. Typically, the bound property is a
collection so that it can hold multiple values selected by the user. The following example
shows a JSP that uses this tag:
<form:form>
<table>
<tr>
<td>Interests:</td>
<td>
<%-- Property is of an array or of type java.util.Collection --%>
<form:checkboxes path="preferences.interests" items="${interestList}"/>
</td>
</tr>
</table>
</form:form>
此示例假定`interestList`是一个作为模型属性可用的`List`,其中包含要从中选择的字符串值。如果你使用`Map`,则会将映射条目键用作值,并将映射条目的值用作要显示的标签。你还可以使用自定义对象,其中你可以使用`itemValue`为值提供属性名,并使用`itemLabel`为标签提供属性名。
This example assumes that the interestList
is a List
available as a model attribute
that contains strings of the values to be selected from. If you use a Map
,
the map entry key is used as the value, and the map entry’s value is used as
the label to be displayed. You can also use a custom object where you can provide the
property names for the value by using itemValue
and the label by using itemLabel
.
The radiobutton
Tag
此标签呈现出一个 HTML input`元素,其中`type`设置为`radio
。
This tag renders an HTML input
element with the type
set to radio
.
典型的使用模式涉及多个绑定到同一属性但具有不同值的标签实例,如下例所示:
A typical usage pattern involves multiple tag instances bound to the same property but with different values, as the following example shows:
<tr>
<td>Sex:</td>
<td>
Male: <form:radiobutton path="sex" value="M"/> <br/>
Female: <form:radiobutton path="sex" value="F"/>
</td>
</tr>
The radiobuttons
Tag
此标签呈现出多个 HTML input`元素,其中`type`设置为`radio
。
This tag renders multiple HTML input
elements with the type
set to radio
.
与 xref:web/webmvc-view/mvc-jsp.adoc#mvc-view-jsp-formtaglib-checkboxestag[checkboxes
标签一样,你可能希望将可用选项作为运行时变量传递。对于此用法,你可以使用 radiobuttons
标签。你需要传递一个 Array
、List
或 Map
,其中包含 items
属性中的可用选项。如果你使用 Map
,则映射项的键用作值,而映射项的值用作显示的标签。你还可以使用一个自定义对象,通过使用 itemValue
提供值属性,通过使用 itemLabel
提供标签,如下例所示:
As with the checkboxes
tag, you might want to
pass in the available options as a runtime variable. For this usage, you can use the
radiobuttons
tag. You pass in an Array
, a List
, or a Map
that contains the
available options in the items
property. If you use a Map
, the map entry key is
used as the value and the map entry’s value are used as the label to be displayed.
You can also use a custom object where you can provide the property names for the value
by using itemValue
and the label by using itemLabel
, as the following example shows:
<tr>
<td>Sex:</td>
<td><form:radiobuttons path="sex" items="${sexOptions}"/></td>
</tr>
The password
Tag
此标签呈现出一个 HTML`input`标签,其中类型设置为`password`,带有绑定值。
This tag renders an HTML input
tag with the type set to password
with the bound value.
<tr>
<td>Password:</td>
<td>
<form:password path="password"/>
</td>
</tr>
请注意,默认情况下不显示密码值。如果你确实希望显示密码值,你可以将`showPassword`属性的值设置为`true`,如下例所示:
Note that, by default, the password value is not shown. If you do want the
password value to be shown, you can set the value of the showPassword
attribute to
true
, as the following example shows:
<tr>
<td>Password:</td>
<td>
<form:password path="password" value="^76525bvHGq" showPassword="true"/>
</td>
</tr>
The select
Tag
此标签呈现一个 HTML 'select' 元素。它支持与所选选项以及嵌套`option`和`options`标签的使用进行数据绑定。
This tag renders an HTML 'select' element. It supports data binding to the selected
option as well as the use of nested option
and options
tags.
假设`User`具有技能列表,则相应的 HTML 如下:
Assume that a User
has a list of skills. The corresponding HTML could be as follows:
<tr>
<td>Skills:</td>
<td><form:select path="skills" items="${skills}"/></td>
</tr>
如果`User`的技能是草药学,那么’Skills' 行的 HTML 源代码如下:
If the User’s
skill are in Herbology, the HTML source of the 'Skills' row could be
as follows:
<tr>
<td>Skills:</td>
<td>
<select name="skills" multiple="true">
<option value="Potions">Potions</option>
<option value="Herbology" selected="selected">Herbology</option>
<option value="Quidditch">Quidditch</option>
</select>
</td>
</tr>
The option
Tag
此标签呈现一个 HTML option`元素。它根据绑定的值设置`selected
。下面的 HTML 显示了它的典型输出:
This tag renders an HTML option
element. It sets selected
, based on the bound
value. The following HTML shows typical output for it:
<tr>
<td>House:</td>
<td>
<form:select path="house">
<form:option value="Gryffindor"/>
<form:option value="Hufflepuff"/>
<form:option value="Ravenclaw"/>
<form:option value="Slytherin"/>
</form:select>
</td>
</tr>
如果`User`所在的学院是格兰芬多,那么’House’行的 HTML 源代码如下:
If the User’s
house was in Gryffindor, the HTML source of the 'House' row would be
as follows:
<tr>
<td>House:</td>
<td>
<select name="house">
<option value="Gryffindor" selected="selected">Gryffindor</option> 1
<option value="Hufflepuff">Hufflepuff</option>
<option value="Ravenclaw">Ravenclaw</option>
<option value="Slytherin">Slytherin</option>
</select>
</td>
</tr>
1 | Note the addition of a selected attribute. |
The options
Tag
此标签会呈现一个 HTML option
元素列表。它会根据绑定值设置 selected
属性。以下 HTML 显示了它的典型输出:
This tag renders a list of HTML option
elements. It sets the selected
attribute,
based on the bound value. The following HTML shows typical output for it:
<tr>
<td>Country:</td>
<td>
<form:select path="country">
<form:option value="-" label="--Please Select"/>
<form:options items="${countryList}" itemValue="code" itemLabel="name"/>
</form:select>
</td>
</tr>
如果 User
住在英国,Country
行的 HTML 源会如下所示:
If the User
lived in the UK, the HTML source of the 'Country' row would be as follows:
<tr>
<td>Country:</td>
<td>
<select name="country">
<option value="-">--Please Select</option>
<option value="AT">Austria</option>
<option value="UK" selected="selected">United Kingdom</option> 1
<option value="US">United States</option>
</select>
</td>
</tr>
1 | Note the addition of a selected attribute. |
如上一个示例所示,option
标签和 options
标签结合使用会生成相同的标准 HTML,但能够让你显式地在JSP 中指定只供显示的值(它所属的位置),就像示例中的默认字符串:“-- 请选择”。
As the preceding example shows, the combined usage of an option
tag with the options
tag
generates the same standard HTML but lets you explicitly specify a value in the
JSP that is for display only (where it belongs), such as the default string in the
example: "-- Please Select".
items
属性通常会使用项目对象集合或数组来填充。如果指定了 itemValue
和 itemLabel
,则它们将指代这些项目对象的 bean 属性。否则,项目对象本身会被转换为字符串。或者,你可以指定一个项目的 Map
,在这种情况下,map 密钥会被解释为选项值,map 值对应于选项标签。如果也碰巧指定了 itemValue
或 itemLabel
(或两者),则项目值属性会应用于 map 密钥,项目标签属性会应用于 map 值。
The items
attribute is typically populated with a collection or array of item objects.
itemValue
and itemLabel
refer to bean properties of those item objects, if
specified. Otherwise, the item objects themselves are turned into strings. Alternatively,
you can specify a Map
of items, in which case the map keys are interpreted as option
values and the map values correspond to option labels. If itemValue
or itemLabel
(or both)
happen to be specified as well, the item value property applies to the map key, and
the item label property applies to the map value.
The textarea
Tag
此标签会呈现一个 HTML textarea
元素。以下 HTML 显示了它的典型输出:
This tag renders an HTML textarea
element. The following HTML shows typical output for it:
<tr>
<td>Notes:</td>
<td><form:textarea path="notes" rows="3" cols="20"/></td>
<td><form:errors path="notes"/></td>
</tr>
The hidden
Tag
此标签会呈现一个 HTML input
标签,其中 type
被设置为带绑定值 的 hidden
。要提交一个未绑定的隐藏值,请使用带 type
被设置为 hidden
的 HTML input
标签。以下 HTML 显示了它的典型输出:
This tag renders an HTML input
tag with the type
set to hidden
with the bound value. To submit
an unbound hidden value, use the HTML input
tag with the type
set to hidden
.
The following HTML shows typical output for it:
<form:hidden path="house"/>
如果我们选择将 house
值提交为一个隐藏值,则 HTML 如下所示:
If we choose to submit the house
value as a hidden one, the HTML would be as follows:
<input name="house" type="hidden" value="Gryffindor"/>
The errors
Tag
此标签会将字段错误呈现到一个 HTML span
元素中。它提供了对在控制器中创建的错误或与控制器关联的任何验证器创建的错误的访问。
This tag renders field errors in an HTML span
element. It provides access to the errors
created in your controller or those that were created by any validators associated with
your controller.
假设我们想要在提交表单后显示 firstName
和 lastName
字段的所有错误消息。我们有针对 User
类实例的验证器,名为 UserValidator
,如下面的示例所示:
Assume that we want to display all error messages for the firstName
and lastName
fields once we submit the form. We have a validator for instances of the User
class
called UserValidator
, as the following example shows:
-
Java
-
Kotlin
public class UserValidator implements Validator {
public boolean supports(Class candidate) {
return User.class.isAssignableFrom(candidate);
}
public void validate(Object obj, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "required", "Field is required.");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "required", "Field is required.");
}
}
class UserValidator : Validator {
override fun supports(candidate: Class<*>): Boolean {
return User::class.java.isAssignableFrom(candidate)
}
override fun validate(obj: Any, errors: Errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "required", "Field is required.")
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "required", "Field is required.")
}
}
form.jsp
可能如下所示:
The form.jsp
could be as follows:
<form:form>
<table>
<tr>
<td>First Name:</td>
<td><form:input path="firstName"/></td>
<%-- Show errors for firstName field --%>
<td><form:errors path="firstName"/></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName"/></td>
<%-- Show errors for lastName field --%>
<td><form:errors path="lastName"/></td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Save Changes"/>
</td>
</tr>
</table>
</form:form>
如果我们提交一个在 firstName
和 lastName
字段中带有空值的表单,则 HTML 如下所示:
If we submit a form with empty values in the firstName
and lastName
fields,
the HTML would be as follows:
<form method="POST">
<table>
<tr>
<td>First Name:</td>
<td><input name="firstName" type="text" value=""/></td>
<%-- Associated errors to firstName field displayed --%>
<td><span name="firstName.errors">Field is required.</span></td>
</tr>
<tr>
<td>Last Name:</td>
<td><input name="lastName" type="text" value=""/></td>
<%-- Associated errors to lastName field displayed --%>
<td><span name="lastName.errors">Field is required.</span></td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Save Changes"/>
</td>
</tr>
</table>
</form>
如果我们想要显示给定页面的整个错误列表该怎么办?下一个示例显示,errors
标签还支持一些基本的通配符功能。
What if we want to display the entire list of errors for a given page? The next example
shows that the errors
tag also supports some basic wildcard functionality.
-
path="*"
: Displays all errors. -
path="lastName"
: Displays all errors associated with thelastName
field. -
If
path
is omitted, only object errors are displayed.
以下示例显示了页面顶部的一个错误列表,然后在字段旁边是针对特定字段的错误:
The following example displays a list of errors at the top of the page, followed by field-specific errors next to the fields:
<form:form>
<form:errors path="*" cssClass="errorBox"/>
<table>
<tr>
<td>First Name:</td>
<td><form:input path="firstName"/></td>
<td><form:errors path="firstName"/></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName"/></td>
<td><form:errors path="lastName"/></td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Save Changes"/>
</td>
</tr>
</table>
</form:form>
HTML 如下所示:
The HTML would be as follows:
<form method="POST">
<span name="*.errors" class="errorBox">Field is required.<br/>Field is required.</span>
<table>
<tr>
<td>First Name:</td>
<td><input name="firstName" type="text" value=""/></td>
<td><span name="firstName.errors">Field is required.</span></td>
</tr>
<tr>
<td>Last Name:</td>
<td><input name="lastName" type="text" value=""/></td>
<td><span name="lastName.errors">Field is required.</span></td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Save Changes"/>
</td>
</tr>
</table>
</form>
`spring-form.tld`标记库描述符(TLD)包含在 `spring-webmvc.jar`中。要获得各个标记的全面参考,请浏览 API 参考 或查看标记库描述。
The spring-form.tld
tag library descriptor (TLD) is included in the spring-webmvc.jar
.
For a comprehensive reference on individual tags, browse the
API reference
or see the tag library description.
HTTP Method Conversion
REST 的一个关键原则是使用“统一接口
”。这意味着所有资源 (URL) 可以使用相同的四种 HTTP 方法进行操作:GET、PUT、POST 和 DELETE。对于每种方法,HTTP 规范都定义了确切的语义。例如,GET 始终应该是安全的操作,这意味着它没有任何副作用,而 PUT 或 DELETE 应该是幂等的,这意味着你可以一遍又一遍地重复这些操作,但最终结果应该相同。虽然 HTTP 定义了这四种方法,但 HTML 仅支持两种:GET 和 POST。幸运的是,有两种可能的解决方法:你可以使用 JavaScript 来执行 PUT 或 DELETE,也可以执行一个 POST,其中“真实
”方法作为一个附加参数(建模为 HTML 表单中的隐藏输入字段)。Spring 的 HiddenHttpMethodFilter
使用后一种技巧。此过滤器是一个普通的 Servlet 过滤器,因此它可用于与任何 Web 框架(不仅仅是 Spring MVC)结合使用。将此过滤器添加到你的 web.xml 中,带有一个隐藏的 method
参数的 POST 就转换为对应的 HTTP 方法请求。
A key principle of REST is the use of the “Uniform Interface”. This means that all
resources (URLs) can be manipulated by using the same four HTTP methods: GET, PUT, POST,
and DELETE. For each method, the HTTP specification defines the exact semantics. For
instance, a GET should always be a safe operation, meaning that it has no side effects,
and a PUT or DELETE should be idempotent, meaning that you can repeat these operations
over and over again, but the end result should be the same. While HTTP defines these
four methods, HTML only supports two: GET and POST. Fortunately, there are two possible
workarounds: you can either use JavaScript to do your PUT or DELETE, or you can do a POST
with the “real” method as an additional parameter (modeled as a hidden input field in an
HTML form). Spring’s HiddenHttpMethodFilter
uses this latter trick. This
filter is a plain Servlet filter and, therefore, it can be used in combination with any
web framework (not just Spring MVC). Add this filter to your web.xml, and a POST
with a hidden method
parameter is converted into the corresponding HTTP method
request.
为了支持 HTTP 方法转换,Spring MVC 表单标签已被更新,以支持设置 HTTP 方法。例如,以下片段来自 Pet Clinic 样本:
To support HTTP method conversion, the Spring MVC form tag was updated to support setting the HTTP method. For example, the following snippet comes from the Pet Clinic sample:
<form:form method="delete">
<p class="submit"><input type="submit" value="Delete Pet"/></p>
</form:form>
上一个示例执行了一个 HTTP POST,其中“真实
”DELETE 方法隐藏在一个请求参数后面。它由 web.xml 中定义的 HiddenHttpMethodFilter
拾取,如下一个示例所示:
The preceding example performs an HTTP POST, with the “real” DELETE method hidden behind
a request parameter. It is picked up by the HiddenHttpMethodFilter
, which is defined in
web.xml, as the following example shows:
<filter>
<filter-name>httpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpMethodFilter</filter-name>
<servlet-name>petclinic</servlet-name>
</filter-mapping>
以下示例显示了对应的 @Controller
方法:
The following example shows the corresponding @Controller
method:
-
Java
-
Kotlin
@RequestMapping(method = RequestMethod.DELETE)
public String deletePet(@PathVariable int ownerId, @PathVariable int petId) {
this.clinic.deletePet(petId);
return "redirect:/owners/" + ownerId;
}
@RequestMapping(method = [RequestMethod.DELETE])
fun deletePet(@PathVariable ownerId: Int, @PathVariable petId: Int): String {
clinic.deletePet(petId)
return "redirect:/owners/$ownerId"
}
HTML5 Tags
Spring 表单标签库允许输入动态属性,这意味着您可以输入任何特定于 HTML5 的属性。
The Spring form tag library allows entering dynamic attributes, which means you can enter any HTML5 specific attributes.
表单 input
标签支持输入 text
之外的 type 属性。此操作的目的是允许呈现特定的新 HTML5 输入类型,例如 email
、date
、range
及其他类型。请注意,输入 type='text'
不是必需的,因为 text
为默认类型。
The form input
tag supports entering a type attribute other than text
. This is
intended to allow rendering new HTML5 specific input types, such as email
, date
,
range
, and others. Note that entering type='text'
is not required, since text
is the default type.