20. Spring JavaScript 快速参考
这spring-js-resources
module 是一个旧模块,不再推荐使用,但仍作为可选模块提供以实现向后兼容性。
它的最初目标是提供一个客户端编程模型,用于通过行为和 Ajax 远程处理逐步增强 Web 页面。
示例存储库中演示了 Spring JS API 的使用。
20.1. 提供 Javascript 资源
Spring Framework 提供了一种提供静态资源的机制。
请参阅 Spring Framework 文档)。
使用新的<mvc:resources>
元素、资源请求 (.js
,.css
等)由DispatcherSevlet
.
以下示例显示了如何在 XML 中配置模块(Java 配置也可用):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<mvc:annotation-driven/>
<mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/web-resources/" />
...
</beans>
这会映射/resources
到/META-INF/web-resources
在 Classpath 上。
这就是捆绑 Spring JavaScript 资源的地方。
但是,您可以修改上述配置中的 location 属性,以便从相对于 Classpath 或 Web 应用程序的任何位置提供资源。
请注意,完整的资源 URL 取决于您的DispatcherServlet
已映射。
在mvc-booking
sample,我们选择使用默认的 servlet 映射 () 进行映射,如下所示:/
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
这意味着要加载的完整 URLSpring.js
是/myapp/resources/spring/Spring.js
.
如果您的DispatcherServlet
映射到/main/*
,则完整 URL 为/myapp/main/resources/spring/Spring.js
.
使用默认 Servlet 映射时,还应将以下配置添加到 Spring MVC 配置中,以确保将 Spring MVC 映射未处理的任何资源请求委托回 Servlet 容器:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
...
<mvc:default-servlet-handler />
</beans>
20.2. 在页面中包含 Spring Javascript
Spring JS 的设计使得可以为任何流行的 Javascript 工具包构建其 API 的实现。 Spring.js 的初始实现建立在 Dojo Toolkit 之上。
在页面中使用 Spring Javascript 需要像往常一样包含底层工具包,Spring.js
base 接口文件和Spring-(library implementation).js
文件。
例如,以下内容Spring.js包括使用ResourceServlet
:
<script type="text/javascript" src="<c:url value="/resources/dojo/dojo.js" />"> </script>
<script type="text/javascript" src="<c:url value="/resources/spring/Spring.js" />"> </script>
<script type="text/javascript" src="<c:url value="/resources/spring/Spring-Dojo.js" />"> </script>
使用基础库的 Widget 系统时,您还必须(通常)包含一些 CSS 资源以获得所需的外观。
对于booking-mvc
reference 应用程序、Dojo 的tundra.css
包括:
<link type="text/css" rel="stylesheet" href="<c:url value="/resources/dijit/themes/tundra/tundra.css" />" />
20.3. Spring Javascript 装饰
Spring Javascript 中的一个中心概念是将装饰应用于现有 DOM 节点的概念。
此技术用于逐步增强 Web 页面,以便该页面在功能较弱的浏览器中仍可正常运行。
这addDecoration
method 用于应用装饰。
以下示例增强了 Spring MVC<form:input>
标签中具有丰富的建议行为:
<form:input id="searchString" path="searchString"/>
<script type="text/javascript">
Spring.addDecoration(new Spring.ElementDecoration({
elementId: "searchString",
widgetType: "dijit.form.ValidationTextBox",
widgetAttrs: { promptMessage : "Search hotels by name, address, city, or zip." }}));
</script>
这ElementDecoration
call 用于将丰富的小部件行为应用于现有的 DOM 节点。
这种装饰类型并不旨在完全隐藏底层工具包,因此会直接使用工具包的原生小部件类型和属性。
此方法允许您使用通用装饰模型以一致的方式集成底层工具包中的任何小部件。
请参阅booking-mvc
参考应用程序,了解应用装饰执行从建议到客户端验证的更多作示例。
使用ElementDecoration
要应用具有丰富验证行为的窗口小部件,一个常见的需求是防止在验证通过之前将表单提交到服务器。
这可以通过ValidateAllDecoration
如下:
<input type="submit" id="proceed" name="_eventId_proceed" value="Proceed" />
<script type="text/javascript">
Spring.addDecoration(new Spring.ValidateAllDecoration({ elementId:'proceed', event:'onclick' }));
</script>
这会用特殊的onclick
事件处理程序,该处理程序触发客户端验证器,并且在成功通过之前不允许提交表单。
AjaxEventDecoration
应用一个客户端事件侦听器,该侦听器向服务器触发远程 Ajax 请求。
它还会自动注册一个回调函数以在响应中链接。
以下示例使用AjaxEventDecoration
:
<a id="prevLink" href="search?searchString=${criteria.searchString}&page=${criteria.page - 1}">Previous</a>
<script type="text/javascript">
Spring.addDecoration(new Spring.AjaxEventDecoration({
elementId: "prevLink",
event: "onclick",
params: { fragments: "body" }
}));
</script>
前面的清单装饰了onclick
事件与 Ajax 调用一起传递一个特殊参数,该参数指定要在响应中重新呈现的片段。
请注意,如果 Javascript 在客户端中不可用,则此链接将完全正常运行。
(有关如何在服务器上处理此请求的详细信息,请参阅处理 Ajax 请求。
还可以对一个元素应用多个修饰。 以下示例显示了一个用 Ajax 和 validate-all 提交抑制装饰的按钮:
<input type="submit" id="proceed" name="_eventId_proceed" value="Proceed" />
<script type="text/javascript">
Spring.addDecoration(new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));
Spring.addDecoration(new Spring.AjaxEventDecoration({elementId:'proceed', event:'onclick',formId:'booking', params:{fragments:'messages'}}));
</script>
还可以使用 Dojo 的查询 API 在单个语句中将装饰应用于多个元素。 以下示例将一组 checkbox 元素装饰为 Dojo Checkbox 小部件:
<div id="amenities">
<form:checkbox path="amenities" value="OCEAN_VIEW" label="Ocean View" /></li>
<form:checkbox path="amenities" value="LATE_CHECKOUT" label="Late Checkout" /></li>
<form:checkbox path="amenities" value="MINIBAR" label="Minibar" /></li>
<script type="text/javascript">
dojo.query("#amenities input[type='checkbox']").forEach(function(element) {
Spring.addDecoration(new Spring.ElementDecoration({
elementId: element.id,
widgetType : "dijit.form.CheckBox",
widgetAttrs : { checked : element.checked }
}));
});
</script>
</div>
20.4. 处理 Ajax 请求
Spring Javascript 的客户端 Ajax 响应处理是建立在从服务器接收“片段”的概念之上的。 这些片段是标准 HTML,用于替换现有页面的某些部分。 服务器上需要的关键部分是确定需要提取完整响应的哪些部分以进行部分渲染的方法。
为了能够呈现完整响应的部分片段,必须使用模板技术构建完整响应,该技术允许使用合成来构建响应,并允许单独引用和呈现合成的成员部分。 Spring Javascript 提供了一些简单的 Spring MVC 扩展,这些扩展利用 tile 来实现这一点。 理论上,相同的技术可以用于任何支持组合的模板系统。
Spring Javascript 的 Ajax 远程处理功能是建立在 Ajax 请求的核心处理代码不应与标准浏览器请求不同的概念之上的。 因此,不需要直接在代码中了解 Ajax 请求,您可以对两种类型的请求使用相同的处理程序。
20.4.1. 提供特定于 Library 的AjaxHandler
将各种 Ajax 库与 Web Flow 的 Ajax 感知行为集成的关键接口(例如,不重定向以进行部分页面更新)是org.springframework.js.AjaxHandler
.
默认情况下,SpringJavascriptAjaxHandler
已配置。它可以检测通过 Spring JS 客户端 API 提交的 Ajax 请求,并且可以在需要重定向时做出适当的响应。
要集成不同的 Ajax 库(无论是纯 JavaScript 库还是更高级别的抽象,例如支持 Ajax 的 JSF 组件库),您可以注入自定义AjaxHandler
到FlowHandlerAdapter
或FlowController
.
20.4.2. 使用 Spring MVC 控制器处理 Ajax 请求
要使用 Spring MVC 控制器处理 Ajax 请求,你需要在 Spring 应用程序上下文中配置提供的 Spring MVC 扩展,以呈现部分响应(请注意,这些扩展需要使用平铺进行模板化),如下所示:
<bean id="tilesViewResolver" class="org.springframework.webflow.mvc.view.AjaxUrlBasedViewResolver">
<property name="viewClass" value="org.springframework.webflow.mvc.view.FlowAjaxTiles3View"/>
</bean>
这将配置AjaxUrlBasedViewResolver
,这反过来又解释 Ajax 请求并创建FlowAjaxTilesView
对象来处理相应片段的渲染。
请注意,FlowAjaxTilesView
能够处理 Web Flow 和纯 Spring MVC 请求的渲染。
这些片段对应于平铺视图定义的各个属性。
例如,请考虑以下磁贴视图定义:
<definition name="hotels/index" extends="standardLayout">
<put-attribute name="body" value="index.body" />
</definition>
<definition name="index.body" template="/WEB-INF/hotels/index.jsp">
<put-attribute name="hotelSearchForm" value="/WEB-INF/hotels/hotelSearchForm.jsp" />
<put-attribute name="bookingsTable" value="/WEB-INF/hotels/bookingsTable.jsp" />
</definition>
Ajax 请求可以指定body
,hotelSearchForm
或bookingsTable
在请求中呈现为 fragments。
20.4.3. 使用 Spring MVC 和 Spring Web Flow 处理 Ajax 请求
Spring Web Flow 通过使用render
元素。
这种方法的好处是 fragment 的选择与 Client 端代码完全解耦,因此不需要像当前使用纯 Spring MVC 控制器方法那样随请求传递特殊参数。
例如,如果要将hotelSearchForm
片段转换为丰富的 Javascript 弹出窗口,您可以定义以下内容view-state
:
<view-state id="changeSearchCriteria" view="enterSearchCriteria.xhtml" popup="true">
<on-entry>
<render fragments="hotelSearchForm" />
</on-entry>
<transition on="search" to="reviewHotels">
<evaluate expression="searchCriteria.resetPage()"/>
</transition>
</view-state>