指令碼檢視

Spring Framework 內建了與任何可在 JSR-223 Java 指令碼引擎上執行的模板庫整合使用的功能。我們在不同的指令碼引擎上測試了以下模板庫:

指令碼庫 指令碼引擎

Handlebars

Nashorn

Mustache

Nashorn

React

Nashorn

EJS

Nashorn

ERB

JRuby

字串模板

Jython

Kotlin 指令碼模板

Kotlin

整合任何其他指令碼引擎的基本規則是它必須實現 ScriptEngineInvocable 介面。

要求

你的類路徑中需要包含指令碼引擎,具體取決於指令碼引擎的不同

  • Java 8+ 提供了 Nashorn JavaScript 引擎。強烈建議使用最新的可用更新版本。

  • 對於 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 renderingContextRenderingContext,用於訪問應用程式上下文、區域設定、模板載入器和 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 上執行的 Handlebars 或 React)以及未設計用於併發的模板庫時,需要將 sharedEngine 屬性設定為 false。在這種情況下,由於這個 bug,需要 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 resources,以獲取更多配置示例。