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"。
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp();
}
}@Configuration
class WebConfiguration : WebMvcConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.jsp()
}
}<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 页面顶部添加以下指令:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>其中 form 是你希望用于该库标签的名称前缀。
Form 标签
该标签渲染一个 HTML 'form' 元素,并向内部标签暴露绑定路径。它将命令对象放入 PageContext 中,以便内部标签可以访问。本库中的所有其他标签都是 form 标签的嵌套标签。
假设我们有一个名为 User 的领域对象,它是一个具有 firstName 和 lastName 属性的 JavaBean。我们可以将其作为返回 form.jsp 的表单控制器的表单后援对象(Form-backing object)。
<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 的命令对象中检索的。
生成的 HTML 如下所示:
<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:form modelAttribute="user">
<!-- ... -->
</form:form>input 标签
该标签渲染一个 HTML input 元素,默认值为绑定值,type 默认为 'text'。你也可以使用 HTML5 特有的类型,如 email、tel、date 等。
checkbox 标签
该标签渲染一个 type 为 checkbox 的 HTML input 标签。
处理 checkbox 标签有三种方式:
- 方式一:布尔值 当绑定值类型为
java.lang.Boolean时,如果值为true,则标记为checked。 - 方式二:数组或集合 当绑定值类型为数组或
java.util.Collection时,如果配置的value存在于绑定的集合中,则标记为checked。 - 方式三:其他对象类型 对于任何其他绑定值类型,如果配置的
value等于绑定值,则标记为checked。
HTML 机制处理 (下划线前缀): 你可能会在生成的 HTML 中看到额外的隐藏字段:
<input name="interests" type="checkbox" value="Quidditch"/>
<input type="hidden" value="1" name="_interests"/>当 HTML 中的复选框未选中时,提交表单时该值不会发送到服务器。这是 HTML 的一个特殊行为。Spring 的辅助机制通过包含一个带有下划线 (_) 前缀的隐藏参数,强制告知 Spring:“这个复选框在表单中是可见的,我希望绑定后的对象能反映其真实状态(即使是未选中)”。
checkboxes 标签
该标签用于根据运行时的选项列表动态渲染多个 checkbox。
<form:checkboxes path="preferences.interests" items="${interestList}"/>你可以传入 Array、List 或 Map。如果使用 Map,Key 作为 value,Value 作为 Label。
radiobutton 标签
该标签渲染一个 type 为 radio 的 HTML input 元素。典型用法是多个标签绑定到同一属性但具有不同的值。
Male: <form:radiobutton path="sex" value="M"/>
Female: <form:radiobutton path="sex" value="F"/>radiobuttons 标签
类似于 checkboxes,用于动态渲染一组单选按钮。
password 标签
渲染一个 type 为 password 的 HTML input 标签。出于安全考虑,默认不显示密码值。如果需要显示,请设置 showPassword="true"。
select 标签
渲染一个 HTML 'select' 元素。支持嵌套的 option 和 options 标签。
<form:select path="skills" items="${skills}"/>option 标签
渲染单个 HTML option。它根据绑定值自动设置 selected 属性。
<form:select path="house">
<form:option value="Gryffindor"/>
<form:option value="Hufflepuff"/>
</form:select>options 标签
渲染一系列 HTML option 元素。
<form:select path="country">
<form:option value="-" label="--Please Select"/>
<form:options items="${countryList}" itemValue="code" itemLabel="name"/>
</form:select>textarea 标签
渲染一个 HTML textarea 元素。
<form:textarea path="notes" rows="3" cols="20"/>hidden 标签
渲染一个 type 为 hidden 的 HTML input 标签。
<form:hidden path="house"/>errors 标签
该标签在 HTML span 元素中渲染字段错误。它允许访问控制器或验证器(Validator)创建的错误。
通配符支持:
path="*": 显示所有错误。path="lastName": 仅显示与lastName字段关联的错误。- 省略
path: 仅显示对象级别的错误(Global Errors)。
<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 表单原生仅支持 GET 和 POST。
Spring 提供了 HiddenHttpMethodFilter 过滤器。添加此过滤器后,一个带有隐藏 _method 参数的 POST 请求将被转换为相应的 HTTP 方法请求(如 PUT 或 DELETE)。
在 Spring MVC 表单标签中,你可以直接设置 method:
<form:form method="delete">
<input type="submit" value="Delete Pet"/>
</form:form>这会在后台执行以下操作:
- 发送一个
POST请求。 - 自动添加一个隐藏的
method参数,值为delete。 - 由
HiddenHttpMethodFilter拦截并转换。
HTML5 标签
Spring 表单标签库允许输入动态属性,这意味着你可以输入任何 HTML5 特有的属性。
input 标签支持非 text 的 type 属性,例如 email、date、range 等。
补充教学
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 默认模式)的部署中会带来一些复杂的路径兼容问题。