
このチュートリアルでは、Spring MVC +
Mustache JSテンプレート
Webアプリケーションの例を示します。
使用される技術:
-
Spring 4.2.4.RELEASE
-
mustache.js
-
JDK 1.8.0__66
-
ジャクソン2.7
-
Eclipse 4.3
-
Tomcat 8
-
Maven 3
-
ブートストラップ3
Springでは、ScriptTemplateConfigurerを使用してJSテンプレートライブラリのほとんど(Mustache、Handlebars、Reactなど)を統合することができます。
この公式のhttp://docs.spring.io/spring/docs/current/spring-framework-reference/html/view.html#view-script[Springスクリプトテンプレート]のドキュメントを参照してください。
P.S Spring 4.2
以降、 `ScriptTemplateConfigurer`がサポートされています
-
Note ** +この例では、組み込みJava 8 Nashorn Javascriptエンジンを使用して、サーバー側で「Mustache JS」を実行します。
isomorphic javascript
の例です。
1.プロジェクトの構成
標準のMavenフォルダ構造。
2. pom.xml
依存性といくつかの有用なプラグインを宣言するためのMaven `pom.xml`ファイル。
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4__0__0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mkyong</groupId>
<artifactId>spring-mvc-mustache</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>spring mvc mustache</name>
<properties>
<jdk.version>1.8</jdk.version>
<spring.version>4.2.4.RELEASE</spring.version>
<servletapi.version>3.1.0</servletapi.version>
<logback.version>1.1.3</logback.version>
<jcl.slf4j.version>1.7.12</jcl.slf4j.version>
<jackson.version>2.7.0</jackson.version>
</properties>
<dependencies>
<!-- Spring and exclude commons log -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Add slf4j Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${jcl.slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- compile only, deployed container will provide this -->
<!-- no web.xml project need this to start app -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servletapi.version}</version>
<scope>provided</scope>
</dependency>
<!-- JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.11.v20150529</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<webApp>
<contextPath>/spring</contextPath>
</webApp>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<wtpversion>2.0</wtpversion>
<wtpContextName>spring</wtpContextName>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
3. Spring + Mustache JSを統合する
MustacheスクリプトテンプレートをSpringビューテンプレートとして統合するには、
ScriptTemplateConfigurer`と
ViewResolver`の両方を設定します。コメントを見てください。
SpringWebConfig.java
package com.mkyong.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.script.ScriptTemplateConfigurer;
import org.springframework.web.servlet.view.script.ScriptTemplateViewResolver;
@EnableWebMvc
@Configuration
@ComponentScan({ "com.mkyong.web.controller" })
public class SpringWebConfig extends WebMvcConfigurerAdapter {
@Bean
public ScriptTemplateConfigurer configurer() {
ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
//1. Nashorn jdk8 script engine.
configurer.setEngineName("nashorn");
//2. Add mustache.min.js and custom render.js to Nashorn
configurer.setScripts("/static/js/mustache.min.js", "/static/js/render.js");
//3. Ask Nashorn to run this function "render()"
configurer.setRenderFunction("render");
return configurer;
}
//Define where is Mustache template, in classpath level.
//If view "hello" is returned, Mustache temple will be '/static/templates/hello.html'
@Bean
public ViewResolver viewResolver() {
ScriptTemplateViewResolver viewResolver = new ScriptTemplateViewResolver();
viewResolver.setPrefix("/static/templates/");
viewResolver.setSuffix(".html");
return viewResolver;
}
//add static resources like js or css
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/** ** ").addResourceLocations("/resources/");
}
}
4. Spring Controller + Mustacheテンプレート
4.1データをMustacheテンプレートに渡すSpringコントローラ。
HelloController.java
package com.mkyong.web.controller;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mkyong.web.model.User;
@Controller
public class HelloController {
private static final Logger logger = LoggerFactory.getLogger(HelloController.class);
private static final ObjectMapper om = new ObjectMapper();
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView printWelcome(HttpServletRequest request) {
ModelAndView result = new ModelAndView();
result.addObject("resources", request.getContextPath() + "/resources");
result.addObject("logo", "mkyong.com");
result.addObject("title", "Spring MVC + Mustache template");
result.addObject("jumbo-title", "Spring MVC + Mustache template");
result.addObject("jumbo-desc", "Maven + Spring MVC + Mustache JS, ScriptTemplate example.");
//1. Test data type
result.addObject("id", 100);
result.addObject("username", "mkyong");
//2. Test List
result.addObject("scriptTemplates", getScriptTemplate());
//3. Test Object
result.addObject("user", new User("abc@gmail.com", 0));
//4. Test List<Object>
List<User> list = new ArrayList<>();
list.add(new User("aaa@gmail.com", 1));
list.add(new User("bbb@yahoo.com", 2));
list.add(new User("ccc@hotmail.com", 3));
result.addObject("users__json", convertObjectToJson(list));
result.addObject("users", list);
result.setViewName("hello");
return result;
}
private List<String> getScriptTemplate() {
List<String> scriptTemplates = new ArrayList<>();
scriptTemplates.add("Handlebars");
scriptTemplates.add("Mustache");
scriptTemplates.add("React");
scriptTemplates.add("EJS");
scriptTemplates.add("ERB");
scriptTemplates.add("String templates");
return scriptTemplates;
}
//Jackson2 - Convert Java Object to JSON format
public static String convertObjectToJson(Object obj) {
String result = "";
try {
result = om.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (JsonProcessingException e) {
logger.error("Error In JSON conversion : {}", e);
}
return result;
}
}
4.2上記のSpringコントローラからのデータを表示するためのMustacheテンプレートファイル。
/static/templates/hello.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{title}}</title>
<link href="{{{resources}}}/core/css/bootstrap.min.css" rel="stylesheet">
<link href="{{{resources}}}/core/css/bootstrap-theme.min.css" rel="stylesheet">
<link href="{{{resources}}}/core/css/hello.css" rel="stylesheet">
</head>
<body role="document">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#">{{logo}}</a>
</div>
</div>
</nav>
<div class="container theme-showcase" role="main">
<div class="jumbotron">
<h1>{{jumbo-title}}</h1>
<p>{{jumbo-desc}}</p>
</div>
<div class="row">
<div class="col-sm-6">
<div class="page-header">
<h1>1. Data Types</h1>
</div>
<p>
<div>
{{#id}}
Hello {{username}}, id : {{.}}
{{/id}}
</div>
</p>
</div>
<div class="col-sm-6">
<div class="page-header">
<h1>2. List</h1>
</div>
<p>
<pre>{{scriptTemplates}}</pre>
<ol>
{{#scriptTemplates}}
<li>{{.}}</li>
{{/scriptTemplates}}
</ol>
</p>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="page-header">
<h1>3. User Object</h1>
</div>
<p>
<div>
<pre>{{user}}</pre>
<ol>
{{#user}}
<li>email- {{user.email}}</li>
<li>loginFailed- {{user.loginFailed}}</li>
{{/user}}
</ol>
</div>
</p>
</div>
<div class="col-sm-6">
<div class="page-header">
<h1>4. List of User Objects (JSON)</h1>
</div>
<p>
<pre>{{user__json}}</pre>
{{#users__json}}
<ol>
<li>email- {{email}}</li>
<li>loginFailed- {{loginFailed}}</li>
</ol>
{{/users__json}}
</p>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="page-header">
<h1>5. List of User Objects (RAW)</h1>
</div>
<p>
No idea how to loop it...
<pre>{{users}}</pre>
{{#users}}
<ol>
<li>email- {{email}}</li>
<li>loginFailed- {{loginFailed}}</li>
</ol>
{{/users}}
</p>
</div>
<div class="col-sm-6">
<div class="page-header">
<h1></h1>
</div>
<p>
</p>
</div>
</div>
</div>
<div class="container">
<hr>
<footer>
<p>© Mkyong.com 2016</p>
</footer>
</div>
<script type="text/javascript" src="{{{resources}}}/core/js/hello.js"></script>
<script type="text/javascript" src="{{{resources}}}/core/js/jquery-1.12.0.min.js"></script>
<script type="text/javascript" src="{{{resources}}}/core/js/bootstrap.min.js"></script>
</body>
</html>
5. Javascript ‘render.js’
ビューが返されると、Springはこの関数 `render(template、model、url)`を実行します。しかし、すべてのJavaオブジェクトやデータ型がJavascriptでサポートされているわけではありません。変換が必要です。特に `List <Object> ‘が必要です。
要約:
-
プリミティブデータ型の場合、変換の必要はありません.
-
java.lang.Iterable`では
Java.from() `で変換します. -
`List <User>`ではJSON形式の文字列に変換します
JSON.parseを介してJSオブジェクトに変換します。このトリックは、任意のJavaオブジェクトのJavaScript変換で機能するはずです。
/static/js/render.js
…./
Bindings to use mustache.js with Nashorn.
//
String templates: the Mustache template content. e.g hello.html
Map model: the model in controller
String url: the templates url (since 4.2.2)
/function render(template, model, url) {
return Mustache.render(template, toJsonObject(model));
}
function toJsonObject(model) {
var o = {};
for (var k in model) {
//Convert Object String to Javascript JSON
if (k.indexOf("__json") > -1) {
o[k]= JSON.parse(model[k]);
continue;
}
//Convert Iterable like List to real JSON array
if (model[k]instanceof Java.type("java.lang.Iterable")) {
o[k]= Java.from(model[k]);
}
else {
o[k]= model[k];
}
}
return o;
}
=== 6.その他のクラス 6.1 `webInitializer`クラスを作成して、` web.xml` Webアプリケーションを作成しません。 MyWebInitializer
package com.mkyong.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.mkyong.config.SpringWebConfig;
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[]getServletConfigClasses() {
return new Class[]{ SpringWebConfig.class };
}
@Override
protected String[]getServletMappings() {
return new String[]{ "/" };
}
@Override
protected Class<?>[]getRootConfigClasses() {
return null;
}
}
6.2ユーザオブジェクト。 User.java
package com.mkyong.web.model;
public class User {
String email; int loginFailed;
public User(String email, int loginFailed) {
this.email = email;
this.loginFailed = loginFailed;
}
//setters and getters }
=== 7.デモ 7.1 __http://localhost:8080/spring/__ image://wp-content/uploads/2016/01/spring-mustache-demo1.png[spring-mustache-demo1、width = 1014、height = 703] 7.2 __http://localhost:8080/spring/__ image://wp-content/uploads/2016/01/spring-mustache-demo2.png[spring-mustache-demo2、width = 999、height = 1570] === 8.このプロジェクトをどのように実行するのですか? 8.1 Githubからソースコードをクローンします。
8.2組み込みJettyコンテナを実行します。
$ mvn jetty:run
8.3訪問URL:__http://localhost:8080/spring/__ === ソースコードをダウンロードする ダウンロード:link://wp-content/uploads/2016/01/spring-mvc-mustache.zip[spring-mvc-mustache.zip](127 KB) Githubのリンク - https://github.com/mkyong/spring-mvc-mustache-js-template[spring-mvc-mustache-js-template.git] === 参考文献 . http://mustache.github.io/[Mustache - ロジックレステンプレート] . https://github.com/janl/mustache.js[Mustache - Javascript] . http://docs.spring.io/spring/docs/current/spring-framework-reference/html/view.html#view-script[Spring IO - ビューテンプレート]。 https://speakerdeck.com/sdeleuze/isomorphic-templating-with-spring-boot-nashorn-and-react[Isomorphic Spring Boot、Nashorn、Reactでのテンプレート化]。 http://winterbe.com/posts/2014/04/05/java8-nashorn-tutorial/[Java 8 ナショーンチュートリアル]。 https://github.com/sdeleuze/spring-react-isomorphic[Spring React 例]。 https://github.com/mjeanroy/springmvc-mustache[さらに別の春 口ひげソリューション]。 http://isomorphic.net/[異形JavaScript] link://tag/mustache/[mustache]link://tag/spring-mvc/[spring mvc]