《Spring Boot极简教程》第7章 Spring Boot集成模板引擎

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 第7章 Spring Boot集成模板引擎其实,没有任何一个模板引擎(jsp,velocity,thymeleaf,freemarker,etc)可以完全实现MVC绝对的分层,只有“自由度”上的界定罢了。

第7章 Spring Boot集成模板引擎

其实,没有任何一个模板引擎(jsp,velocity,thymeleaf,freemarker,etc)可以完全实现MVC绝对的分层,只有“自由度”上的界定罢了。因为MVC本来就是相互关联的,不可分割的一个整体。

在MVC模式中,模板引擎的工作原理基本一样,比如说以freemarker为例,如下图:

7.1 Spring Boot集成jsp模板

7.2 Spring Boot集成thymeleaf模板

7.3 Spring Boot集成velocity模板

本节我们使用SpringBoot集成velocity开发一个极简的服务监控系统。

我们使用SpringBoot 1.4.5.RELEASE, 这是SpringBoot集成Velocity views的最新版本,目前看也是最后一个版本。数据库ORM层我们采用jpa。

默认情况下,Spring Boot会配置一个VelocityViewResolver,如果需要的是VelocityLayoutViewResolver,你可以自己创建一个名为velocityViewResolver的bean。你也可以将VelocityProperties实例注入到自定义视图解析器以获取基本的默认设置。

以下示例使用VelocityLayoutViewResolver替换自动配置的velocity视图解析器,并自定义layoutUrl及应用所有自动配置的属性:

@Bean(name = "velocityViewResolver")
public VelocityLayoutViewResolver velocityViewResolver(VelocityProperties properties) {
    VelocityLayoutViewResolver resolver = new VelocityLayoutViewResolver();
    properties.applyToViewResolver(resolver);
    resolver.setLayoutUrl("layout/default.vm");
    return resolver;
}

1.配置pom依赖

引入spring-boot-starter-parent

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <!-- Starter for building MVC web applications using Velocity views. Deprecated since 1.4 -->
        <version>1.4.5.RELEASE</version>
        <!--<version>1.5.2.RELEASE</version>-->
    </parent>

引入velocity-starter

<!--web容器支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>            
        </dependency>
   
        <!--Velocity starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-velocity</artifactId>
        </dependency>

默认配置下spring boot会从src/main/resources/templates目录中去找模板

引入jpa,mysql-connector

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

2.application.properties配置

# VELOCITY TEMPLATES (VelocityAutoConfiguration) 在SpringBoot
spring.velocity.templateEncoding=UTF-8
spring.velocity.properties.input.encoding=UTF-8
spring.velocity.properties.output.encoding=UTF-8
spring.velocity.resourceLoaderPath=classpath:/templates/
spring.velocity.suffix=.html

server.port=7001

# security
#security.user.name=admin
#security.user.password=admin

# Spring Boot log level
logging.config=logback.xml
logging.level.org.springframework.web: INFO

#mysql
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/femon?useUnicode=true&characterEncoding=UTF8
spring.datasource.username = qa_conn
spring.datasource.password = qa_conn
spring.datasource.driverClassName = com.mysql.jdbc.Driver
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = update
# Naming strategy
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy

# stripped before adding them to the entity manager)
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect


3.Dao层代码示例

package com.femon.dao;

import java.util.Date;
import java.util.List;

import com.femon.entity.ServiceData;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;

/**
 * @author 一剑 2015年12月23日 下午9:34:15
 */
public interface ServiceDataDao extends PagingAndSortingRepository<ServiceData, Integer> {

    @Query("select h from ServiceData h where h.serviceId = ?1")
    List<ServiceData> findByServiceId(int serviceId, Pageable pageable);

    @Query("select h from ServiceData h where h.serviceId = ?1 and h.sampleTime between ?2 and ?3 ")
    List<ServiceData> findByServiceIdAndDay(int serviceId, Date dayStart, Date dayEnd, Pageable pageable);

    @Query("select h from ServiceData h where h.serviceId = ?1 and state=0 and h.sampleTime between ?2 and ?3 ")
    Page<ServiceData> findFailByServiceIdAndDay(int serviceId, Date dayStart, Date dayEnd, Pageable pageable);

    ServiceData save(ServiceData h);

}

4.Controller层代码示例

package com.femon.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import com.alibaba.fastjson.JSON;

import com.femon.dao.ServiceDao;
import com.femon.dao.ServiceDataDao;
import com.femon.entity.Service;
import com.femon.entity.ServiceData;
import com.femon.result.ServiceDataResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

/**
 * @author 一剑 2015年12月29日 下午5:23:22
 */
@Controller
public class ServiceController {
    @Autowired
    ServiceDataDao historyDao;
    @Autowired
    ServiceDao serviceDao;

    ......

    @RequestMapping(value = "/service", method = RequestMethod.GET)
    public ModelAndView list(Model model, @RequestParam(value = "page", defaultValue = "0", required = false) int page,
                             @RequestParam(value = "count", defaultValue = "10", required = false) int count,
                             @RequestParam(value = "order", defaultValue = "ASC", required = false)
                                 Sort.Direction direction,
                             @RequestParam(value = "sort", defaultValue = "gmtCreate", required = false)
                                 String sortProperty,
                             @RequestParam(value = "hostCode", defaultValue = "1", required = false) int hostCode) {
        ModelAndView modelAndView = new ModelAndView("/service");

        Page result = null;

        if (hostCode == 0) {
            result = serviceDao.findAll(new PageRequest(page, count, new Sort(direction, sortProperty)));
        } else {
            result = serviceDao.findByHost(hostCode, new PageRequest(page, count, new Sort(direction, sortProperty)));
        }
        long totalPages = result.getTotalPages();
        List<Integer> pageIndexList = new ArrayList<Integer>((int)totalPages);
        for (int i = 0; i < totalPages; i++) {
            pageIndexList.add(i);
        }
        int currentPage = page;
        List<Service> serviceList = result.getContent();
        model.addAttribute("serviceList", serviceList);
        model.addAttribute("pageIndexList", pageIndexList);
        model.addAttribute("currentPage", currentPage);
        model.addAttribute("currentHost", hostCode);

        return modelAndView;
    }

    ......

}

5.执行定时任务

简单的定时任务的执行,只需要使用@Scheduled注解即可。但是要在启动类上面加上注解@EnableScheduling。

支持cron表达式:

@Scheduled(cron="0 * * * * MON-FRI")

和fixedRate:

@Scheduled(fixedRate = 60000)

等使用方式。

代码示例

@Component
public class WatchService {
    @Scheduled(fixedRate = 60000)
    public void curlJob() {
        ...
    }
}

6.启动类代码

应用入口类:Application.java

package com.femon;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * @author 一剑
 */

@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages = "com.femon")
@EnableScheduling
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

7.运行测试

Run Application,你将看到如下的输出:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.4.5.RELEASE)

2017-04-05 14:08:35.456  INFO 93948 --- [           main] com.femon.Application                    : Starting Application on jacks-MacBook-Air.local with PID 93948 (/Users/jack/book/femon/target/classes started by jack in /Users/jack/book/femon)
2017-04-05 14:08:35.466  INFO 93948 --- [           main] com.femon.Application                    : No active profile set, falling back to default profiles: default
2017-04-05 14:08:35.742  INFO 93948 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@36c88a32: startup date [Wed Apr 05 14:08:35 CST 2017]; root of context hierarchy
2017-04-05 14:08:37.996  INFO 93948 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$e6b9fa58] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-04-05 14:08:38.673  INFO 93948 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 7001 (http)
2017-04-05 14:08:38.686  INFO 93948 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2017-04-05 14:08:38.687  INFO 93948 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.11
2017-04-05 14:08:38.811  INFO 93948 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-04-05 14:08:38.812  INFO 93948 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3079 ms

.......

2017-04-05 14:08:45.135  INFO 93948 --- [           main] o.s.w.s.v.velocity.VelocityConfigurer    : ClasspathResourceLoader with name 'springMacro' added to configured VelocityEngine
2017-04-05 14:08:45.471  INFO 93948 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-04-05 14:08:45.486  INFO 93948 --- [           main] s.a.ScheduledAnnotationBeanPostProcessor : No TaskScheduler/ScheduledExecutorService bean found for scheduled processing
2017-04-05 14:08:45.576  INFO 93948 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 7001 (http)
2017-04-05 14:08:45.582  INFO 93948 --- [           main] com.femon.Application                    : Started Application in 11.253 seconds (JVM running for 12.373)

访问:http://localhost:7001/

系统运行效果图:

首页
创建服务
服务列表
服务详情

源代码:https://github.com/EasySpringBoot/femon

7.4 Spring Boot集成freemarker模板

与JSP相比,FreeMarker的一个优点在于不能轻易突破模板语言开始编写Java代码,因此降低了领域逻辑漏进视图层的危险几率。

本节我们给出一个SpringBoot集成freemarker模板引擎的Demo,基于gradle构建。

1.添加spring-boot-starter-freemarker依赖到pom中

buildscript {
    ext {
        springBootVersion = '1.5.2.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}


dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.boot:spring-boot-starter-freemarker')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

2.写后端Controller

package com.example.controller;

import java.util.Date;
import java.util.Map;

import com.example.biz.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * Created by jack on 2017/4/5.
 */
@Controller
public class WelcomeController {

    @Value("${application.message:Hello,World}")
    private String message = "Hello,World";

    @Autowired
    BookService bookService;

    @GetMapping("/welcome")
    public String welcome(Map<String, Object> model) {
        model.put("time", new Date());
        model.put("message", this.message);
        model.put("books", bookService.findAll());
        return "welcome";
    }

}

3.写前端ftl代码

 <!DOCTYPE html>
<html lang="zh">
<body>
Date: ${time?date}
<br>
Time: ${time?time}
<br>
Message: ${message}
<div>
    <#list books as book>
        <li>书名: ${book.name}</li>
        <li>作者: ${book.author}</li>
        <li>出版社: ${book.press}</li>
    </#list>
</div>
</body>

</html>

4.运行测试

运行DemoApplication, 我们将看到如下日志:

2017-04-05 22:05:06.020  INFO 98366 --- [           main] com.example.DemoApplication              : Starting DemoApplication on jacks-MacBook-Air.local with PID 98366 (/Users/jack/book/demo/build/classes/main started by jack in /Users/jack/book/demo)

......

o.s.w.s.v.f.FreeMarkerConfigurer         : ClassTemplateLoader for Spring macros added to FreeMarker configuration
2017-04-05 22:05:08.848  INFO 98366 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-04-05 22:05:08.911  INFO 98366 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 5678 (http)
2017-04-05 22:05:08.931  INFO 98366 --- [           main] com.example.DemoApplication              : Started DemoApplication in 3.37 seconds (JVM running for 4.017)
2017-04-05 22:25:02.870  INFO 98366 --- [nio-5678-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2017-04-05 22:25:02.872  INFO 98366 --- [nio-5678-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2017-04-05 22:25:02.902  INFO 98366 --- [nio-5678-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 30 ms

浏览器访问:http://localhost:5678/welcome
我们将看到如下输出:

freemarker demo

本节工程源码 :https://github.com/EasySpringBoot/HelloWorld/tree/freemarker_demo_2017.4.6

7.5 Spring Boot集成groovy模板

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
定时任务在企业应用中至关重要,常用于异步数据处理、自动化运维等场景。在单体应用中,利用Java的`java.util.Timer`或Spring的`@Scheduled`即可轻松实现。然而,进入微服务架构后,任务可能因多节点并发执行而重复。Spring Cloud Alibaba为此发布了Scheduling模块,提供轻量级、高可用的分布式定时任务解决方案,支持防重复执行、分片运行等功能,并可通过`spring-cloud-starter-alibaba-schedulerx`快速集成。用户可选择基于阿里云SchedulerX托管服务或采用本地开源方案(如ShedLock)
|
3天前
|
存储 Java 开发工具
【三方服务集成】最新版 | 阿里云OSS对象存储服务使用教程(包含OSS工具类优化、自定义阿里云OSS服务starter)
阿里云OSS(Object Storage Service)是一种安全、可靠且成本低廉的云存储服务,支持海量数据存储。用户可通过网络轻松存储和访问各类文件,如文本、图片、音频和视频等。使用OSS后,项目中的文件上传业务无需在服务器本地磁盘存储文件,而是直接上传至OSS,由其管理和保障数据安全。此外,介绍了OSS服务的开通流程、Bucket创建、AccessKey配置及环境变量设置,并提供了Java SDK示例代码,帮助用户快速上手。最后,展示了如何通过自定义starter简化工具类集成,实现便捷的文件上传功能。
【三方服务集成】最新版 | 阿里云OSS对象存储服务使用教程(包含OSS工具类优化、自定义阿里云OSS服务starter)
|
4天前
|
存储 前端开发 Java
Spring Boot 集成 MinIO 与 KKFile 实现文件预览功能
本文详细介绍如何在Spring Boot项目中集成MinIO对象存储系统与KKFileView文件预览工具,实现文件上传及在线预览功能。首先搭建MinIO服务器,并在Spring Boot中配置MinIO SDK进行文件管理;接着通过KKFileView提供文件预览服务,最终实现文档管理系统的高效文件处理能力。
|
17天前
|
XML JavaScript Java
Spring Retry 教程
Spring Retry 是 Spring 提供的用于处理方法重试的库,通过 AOP 提供声明式重试机制,不侵入业务逻辑代码。主要步骤包括:添加依赖、启用重试机制、设置重试策略(如异常类型、重试次数、延迟策略等),并可定义重试失败后的回调方法。适用于因瞬时故障导致的操作失败场景。
Spring Retry 教程
|
21天前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
2月前
|
Java 数据库连接 Spring
一文讲明 Spring 的使用 【全网超详细教程】
这篇文章是一份全面的Spring框架使用教程,涵盖了从基础的项目搭建、IOC和AOP概念的介绍,到Spring的依赖注入、动态代理、事务处理等高级主题,并通过代码示例和配置文件展示了如何在实际项目中应用Spring框架的各种功能。
一文讲明 Spring 的使用 【全网超详细教程】
|
2月前
|
测试技术 Java Spring
Spring 框架中的测试之道:揭秘单元测试与集成测试的双重保障,你的应用真的安全了吗?
【8月更文挑战第31天】本文以问答形式深入探讨了Spring框架中的测试策略,包括单元测试与集成测试的有效编写方法,及其对提升代码质量和可靠性的重要性。通过具体示例,展示了如何使用`@MockBean`、`@SpringBootTest`等注解来进行服务和控制器的测试,同时介绍了Spring Boot提供的测试工具,如`@DataJpaTest`,以简化数据库测试流程。合理运用这些测试策略和工具,将助力开发者构建更为稳健的软件系统。
39 0
|
2月前
|
数据库 开发者 Java
颠覆传统开发:Hibernate与Spring Boot的集成,让你的开发效率飞跃式提升!
【8月更文挑战第31天】在 Java 开发中,Spring Boot 和 Hibernate 已成为许多开发者的首选技术栈。Spring Boot 简化了配置和部署过程,而 Hibernate 则是一个强大的 ORM 框架,用于管理数据库交互。将两者结合使用,可以极大提升开发效率并构建高性能的现代 Java 应用。本文将通过代码示例展示如何在 Spring Boot 项目中集成 Hibernate,并实现基本的数据库操作,包括添加依赖、配置数据源、创建实体类和仓库接口,以及在服务层和控制器中处理 HTTP 请求。这种组合不仅简化了配置,还提供了一套强大的工具来快速开发现代 Java 应用程序。
62 0
|
2月前
|
消息中间件 Java Kafka
Spring Boot与模板引擎:整合Thymeleaf和FreeMarker,打造现代化Web应用
【8月更文挑战第29天】这段内容介绍了在分布式系统中起到异步通信与解耦作用的消息队列,并详细探讨了三种流行的消息队列产品:RabbitMQ、RocketMQ 和 Kafka。RabbitMQ 是一个基于 AMQP 协议的开源消息队列系统,支持多种消息模型,具有高可靠性及稳定性;RocketMQ 则是由阿里巴巴开源的高性能分布式消息队列,支持事务消息等多种特性;而 Kafka 是 LinkedIn 开源的分布式流处理平台,以其高吞吐量和良好的可扩展性著称。文中还提供了使用这三种消息队列产品的示例代码。
23 0
|
2月前
|
SQL Java 数据库连接
Spring Boot联手MyBatis,打造开发利器:从入门到精通,实战教程带你飞越编程高峰!
【8月更文挑战第29天】Spring Boot与MyBatis分别是Java快速开发和持久层框架的优秀代表。本文通过整合Spring Boot与MyBatis,展示了如何在项目中添加相关依赖、配置数据源及MyBatis,并通过实战示例介绍了实体类、Mapper接口及Controller的创建过程。通过本文,你将学会如何利用这两款工具提高开发效率,实现数据的增删查改等复杂操作,为实际项目开发提供有力支持。
61 0
下一篇
无影云桌面