指令碼視圖

Spring Framework 內建整合,可將 Spring MVC 與任何可在 JSR-223 Java 指令碼引擎之上執行的範本程式庫搭配使用。我們已在不同的指令碼引擎上測試過下列範本程式庫

指令碼程式庫 指令碼引擎

Handlebars

Nashorn

Mustache

Nashorn

React

Nashorn

EJS

Nashorn

ERB

JRuby

字串範本

Jython

Kotlin 指令碼範本

Kotlin

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

需求

您需要在類別路徑中擁有指令碼引擎,其詳細資訊因指令碼引擎而異

  • Nashorn JavaScript 引擎隨附於 Java 8+。強烈建議使用可用的最新更新版本。

  • JRuby 應新增為 Ruby 支援的相依性。

  • Jython 應新增為 Python 支援的相依性。

  • org.jetbrains.kotlin:kotlin-script-util 相依性和包含 org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory 行的 META-INF/services/javax.script.ScriptEngineFactory 檔案應新增以支援 Kotlin 指令碼。如需更多詳細資訊,請參閱此範例

您需要擁有指令碼範本程式庫。其中一種針對 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>

使用下列參數呼叫 render 函數

  • String template:範本內容

  • Map model:視圖模型

  • RenderingContext renderingContextRenderingContext,可讓您存取應用程式 Context、地區設定、範本載入器和 URL(自 5.0 版起)

Mustache.render() 本身與此簽名相容,因此您可以直接呼叫它。

如果您的範本技術需要一些自訂,您可以提供一個指令碼來實作自訂 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資源,以取得更多組態範例。