重学SpringBoot系列之整合静态资源与模板引擎

Posted 大忽悠爱忽悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重学SpringBoot系列之整合静态资源与模板引擎相关的知识,希望对你有一定的参考价值。


webjars与静态资源

spring boot静态资源

静态资源目录

SpringBoot默认配置下,提供了以下几个静态资源目录:

/static:  classpath:/static/
/public: classpath:/public/
/resources: classpath:/resources/
/META-INF/resources:classpath:/META-INF/resources/

当然,可以通过spring.resources.static-locations配置指定静态文件的位置。但是要特别注意,一旦自己指定了静态资源目录,系统默认的静态资源目录就会失效。所以系统默认的就已经足够使用了,尽量不要自定义。

#配置静态资源
spring:
  resources:
    #指定静态资源目录
    static-locations: classpath:/mystatic/

favicon.ico图标

如果在配置的静态资源目录中有favicon.ico文件,SpringBoot会自动将其设置为应用图标。


欢迎页面

SpringBoot支持静态和模板欢迎页,它首先在静态资源目录查看index.html文件做为首页,若未找到则查找index模板。


使用WebJars管理css&js

为什么使用 WebJars?

显而易见,因为简单。但不仅是依赖这么简单:

  • 清晰的管理 web 依赖
  • 通过 Maven, Gradle 等项目管理工具就可以下载 web 依赖
  • 解决 web 组件中传递依赖的问题以及版本问题
  • 页面依赖的版本自动检测功能

WebJars是将这些通用的Web前端资源打包成Java的Jar包,然后借助Maven工具对其管理,保证这些Web资源版本唯一性,升级也比较容易。关于webjars资源,有一个专门的网站https://www.webjars.org/,我们可以到这个网站上找到自己需要的资源,在自己的工程中添加入maven依赖,即可直接使用这些资源了。

1.pom中引入依赖

我们可以从WebJars官方查看maven依赖,如下图

例如:将bootstrap和jquery引入pom文件中

<dependency>
   <groupId>org.webjars</groupId>
   <artifactId>jquery</artifactId>
   <version>3.5.1</version>
</dependency>
<dependency>
   <groupId>org.webjars</groupId>
   <artifactId>bootstrap</artifactId>
   <version>4.5.0</version>
</dependency>

2.访问引入的js文件

在html内访问静态资源可以使用如下方式:

<script src="/webjars/jquery/3.5.1/jquery.min.js "></script>
<script src="/webjars/bootstrap/4.5.0/js/bootstrap.min.js"></script>

自动检测依赖的版本

如果使用 Spring 4.2 以上的版本,并且加入 webjars-locator 组件,就不需要在 html 添加依赖的时候填写版本。

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>webjars-locator</artifactId>
    <version>0.30</version>
</dependency>

引入 webjars-locator 值后可以省略版本号:

<script src="/webjars/jquery/jquery.min.js "></script>
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script>

注意:只能去掉版本号,好处是:当你升级webjar版本的时候,就不用每个引入webjar的文件都修改一遍版本号。

简单来说,webjars可以统一的以jar包的形式管理前端的资源,这样就省去了下载前端资源文件,放到静态资源目录static目录下面的麻烦事

并且想替换版本的时候,不需要像之前删除掉旧版本的所有静态资源文件,再引进新版本那么麻烦,之前更改maven包管理里面的版本即可


测试

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
    <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css">
</head>
<body>
    <div class="container"><br/>
        <div class="alert alert-success">
            <strong>成功!</strong>bootstrap webjar 完美!
        </div>
    </div>


    <script src="/webjars/jquery/jquery.min.js "></script>
    <script src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

显示效果:bootstrap的alert-success


模板引擎选型与未来趋势

java web开发经历的几个阶段

jsp开发阶段

现在仍然有很多企业项目使用jsp开发。可以说jsp就是页面端的servlet,jsp文件糅合了三种元素:Java代码、动态的数据、HTML代码结构。从抽象层次来看,Java代码部分不仅用来组织数据,还被用来控制HTML页面结构。这样在层次划分上属于比较含糊不清的。当然企业可以通过规范的方式去限制,不允许在jsp页面写java代码,但这只是规范层面的事,实际怎样无法控制。

使用java模板引擎

在这个阶段就出现了freemarker、velocity这样的严格数据模型与业务代码分离的模板引擎。实现了严格的MVC分离,模板引擎的另外一个好处就是:宏定义或者说是组件模板,比jsp标签好用,极大的减少了重复页面组件元素的开发。另外,相对于jsp而言,模板引擎的开发效率会更高。我们都知道,JSP在第一次执行的时候需要转换成Servlet类,开发阶段进行功能调适时,需要频繁的修改JSP,每次修改都要编译和转换,那么试想一天中我们浪费在程序编译的时间有多少。

但是java模板引擎,仍然是使用的服务器端的渲染技术,也就是没有办法将html页面和后台服务层面全面解耦,这就要求前端工程师和后端工程师在同一个项目结构下工作,而且前端工程师及其依赖于后端的业务数据,页面无法脱离于后端请求数据在浏览器独立运行。


前端工程化

在ajax和nodejs相继出现之后,可以说为前端的发展带来了革命性的变化,前端可以做自己的工程化实践。这些新的前端技术通常是“所见即所得”,写完的代码可以直接在浏览器上查看,将前端后端的串行化工作模式转变为并行工作的模式。前端专注于布局、美化,后端专注于业务。专业的人越来越专业,工作效率也更高。

随着VUE、angularjs、reactjs的大行其道,开始实现真正的前后端分离技术。前端的工程师负责页面的美化与结构,后端工程师可以专注
于业务的处理。


java模板引擎的选型。

常见的模板引擎有Freemarker、Thymeleaf、Velocity等,下面我们就分别来说一下。

spring boot目前官方集成的框架只有freemarker和Thymeleaf,官方明确建议放弃velocity。很多人说thymeleaf是官方推荐使用的模板引擎,说实话我没找到这个说法的出处。

Thymeleaf:

Thymeleaf的最大优点也是他的最大的缺点,就是它使用静态html嵌入标签属性,浏览器可以直接打开模板文件,便于前后端联调。也就是贴近于“所见即所得”。但是也正是因为,thyme使用标签属性去放数据,也导致它的语法违反了程序员对于html的理解。另外Thymeleaf的性能一直为人所诟病。

Thymeleaf代码和下面freemarker对一个对象数组遍历的代码对比一下:

<tr th:each="item : $users">
    <td th:text="$item.userId"> </td>
    <td th:text="$item.username"> </td>
    <td th:text="$item.password"> </td>
    <td th:text="$item.email"> </td>
    <td th:text="$item.mobile"> </td>
</tr>

FreeMarker代码:

<#list users as item>
    <tr>
        <td>$item.userId</td>
        <td>$item.username</td>
        <td>$item.password</td>
        <td>$item.email</td>
        <td>$item.mobile</td>
    </tr>
</#list>

很明显FreeMarker更符合开发人员对于HTML的使用规范,将展示内容放在标签内,而不是作为标签属性存在。就冲这一点,就我个人而言,ThymeLeaf完全不在我的考虑范围之内。另外,ThymeLeaf2.0的性能非常差,为人所诟病,Thymeleaf3.0虽然有所改善,但是没有颠覆性的变化。


最后

综上,目前为止如果使用java模板引擎,我还是推荐freemarker。当然,我还有一个建议,去学LayUI等前端框架,或者去学vue、angularjs、reactjs,不要用纯java模板引擎,这些东西用的会越来越少。

上图是百度指数,技术的火爆程度一目了然!


web应用开发之整合jsp

通过Maven坐标集成jsp

JSP需要如下的三个依赖提供运行环境

  • 内嵌的 tomcat容器,spring-boot-starter-web 包含了spring-boot-starter-tomcat ,所以不需要再单独引入。
  • tomcat-embed-jasper 主要用来支持 JSP 的解析和运行。
  • jstl ,提供给Java Web开发人员一个标准通用的标签库。开发人员可以利用这些标签取代JSP页面上写Java代码,从而提高程序的可读性,降低程序的维护难度。
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring boot 内置tomcat jsp支持 -->
<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!--jsp页面使用jstl标签-->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>jstl</artifactId>
</dependency>

配置JSP查找位置

我们需要通过配置告诉Spring Boot在进行页面渲染的时候,去哪里寻找JSP文件

spring:
  mvc:
    view:
      suffix: .jsp
      prefix: /WEB-INF/jsp/

debug: true
  • spring.mvc.view.prefix 指明 jsp 文件在 webapp 下的哪个目录
  • spring.mvc.view.suffix 指明 jsp以什么样的后缀结尾。一定是/WEB-INF/下的目录,否则后面我们打包会报错。

这个目录结构和配置文件指定的位置对应,一定不要放错了。

  • 静态资源,如:图片放在resources/static目录下面
  • jsp文件放在webapp.WEB-INF.jsp的下面

代码测试

@Controller
@RequestMapping("/template")
public class TemplateController 

    @Resource
    ArticleService articleService;

    @GetMapping("/jsp")
    public String index(String name, Model model) 

        List<ArticleVO> articles = articleService.getAll();

        model.addAttribute("articles", articles);

        //模版名称,实际的目录为:src/main/webapp/WEB-INF/jsp/jsptemp.jsp
        return "jsptemp";
    

jsptemp.jsp

文本代码如下

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css">
</head>
<body>
<table class="table">
    <tr>
        <td>作者</td>
        <td>教程名称</td>
        <td>内容</td>
    </tr>
    <c:forEach var="article" items="$articles">
        <tr class="text-info">
            <td>$article.author</td>
            <td>$article.title</td>
            <td>$article.content</td>
        </tr>
    </c:forEach>


</table>
<img src="/image/jsp.png">

<script src="/webjars/jquery/jquery.min.js "></script>
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</body>

运行方法测试

访问:http://localhost:8888/template/jsp,因为jsp对jar运行的方式支持不好,所以要一一进行测试,结果如下:

  • 使用IDEA启动类启动测试,没有问题
  • 使用spring-boot:run -f pom.xml测试,没有问题(maven启动)
  • 打成jar包通过java -jar方式运行,页面报错
  • 打成war包,运行于外置的tomcat,没有问题

所以,目前无法用jar包的形式运行jsp应用,至少我没有实验成功。


web应用开发之整合freemarker

Freemarker简介

FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写。一般对FreeMarker第一印象是用来替代JSP的,但是与JSP 不同的是FreeMarker 模板可以在 Servlet容器之外使用。可以使用它们来生成电子邮件、 配置文件、 XML 映射等。或者可以直接生成HTML文件,以及其他的文件,用来做代码自动生成的工具。

Freemarker作为页面模板引擎的核心能力在于,将以HTML为基础的模板中的相关语法占位符用数据进行填充,填充之后形成可以被浏览器渲染的HTML文件


整合

首先通过maven坐标的方式将freemarker引入到项目中来,因为freemarker是Spring Boot父项目支持的模板引擎,所以不用加版本号,版本由父项目统一管理

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

在application.yml全局配置文件中进行如下的配置

spring:
  freemarker:
    cache: false # 缓存配置 开发阶段应该配置为false 因为经常会改
    suffix: .ftl # 模版文件后缀名 
    charset: UTF-8 # 文件编码
    template-loader-path: classpath:/templates/  

如果没有,新建static和templates文件夹


代码测试

我们这里只做一个简单的测试,测试内容是:将article数据从数据库表里面查询出来,并将查询结果List返回给前端FreeMarker模板页面,进行数据填充。

import com.zimug.boot.launch.model.ArticleVO;
import com.zimug.boot.launch.service.ArticleService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import java.util.List;

@Controller
@RequestMapping("/template")
public class TemplateController 

    @Resource
    ArticleService articleService;

    @GetMapping("/freemarker")
    public String index(Model model) 

        List<ArticleVO> articles = articleService.getAll();

        model.addAttribute("articles", articles);

        //模版名称,实际的目录为:resources/templates/fremarkertemp.ftl
        return "freemarkertemp";
    

FreeMarker模板页面,核心内容在于<#list articles as article>进行列表数据遍历。(其他内容如:HTML、webjars都不是本节需要关注的核心内容)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css">
</head>
<body>
    <div class="container">
        <table class="table">
            <tr>
                <td>作者</td>
                <td>教程名称</td>
                <td>内容</td>
            </tr>

            <#list articles as article>
                <tr>
                    <td>$article.author</td>
                    <td>$article.title</td>
                    <td>$article.content</td>
                </tr>
            </#list>
        </table>
    </div>

    <script src="/webjars/jquery/jquery.min.js "></script>
    <script src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

FreeMarker在线手册


web应用开发之整合thymeleaf

Thymeleaf简介

Thymeleaf 是一个服务器端 Java 模板引擎,能够处理 HTML、XML、CSS、javascript 等模板文件。Thymeleaf 模板可以直接当作静态原型来使用,它主要目标是为开发者的开发工作流程带来优雅的自然模板,也是 Java 服务器端 HTML5 开发的理想选择


准备工作-IDEA设置

在开始使用ThymeLeaf作为模板引擎进行页面开发之前,我们有必要对IDEA进行一些设置。这些设置帮助IDEA更好的识别ThymeLeaf语法,增强我们的开发体验

  • 安装ThymeLeaf插件,并使其生效(在绝大多数的IDEA版本该插件都是默认安装并生效的)

  • 去掉变量表达式识别检查,会造成变量红色下划线,影响开发体验


集成

使用Maven坐标将thymeleaf引入到项目中

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

对thymeleaf模板进行配置

spring:
  thymeleaf:
    cache: false # 启用缓存:建议生产开启
    check-template-location: true # 检查模版是否存在
    enabled: true # 是否启用
    encoding: UTF-8 # 模版编码
    excluded-view-names: # 应该从解析中排除的视图名称列表(用逗号分隔)
    mode: HTML5 # 模版模式
    prefix: classpath:/templates/ # 模版存放路径
    suffix: .html # 模版后缀

Hello ThymeLeaf

例子完成之后,项目代码结构如下:

查询一个articles文章列表,并返回模板名称,由Spring根据名称找到模板进行页面渲染

import com.zimug.boot.launch.model.ArticleVO;
import com.zimug.boot.launch.service.ArticleService;
import org.springframework.stereotype.Controller;

以上是关于重学SpringBoot系列之整合静态资源与模板引擎的主要内容,如果未能解决你的问题,请参考以下文章

重学SpringBoot系列之整合分布式文件系统

重学Springboot系列之整合数据库开发框架---下

重学Springboot系列之整合数据库开发框架---上

重学Springboot系列之整合数据库开发框架---中

重学SpringBoot系列之日志框架与全局日志管理

重学SpringBoot系列之EhCache缓存,缓存问题