脚本视图

Spring Framework 内置了与任何可在 JSR-223 Java 脚本引擎上运行的模板库一起使用 Spring MVC 的集成。 我们已在不同的脚本引擎上测试了以下模板库:

脚本库 脚本引擎

Handlebars

Nashorn

Mustache

Nashorn

React

Nashorn

EJS

Nashorn

ERB

JRuby

字符串模板

Jython

Kotlin 脚本模板

Kotlin

集成任何其他脚本引擎的基本规则是它必须实现 ScriptEngineInvocable 接口。

要求

您需要在类路径中包含脚本引擎,具体细节因脚本引擎而异:

  • Nashorn JavaScript 引擎随 Java 8+ 提供。强烈建议使用最新的可用更新版本。

  • 对于 Ruby 支持,应添加 JRuby 作为依赖项。

  • 对于 Python 支持,应添加 Jython 作为依赖项。

  • 对于 Kotlin 脚本支持,应添加 org.jetbrains.kotlin:kotlin-script-util 依赖项和一个包含 org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory 行的 META-INF/services/javax.script.ScriptEngineFactory 文件。有关更多详细信息,请参阅 此示例

您需要拥有脚本模板库。对于 JavaScript,一种方法是通过 WebJars

脚本模板

您可以声明一个 ScriptTemplateConfigurer bean 来指定要使用的脚本引擎、要加载的脚本文件、要调用哪个函数来渲染模板等等。 以下示例使用 Mustache 模板和 Nashorn JavaScript 引擎:

  • Java

  • Kotlin

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		registry.scriptTemplate();
	}

	@Bean
	public ScriptTemplateConfigurer configurer() {
		ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
		configurer.setEngineName("nashorn");
		configurer.setScripts("mustache.js");
		configurer.setRenderObject("Mustache");
		configurer.setRenderFunction("render");
		return configurer;
	}
}
@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {

	override fun configureViewResolvers(registry: ViewResolverRegistry) {
		registry.scriptTemplate()
	}

	@Bean
	fun configurer() = ScriptTemplateConfigurer().apply {
		engineName = "nashorn"
		setScripts("mustache.js")
		renderObject = "Mustache"
		renderFunction = "render"
	}
}

以下示例以 XML 形式显示了相同的配置:

<mvc:annotation-driven/>

<mvc:view-resolvers>
	<mvc:script-template/>
</mvc:view-resolvers>

<mvc:script-template-configurer engine-name="nashorn" render-object="Mustache" render-function="render">
	<mvc:script location="mustache.js"/>
</mvc:script-template-configurer>

对于 Java 和 XML 配置,控制器看起来没有区别,如以下示例所示:

  • Java

  • Kotlin

@Controller
public class SampleController {

	@GetMapping("/sample")
	public String test(Model model) {
		model.addAttribute("title", "Sample title");
		model.addAttribute("body", "Sample body");
		return "template";
	}
}
@Controller
class SampleController {

	@GetMapping("/sample")
	fun test(model: Model): String {
		model["title"] = "Sample title"
		model["body"] = "Sample body"
		return "template"
	}
}

以下示例显示了 Mustache 模板:

<html>
	<head>
		<title>{{title}}</title>
	</head>
	<body>
		<p>{{body}}</p>
	</body>
</html>

渲染函数使用以下参数调用:

  • String template: 模板内容

  • Map model: 视图模型

  • RenderingContext renderingContext: 提供对应用程序上下文、区域设置、模板加载器和 URL(自 5.0 起)访问的 RenderingContext

Mustache.render() 本身与此签名兼容,因此您可以直接调用它。

如果您的模板技术需要一些自定义,您可以提供一个实现自定义渲染功能的脚本。例如,Handlerbars 在使用模板之前需要编译模板,并且需要一个 polyfill 来模拟服务器端脚本引擎中不可用的一些 浏览器功能。

以下示例显示了如何执行此操作:

  • Java

  • Kotlin

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		registry.scriptTemplate();
	}

	@Bean
	public ScriptTemplateConfigurer configurer() {
		ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
		configurer.setEngineName("nashorn");
		configurer.setScripts("polyfill.js", "handlebars.js", "render.js");
		configurer.setRenderFunction("render");
		configurer.setSharedEngine(false);
		return configurer;
	}
}
@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {

	override fun configureViewResolvers(registry: ViewResolverRegistry) {
		registry.scriptTemplate()
	}

	@Bean
	fun configurer() = ScriptTemplateConfigurer().apply {
		engineName = "nashorn"
		setScripts("polyfill.js", "handlebars.js", "render.js")
		renderFunction = "render"
		isSharedEngine = false
	}
}

当使用非线程安全的脚本引擎和非并发设计的模板库(例如在 Nashorn 上运行的 Handlebars 或 React)时,需要将 sharedEngine 属性设置为 false。在这种情况下,由于 此错误,需要 Java SE 8 update 60,但通常建议在任何情况下都使用最新的 Java SE 补丁版本。

polyfill.js 仅定义 Handlebars 正常运行所需的 window 对象,如下所示:

var window = {};

这个基本的 render.js 实现在使用模板之前编译模板。一个生产就绪的实现还应该存储任何重用的缓存模板或预编译模板。 您可以在脚本端执行此操作(并处理您需要的任何自定义——例如,管理模板引擎配置)。以下示例显示了如何执行此操作:

function render(template, model) {
	var compiledTemplate = Handlebars.compile(template);
	return compiledTemplate(model);
}

请查看 Spring Framework 单元测试、 Java资源, 以获取更多配置示例。