《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模板

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
26天前
|
Java 关系型数据库 MySQL
SpringBoot 通过集成 Flink CDC 来实时追踪 MySql 数据变动
通过详细的步骤和示例代码,您可以在 SpringBoot 项目中成功集成 Flink CDC,并实时追踪 MySQL 数据库的变动。
176 43
|
5天前
|
Cloud Native Java Nacos
springcloud/springboot集成NACOS 做注册和配置中心以及nacos源码分析
通过本文,我们详细介绍了如何在 Spring Cloud 和 Spring Boot 中集成 Nacos 进行服务注册和配置管理,并对 Nacos 的源码进行了初步分析。Nacos 作为一个强大的服务注册和配置管理平台,为微服务架构提供
35 14
|
5天前
|
消息中间件 XML 前端开发
springBoot集成websocket实时消息推送
本文介绍了如何在Spring Boot项目中集成WebSocket实现实时消息推送。首先,通过引入`spring-boot-starter-websocket`依赖,配置`WebSocketConfig`类来启用WebSocket支持。接着,创建`WebSocketTest`服务器类,处理连接、消息收发及错误等事件,并使用`ConcurrentHashMap`管理用户连接。最后,前端通过JavaScript建立WebSocket连接,监听消息并进行相应处理。此方案适用于需要实时通信的应用场景,如聊天室、通知系统等。
|
5天前
|
前端开发 Java Nacos
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
本文介绍了如何使用Spring Cloud Alibaba 2023.0.0.0技术栈构建微服务网关,以应对微服务架构中流量治理与安全管控的复杂性。通过一个包含鉴权服务、文件服务和主服务的项目,详细讲解了网关的整合与功能开发。首先,通过统一路由配置,将所有请求集中到网关进行管理;其次,实现了限流防刷功能,防止恶意刷接口;最后,添加了登录鉴权机制,确保用户身份验证。整个过程结合Nacos注册中心,确保服务注册与配置管理的高效性。通过这些实践,帮助开发者更好地理解和应用微服务网关。
22 0
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
|
1月前
|
监控 前端开发 Java
SpringBoot集成Tomcat、DispatcherServlet
通过这些配置,您可以充分利用 Spring Boot 内置的功能,快速构建和优化您的 Web 应用。
58 21
|
2月前
|
监控 Java 应用服务中间件
SpringBoot是如何简化Spring开发的,以及SpringBoot的特性以及源码分析
Spring Boot 通过简化配置、自动配置和嵌入式服务器等特性,大大简化了 Spring 应用的开发过程。它通过提供一系列 `starter` 依赖和开箱即用的默认配置,使开发者能够更专注于业务逻辑而非繁琐的配置。Spring Boot 的自动配置机制和强大的 Actuator 功能进一步提升了开发效率和应用的可维护性。通过对其源码的分析,可以更深入地理解其内部工作机制,从而更好地利用其特性进行开发。
50 6
|
2月前
|
监控 Java Nacos
使用Spring Boot集成Nacos
通过上述步骤,Spring Boot应用可以成功集成Nacos,利用Nacos的服务发现和配置管理功能来提升微服务架构的灵活性和可维护性。通过这种集成,开发者可以更高效地管理和部署微服务。
250 17
|
2月前
|
XML JavaScript Java
SpringBoot集成Shiro权限+Jwt认证
本文主要描述如何快速基于SpringBoot 2.5.X版本集成Shiro+JWT框架,让大家快速实现无状态登陆和接口权限认证主体框架,具体业务细节未实现,大家按照实际项目补充。
99 11
|
2月前
|
缓存 安全 Java
Spring Boot 3 集成 Spring Security + JWT
本文详细介绍了如何使用Spring Boot 3和Spring Security集成JWT,实现前后端分离的安全认证概述了从入门到引入数据库,再到使用JWT的完整流程。列举了项目中用到的关键依赖,如MyBatis-Plus、Hutool等。简要提及了系统配置表、部门表、字典表等表结构。使用Hutool-jwt工具类进行JWT校验。配置忽略路径、禁用CSRF、添加JWT校验过滤器等。实现登录接口,返回token等信息。
499 12
|
Java 应用服务中间件
SpringBoot集成使用jsp(超详细)
SpringBoot集成使用jsp(超详细)
SpringBoot集成使用jsp(超详细)

热门文章

最新文章