此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0spring-doc.cadn.net.cn

JSP 和 JSTL

Spring Framework 具有用于将 Spring MVC 与 JSP 和 JSTL 一起使用的内置集成。spring-doc.cadn.net.cn

View 解析程序

使用 JSP 进行开发时,通常会声明InternalResourceViewResolver豆。spring-doc.cadn.net.cn

InternalResourceViewResolver可用于分派到任何 Servlet 资源,但在 特别是对于 JSP 来说。作为最佳实践,我们强烈建议将 JSP 文件放在 在'WEB-INF'目录中,因此客户端无法直接访问。spring-doc.cadn.net.cn

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

JSP 与 JSTL

使用 JSP 标准标记库 (JSTL) 时,必须使用特殊的视图类JstlView,因为 JSTL 需要先做一些准备,然后才能使用 I18N 功能 工作。spring-doc.cadn.net.cn

Spring 的 JSP 标记库

Spring 提供请求参数到命令对象的数据绑定,如 前面的章节。促进 JSP 页面的开发 data binding 功能,Spring 提供了一些标签,使事情变得更加容易。都 Spring 标签具有 HTML 转义功能,用于启用或禁用字符转义。spring-doc.cadn.net.cn

spring.tld标记库描述符 (TLD) 包含在spring-webmvc.jar. 有关各个标记的全面参考,请浏览 API 参考或查看标记库描述。spring-doc.cadn.net.cn

Spring 的表单标记库

从版本 2.0 开始, Spring 提供了一组全面的数据绑定感知标签,用于 在使用 JSP 和 Spring Web MVC 时处理表单元素。每个标签都支持 其对应的 HTML 标签对应的属性集,使标签 熟悉且直观易用。标记生成的 HTML 符合 HTML 4.01/XHTML 1.0 标准。spring-doc.cadn.net.cn

与其他表单/输入标记库不同, Spring 的表单标记库与 Spring Web MVC,为标签提供对命令对象和引用数据的 控制器处理。正如我们在以下示例中所示,表单标记使 JSP 更易于开发、阅读和维护。spring-doc.cadn.net.cn

我们将浏览 form 标记,并查看如何使用每个标记的示例。我们有 包含生成的 HTML 片段,其中某些标记需要进一步注释。spring-doc.cadn.net.cn

配置

表单标记库捆绑在spring-webmvc.jar.库描述符为 叫spring-form.tld.spring-doc.cadn.net.cn

要使用此库中的标记,请将以下指令添加到 JSP 的顶部 页:spring-doc.cadn.net.cn

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

哪里form是要用于此库中的标签的标签名称前缀。spring-doc.cadn.net.cn

表单标签

此标签呈现一个 HTML“form”元素,并公开一个指向内部标签的绑定路径 捆绑。它将命令对象放在PageContext以便 Command 对象可以 通过 inner 标签访问。此库中的所有其他标签都是form标记。spring-doc.cadn.net.cn

假设我们有一个名为User.它是一个具有属性 如firstNamelastName.我们可以将其用作 form 控制器,该控制器返回form.jsp.以下示例显示了form.jsp能 肖:spring-doc.cadn.net.cn

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

firstNamelastName值是从放置在 这PageContext通过页面控制器。继续阅读以查看更复杂的示例 如何将 inner 标记与form标记。spring-doc.cadn.net.cn

下面的清单显示了生成的 HTML,它看起来像一个标准表单:spring-doc.cadn.net.cn

<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.如果您已将 form-backing 对象以其他名称放入模型中 (绝对是最佳实践),您可以将表单绑定到命名变量,因为 以下示例显示:spring-doc.cadn.net.cn

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

input标记

此标签呈现 HTMLinput元素,其绑定值和type='text'默认情况下。 有关此标记的示例,请参阅 Form 标记。您还可以使用 HTML5 特定的类型,例如email,tel,date等。spring-doc.cadn.net.cn

checkbox标记

此标签呈现 HTMLinput标签与type设置为checkbox.spring-doc.cadn.net.cn

假设我们的User具有首选项,例如新闻通讯订阅和 爱好。以下示例显示了Preferences类:spring-doc.cadn.net.cn

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可能类似于以下内容:spring-doc.cadn.net.cn

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

有三种方法可以实现checkbox标签,它应该可以满足您的所有复选框需求。spring-doc.cadn.net.cn

  • 方法一:当绑定值为java.lang.Booleaninput(checkbox)标记为checked如果 bound 值为true.这value属性对应于setValue(Object)value 属性。spring-doc.cadn.net.cn

  • 方法二:当绑定值为arrayjava.util.Collectioninput(checkbox)标记为checked如果配置的setValue(Object)value 为 存在于 Bound 中Collection.spring-doc.cadn.net.cn

  • 方法三:对于任何其他绑定值类型,input(checkbox)标记为checked如果配置的setValue(Object)等于 bound 值。spring-doc.cadn.net.cn

请注意,无论采用哪种方法,都会生成相同的 HTML 结构。以下内容 HTML 代码段定义了一些复选框:spring-doc.cadn.net.cn

<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 页面中的复选框,则其值不会发送到 server 作为 HTTP 请求参数的一部分,因此我们需要一个 HTML 中此怪癖的解决方法,以便 Spring 表单数据绑定正常工作。这checkbox标签遵循现有的 Spring 约定,即包含一个隐藏的参数 为每个复选框添加下划线 () 前缀。通过这样做,您可以有效地 告诉 Spring “复选框在表单中可见,我希望我的对象 无论如何,表单数据都会绑定以反映复选框的状态。_spring-doc.cadn.net.cn

checkboxes标记

此标签呈现多个 HTMLinput标签中带有type设置为checkbox.spring-doc.cadn.net.cn

本节基于前面的示例。checkboxtag 部分。有时,您更喜欢 不必在 JSP 页中列出所有可能的爱好。您宁愿提供 一个可用选项的列表,并将其传递给标签。那就是 目的checkboxes标记。您可以传入Array一个ListMap包含 的items财产。通常,绑定属性是 集合,以便它可以保存用户选择的多个值。以下示例 显示了使用此标记的 JSP:spring-doc.cadn.net.cn

<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可用作 Model 属性 ,其中包含要从中选择的值的字符串。如果您使用Map, 映射条目键用作值,映射条目的值用作 要显示的标签。您还可以使用自定义对象,您可以在其中提供 value 的属性名称itemValue和标签itemLabel.spring-doc.cadn.net.cn

radiobutton标记

此标签呈现 HTMLinput元素替换为type设置为radio.spring-doc.cadn.net.cn

典型的使用模式涉及绑定到同一属性的多个标记实例 但具有不同的值,如下例所示:spring-doc.cadn.net.cn

<tr>
	<td>Sex:</td>
	<td>
		Male: <form:radiobutton path="sex" value="M"/> <br/>
		Female: <form:radiobutton path="sex" value="F"/>
	</td>
</tr>

radiobuttons标记

此标签呈现多个 HTMLinput元素替换为type设置为radio.spring-doc.cadn.net.cn

checkboxes标记,您可能希望 将 available options 作为运行时变量传入。对于此用法,您可以使用radiobuttons标记。您传入一个Array一个ListMap,其中包含 的items财产。如果您使用Map,则映射入口键为 used as the value 和 map entry 的值用作要显示的标签。 您还可以使用自定义对象,您可以在其中为值提供属性名称 通过使用itemValue和标签itemLabel,如下例所示:spring-doc.cadn.net.cn

<tr>
	<td>Sex:</td>
	<td><form:radiobuttons path="sex" items="${sexOptions}"/></td>
</tr>

password标记

此标签呈现 HTMLinput标记中,并将类型设置为password替换为绑定值。spring-doc.cadn.net.cn

<tr>
	<td>Password:</td>
	<td>
		<form:password path="password"/>
	</td>
</tr>

请注意,默认情况下,不会显示 password 值。如果您确实希望使用 password 值,则可以设置showPassword属性设置为true,如下例所示:spring-doc.cadn.net.cn

<tr>
	<td>Password:</td>
	<td>
		<form:password path="password" value="^76525bvHGq" showPassword="true"/>
	</td>
</tr>

select标记

此标签呈现 HTML 'select' 元素。它支持将数据绑定到选定的 选项以及使用嵌套的optionoptions标签。spring-doc.cadn.net.cn

假设User有一个技能列表。相应的 HTML 可能如下所示:spring-doc.cadn.net.cn

<tr>
	<td>Skills:</td>
	<td><form:select path="skills" items="${skills}"/></td>
</tr>

如果User’sskill 在 Herbology 中,则 'Skills' 行的 HTML 源可以是 如下:spring-doc.cadn.net.cn

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

option标记

此标签呈现 HTMLoption元素。它设置selected,基于边界 价值。以下 HTML 显示了它的典型输出:spring-doc.cadn.net.cn

<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’shouse 位于格兰芬多中,则 'House' 行的 HTML 源将为 如下:spring-doc.cadn.net.cn

<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 请注意,添加了selected属性。

options标记

此标签呈现 HTMLoption元素。它将selected属性 基于 Bound 值。以下 HTML 显示了它的典型输出:spring-doc.cadn.net.cn

<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 源如下所示:spring-doc.cadn.net.cn

<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 请注意,添加了selected属性。

如前面的示例所示,option标签与options标记 生成相同的标准 HTML,但允许您在 仅用于显示(属于它的位置)的 JSP,例如 示例:“-- 请选择”。spring-doc.cadn.net.cn

items属性通常填充 item 对象的集合或数组。itemValueitemLabel引用这些 Item 对象的 bean 属性,如果 指定。否则,item 对象本身将转换为字符串。或者 您可以指定Mapof items,在这种情况下,映射键被解释为 option values 和 map 值对应于选项标签。如果itemValueitemLabel(或两者兼而有之) 恰好也被指定,则 item 值属性适用于 map 键,并且 item label 属性适用于 map 值。spring-doc.cadn.net.cn

textarea标记

此标签呈现 HTMLtextarea元素。以下 HTML 显示了它的典型输出:spring-doc.cadn.net.cn

<tr>
	<td>Notes:</td>
	<td><form:textarea path="notes" rows="3" cols="20"/></td>
	<td><form:errors path="notes"/></td>
</tr>

hidden标记

此标签呈现 HTMLinput标签与type设置为hidden替换为绑定值。提交 未绑定的隐藏值,请使用 HTMLinput标签与type设置为hidden. 以下 HTML 显示了它的典型输出:spring-doc.cadn.net.cn

<form:hidden path="house"/>

如果我们选择提交house值设置为隐藏值,则 HTML 将如下所示:spring-doc.cadn.net.cn

<input name="house" type="hidden" value="Gryffindor"/>

errors标记

此标签在 HTML 中呈现字段错误span元素。它提供对错误的访问 在您的控制器中创建的,或者是由与 您的控制器。spring-doc.cadn.net.cn

假设我们想要显示firstNamelastName字段。我们有一个 Validator 用于User类 叫UserValidator,如下例所示:spring-doc.cadn.net.cn

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可能如下所示:spring-doc.cadn.net.cn

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

如果我们提交的表单在firstNamelastName领域 HTML 将如下所示:spring-doc.cadn.net.cn

<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标签还支持一些基本的通配符功能。spring-doc.cadn.net.cn

以下示例在页面顶部显示错误列表,后跟 字段旁边的特定于字段的错误:spring-doc.cadn.net.cn

<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 将如下所示:spring-doc.cadn.net.cn

<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 参考或查看标记库描述。spring-doc.cadn.net.cn

HTTP 方法转换

REST 的一个关键原则是使用“统一接口”。这意味着所有 可以使用相同的四种 HTTP 方法作资源 (URL):GET、PUT、POST、 和 DELETE 的 DELETE 命令。对于每种方法,HTTP 规范定义了确切的语义。为 例如,GET 应该始终是一个安全的作,这意味着它没有副作用, PUT 或 DELETE 应该是幂等的,这意味着您可以重复这些作 一遍又一遍,但最终结果应该是相同的。虽然 HTTP 定义了这些 四种方法,HTML 只支持两种:GET 和 POST。幸运的是,有两种可能 解决方法:您可以使用 JavaScript 执行 PUT 或 DELETE,也可以执行 POST 使用“real”方法作为附加参数(在 HTML 表单)。Spring的HiddenHttpMethodFilter使用后一个技巧。这 filter 是一个普通的 Servlet 过滤器,因此,它可以与任何 Web 框架(不仅仅是 Spring MVC)。将此过滤器添加到您的 web.xml,然后 POST 带有隐藏的methodparameter 转换为对应的 HTTP 方法 请求。spring-doc.cadn.net.cn

为了支持 HTTP 方法转换,更新了 Spring MVC 表单标记以支持设置 HTTP 方法。例如,以下代码片段来自 Pet Clinic 示例:spring-doc.cadn.net.cn

<form:form method="delete">
	<p class="submit"><input type="submit" value="Delete Pet"/></p>
</form:form>

前面的示例执行 HTTP POST,其中隐藏了 “真正的” DELETE 方法 请求参数。它由HiddenHttpMethodFilter,它在 web.xml,如下例所示:spring-doc.cadn.net.cn

<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方法:spring-doc.cadn.net.cn

@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 标签

Spring 表单标签库允许输入动态属性,这意味着您可以 输入任何特定于 HTML5 的属性。spring-doc.cadn.net.cn

表单input标签支持输入 type 属性,而不是text.这是 旨在允许呈现新的 HTML5 特定输入类型,例如email,date,range等。请注意,输入type='text'不是必需的,因为text是默认类型。spring-doc.cadn.net.cn