Spring MVC + Mustache JS模板示例

春天的胡子图像

在本教程中,我们将向您展示Spring MVC + Mustache JS模板 Web应用程序示例。

使用的技术:

  1. Spring4.2.4。发布
  2. mustache.js
  3. JDK 1.8.0_66
  4. 杰克逊2.7
  5. Eclipse 4.3
  6. 雄猫8
  7. Maven 3
  8. 引导程序3

注意
该解决方案仍然有效,但建议使用此简单的Spring Boot + JMustache解决方案。

在Spring,我们可以使用ScriptTemplateConfigurer集成大多数JS模板库,例如Mustache,Handlebars或React。 请参阅此官方Spring脚本模板文档。

从Spring 4.2开始就支持PS ScriptTemplateConfigurer

注意
本示例将使用内置的Java 8 Nashorn Javascript引擎在服务器端运行“ Mustache JS”。 一个同构的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视图模板,请同时配置ScriptTemplateConfigurerViewResolver 。 参见评论以进行自我解释。

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.弹簧控制器+小胡子模板

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一个Mustache模板文件,用于显示来自上述Spring控制器的数据。

/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>
            &lt;pre&gt;{{scriptTemplates}}&lt;/pre&gt;
            <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>
                &lt;pre&gt;{{user}}&lt;/pre&gt;
                <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>
            &lt;pre&gt;{{user_json}}&lt;/pre&gt;
            {{#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...
            &lt;pre&gt;{{users}}&lt;/pre&gt;
            {{#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>&copy; 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语言支持所有Java对象或数据类型,因此需要转换,尤其是List<Object>

总结:

  1. 对于原始数据类型,无需进行转换。
  2. 对于java.lang.Iterable ,将其与Java.from()转换。
  3. 对于List<User> ,使用Jackson将其转换为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));
}

// Some Java objects may not support in JS directly, need conversion.
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 /

春天小胡子demo1

7.2 http:// localhost:8080 / spring /

春天的小胡子demo2

8.如何运行该项目?

8.1从Github克隆源代码。

$ git clone https://github.com/mkyong/spring-mvc-mustache-js-template

8.2运行嵌入式Jetty容器。

$ mvn jetty:run

8.3访问URL: http:// localhost:8080 / spring /

下载源代码

下载– spring-mvc-mustache.zip (127 KB)

Github链接– spring-mvc-mustache-js-template.git

参考文献

  1. 小胡子–无逻辑模板
  2. 小胡子– Javascript
  3. Spring IO –查看模板
  4. 使用Spring Boot,Nashorn和React的同构模板
  5. Java 8 Nashorn教程
  6. Spring React示例
  7. Spring小胡子的另一个解决方案
  8. 同构JavaScript

翻译自: https://mkyong.com/spring-mvc/spring-mvc-mustache-js-template-example/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值