Script Views

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

Scripting Library Scripting Engine

Handlebars

Nashorn

Mustache

Nashorn

React

Nashorn

EJS

Nashorn

ERB

JRuby

String templates

Jython

Kotlin Script templating

Kotlin

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

Requirements

您需要在类路径中使用脚本引擎,其详细信息因脚本引擎的不同而有所不同:

  • 在 Java 8+ 中提供了 Nashorn JavaScript 引擎。强烈建议使用最新更新版本。

  • JRuby 应当作为依赖项添加以支持 Ruby。

  • Jython 应当作为依赖项添加以支持 Python。

  • org.jetbrains.kotlin:kotlin-script-util 依赖项和包含 org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory 行的 META-INF/services/javax.script.ScriptEngineFactory 文件应当添加,以支持 Kotlin 脚本。查看 this example 了解更多详情。

你需要具有脚本模板化库。对于 JavaScript,执行此操作的一种方法是通过 WebJars

Script Templates

您可以声明一个 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:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/view/script/RenderingContext.html[RenderingContext],可用于访问应用程序上下文、语言环境、模板加载器和 URL(从 5.0 开始)

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 上运行 Handlebar 或 React 等不适用于并发且专为并发设计的模板化库中使用非线程安全脚本引擎时,设置 sharedEngine 属性为 false 是必需的。在这种情况下,由于 this bug,Java SE 8 更新 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 单元测试、https://github.com/spring-projects/spring-framework/tree/main/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script[Java] 和 resources,以获取更多配置示例。