Skip to content

JSP 与 JSTL

Spring Framework 内置了对 JSP (JavaServer Pages) 和 JSTL (JSP Standard Tag Library) 的深度集成。

视图解析器 (View Resolvers)

在开发 JSP 时,通常会声明一个 InternalResourceViewResolver Bean。

InternalResourceViewResolver 可用于分发到任何 Servlet 资源,但特别适用于 JSP。作为最佳实践,我们强烈建议将 JSP 文件放在 WEB-INF 目录下的子目录中,这样客户端就无法直接访问它们。

以下配置展示了如何注册一个 JSP 视图解析器,默认视图名称前缀为 "/WEB-INF/",默认后缀为 ".jsp"

java
@Configuration
public class WebConfiguration implements WebMvcConfigurer {

	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		registry.jsp();
	}
}
kotlin
@Configuration
class WebConfiguration : WebMvcConfigurer {

	override fun configureViewResolvers(registry: ViewResolverRegistry) {
		registry.jsp()
	}
}
xml
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:mvc="http://www.springframework.org/schema/mvc"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="
			http://www.springframework.org/schema/beans
			https://www.springframework.org/schema/beans/spring-beans.xsd
			http://www.springframework.org/schema/mvc
			https://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<mvc:view-resolvers>
		<mvc:jsp/>
	</mvc:view-resolvers>

</beans>

提示

你可以指定自定义的前缀和后缀。

JSPs 还是 JSTL

在使用 JSP 标准标签库 (JSTL) 时,必须使用特殊的视图类 JstlView。因为 JSTL 需要一些准备工作(例如国际化 I18N 功能)才能正常运行。

Spring 的 JSP 标签库

Spring 提供了请求参数到命令对象(Command Object)的数据绑定。为了简化在 JSP 页面中结合数据绑定功能的开发,Spring 提供了一些标签。所有 Spring 标签都具有 HTML 转义功能,可以启用或禁用字符转义。

spring.tld 标签库描述符(TLD)包含在 spring-webmvc.jar 中。

Spring 表单标签库

从 2.0 版本开始,Spring 提供了一套完善的、支持数据绑定的标签,用于在 JSP 和 Spring Web MVC 环境下处理表单元素。每个标签都支持其对应 HTML 标签的属性,使开发体验直观且熟悉。标签生成的 HTML 符合 HTML 4.01/XHTML 1.0 规范。

与传统的表单/输入标签库不同,Spring 的表单标签库与 Spring Web MVC 深度集成,使标签能够访问控制器处理的命令对象(Command Object)和参考数据。

配置

表单标签库捆绑在 spring-webmvc.jar 中。库描述符名为 spring-form.tld

要使用此库中的标签,请在 JSP 页面顶部添加以下指令:

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

其中 form 是你希望用于该库标签的名称前缀。

Form 标签

该标签渲染一个 HTML 'form' 元素,并向内部标签暴露绑定路径。它将命令对象放入 PageContext 中,以便内部标签可以访问。本库中的所有其他标签都是 form 标签的嵌套标签。

假设我们有一个名为 User 的领域对象,它是一个具有 firstNamelastName 属性的 JavaBean。我们可以将其作为返回 form.jsp 的表单控制器的表单后援对象(Form-backing object)。

xml
<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 的命令对象中检索的。

生成的 HTML 如下所示:

xml
<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。如果你将对象以其他名称放入模型中(最佳实践),可以将表单绑定到该命名变量:

xml
<form:form modelAttribute="user">
    <!-- ... -->
</form:form>

input 标签

该标签渲染一个 HTML input 元素,默认值为绑定值,type 默认为 'text'。你也可以使用 HTML5 特有的类型,如 emailteldate 等。

checkbox 标签

该标签渲染一个 typecheckbox 的 HTML input 标签。

处理 checkbox 标签有三种方式:

  1. 方式一:布尔值 当绑定值类型为 java.lang.Boolean 时,如果值为 true,则标记为 checked
  2. 方式二:数组或集合 当绑定值类型为数组或 java.util.Collection 时,如果配置的 value 存在于绑定的集合中,则标记为 checked
  3. 方式三:其他对象类型 对于任何其他绑定值类型,如果配置的 value 等于绑定值,则标记为 checked

HTML 机制处理 (下划线前缀): 你可能会在生成的 HTML 中看到额外的隐藏字段:

xml
<input name="interests" type="checkbox" value="Quidditch"/>
<input type="hidden" value="1" name="_interests"/>

当 HTML 中的复选框未选中时,提交表单时该值不会发送到服务器。这是 HTML 的一个特殊行为。Spring 的辅助机制通过包含一个带有下划线 (_) 前缀的隐藏参数,强制告知 Spring:“这个复选框在表单中是可见的,我希望绑定后的对象能反映其真实状态(即使是未选中)”。

checkboxes 标签

该标签用于根据运行时的选项列表动态渲染多个 checkbox

xml
<form:checkboxes path="preferences.interests" items="${interestList}"/>

你可以传入 ArrayListMap。如果使用 Map,Key 作为 value,Value 作为 Label。

radiobutton 标签

该标签渲染一个 typeradio 的 HTML input 元素。典型用法是多个标签绑定到同一属性但具有不同的值。

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

radiobuttons 标签

类似于 checkboxes,用于动态渲染一组单选按钮。

password 标签

渲染一个 typepassword 的 HTML input 标签。出于安全考虑,默认不显示密码值。如果需要显示,请设置 showPassword="true"

select 标签

渲染一个 HTML 'select' 元素。支持嵌套的 optionoptions 标签。

xml
<form:select path="skills" items="${skills}"/>

option 标签

渲染单个 HTML option。它根据绑定值自动设置 selected 属性。

xml
<form:select path="house">
	<form:option value="Gryffindor"/>
	<form:option value="Hufflepuff"/>
</form:select>

options 标签

渲染一系列 HTML option 元素。

xml
<form:select path="country">
	<form:option value="-" label="--Please Select"/>
	<form:options items="${countryList}" itemValue="code" itemLabel="name"/>
</form:select>

textarea 标签

渲染一个 HTML textarea 元素。

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

hidden 标签

渲染一个 typehidden 的 HTML input 标签。

xml
<form:hidden path="house"/>

errors 标签

该标签在 HTML span 元素中渲染字段错误。它允许访问控制器或验证器(Validator)创建的错误。

通配符支持

  • path="*": 显示所有错误。
  • path="lastName": 仅显示与 lastName 字段关联的错误。
  • 省略 path: 仅显示对象级别的错误(Global Errors)。
xml
<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>
	</table>
</form:form>

HTTP 方法转换 (REST 支持)

REST 的原则之一是使用统一接口。HTML 表单原生仅支持 GETPOST

Spring 提供了 HiddenHttpMethodFilter 过滤器。添加此过滤器后,一个带有隐藏 _method 参数的 POST 请求将被转换为相应的 HTTP 方法请求(如 PUTDELETE)。

在 Spring MVC 表单标签中,你可以直接设置 method

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

这会在后台执行以下操作:

  1. 发送一个 POST 请求。
  2. 自动添加一个隐藏的 method 参数,值为 delete
  3. HiddenHttpMethodFilter 拦截并转换。

HTML5 标签

Spring 表单标签库允许输入动态属性,这意味着你可以输入任何 HTML5 特有的属性。

input 标签支持非 texttype 属性,例如 emaildaterange 等。


补充教学

1. 为什么 InternalResourceViewResolver 通常要配置前缀和后缀?

为了简化控制器中的逻辑。如果你配置了前缀 /WEB-INF/jsp/ 和后缀 .jsp,那么你的控制器只需返回 "userForm",解析器就会自动拼装成 /WEB-INF/jsp/userForm.jsp。这不仅减少了代码冗余,还方便了以后统一更改视图文件的存放路径。

2. JSP 转义安全

默认情况下,Spring 表单标签会对值进行 HTML 转义,这能有效防止反射型 XSS 攻击。如果你确实需要渲染 HTML 源码(例如富文本编辑器提交的内容),可以在标签中设置 htmlEscape="false"

3. JSPs 在现代开发中的地位

虽然 JSP 在存量项目中依然随处可见,但对于新项目,Spring 官方和社区更推荐使用 Thymeleaf

  • Thymeleaf 的优势:它是“天然模板”,直接双击 HTML 文件就能在浏览器中看到样貌(静态预览),而 JSP 必须在容器中运行。
  • JSP 的局限:它本质上会被编译成 Java Servlet 类,这在现代基于 Fat JAR(Spring Boot 默认模式)的部署中会带来一些复杂的路径兼容问题。

Based on Spring Framework.