Springboot 系列(五)Spring Boot web 开发之静态资源和模版引擎
前言
Spring Boot 天生的适合 web 应用开发,它可以快速的嵌入 Tomcat, Jetty 或 Netty 用于包含一个 HTTP 服务器。且开发十分简单,只需要引入 web 开发所需的包,然后编写业务代码即可。
自动配置原理?
在进行 web 开发之前让我再来回顾一下自动配置,可以参考系列文章第三篇。Spring Boot 为 Spring MVC 提供了自动配置,添加了如下的功能:
- 视图解析的支持。
- 静态资源映射,WebJars 的支持。
- 转换器 Converter 的支持。
- 自定义 Favicon 的支持。
- 等等
在引入每个包时候我们需要思考是如何实现自动配置的,以及我们能自己来配置哪些东西,这样开发起来才会得心应手。
关于 Spring Boot Web 开发的更详细介绍可以参考官方文档。
1. JSON 格式转换
Spring Boot 默认使用 Jackson 进行 JSON 化处理,如果想要切换成 FastJson 可以首先从官方文档里查询信息。从这里知道对于 ResponseBody 的渲染主要是通过 HttpMessageConverters, 而首先引入FastJson Pom依赖并排除 Spring Boot 自带的 Jackson。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-json</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
编写转换器处理 json 的日期格式同时处理中文乱码问题。
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/**
* 自定义JSON转换器
*
* @param converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
//日期格式化
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
//处理中文乱码问题
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
converter.setSupportedMediaTypes(fastMediaTypes);
converter.setFastJsonConfig(fastJsonConfig);
converters.add(converter);
}
}
2. 静态资源映射
By default, Spring Boot serves static content from a directory called
/static(or/publicor/resourcesor/META-INF/resources) in the classpath or from the root of theServletContext.
2.1 默认映射
官方文档告诉我们 Spring Boot 对于静态资源的映射目录是 /static , /public , /resources 以及 /META-INF/resource。除此之外其实还映射了 /webjars/** 到 classpath:/META-INF/resources/webjars。
很明显此处是自动配置实现的,通过查看源码分析这段配置。


而对于网站图标,Spring Boot 也已经配置了默认位置,可以在看到。
// path: org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
@Bean
public SimpleUrlHandlerMapping faviconHandlerMapping() {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
mapping.setUrlMap(Collections.singletonMap("**/favicon.ico", // 图表
faviconRequestHandler()));
return mapping;
}
@Bean
public ResourceHttpRequestHandler faviconRequestHandler() {
ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
requestHandler.setLocations(resolveFaviconLocations());
return requestHandler;
}
private List<Resource> resolveFaviconLocations() {
String[] staticLocations = getResourceLocations(
this.resourceProperties.getStaticLocations());
List<Resource> locations = new ArrayList<>(staticLocations.length + 1);
Arrays.stream(staticLocations).map(this.resourceLoader::getResource)
.forEach(locations::add);
locations.add(new ClassPathResource("/"));
return Collections.unmodifiableList(locations);
}
根据 Spring Boot 默认的静态资源映射规则,可以直接把需要的静态资源放在响应的文件夹下然后直接引用即可。

而放在 Public 文件夹下的 HTML 页面也可以直接访问。

2.2 webjars
webjars 的思想是把静态资源打包到 Jar 包中,然后使用 JVM 构建工具进行管理,如 maven , Gradle 等。
使用 webjars 第一步需要进入依赖,如要使用 bootstrap。
<!-- Web Jars 静态资源文件 -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.1.3</version>
</dependency>
引入之后查看 bootstrap 资源。

由于 Springboot 映射了 /webjars/** 到 classpath:/META-INF/resources/webjars. 因此可以直接在文件中引用 webjars 的静态资源。
<!-- Bootstrap core CSS -->
<link href="/webjars/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet">
<script src="/webjars/bootstrap/4.1.3/js/bootstrap.min.js"></script>
3. 模版引擎
Spring MVC 支持各种模版技术,如 Thymeleaf , FreeMarker , JSP 等。而Thyemeleaf 原型即页面的特性或许更符合 Spring Boot 快速开发的思想而被官方推荐。

Thymeleaf 是适用于 Web 开发的服务端 Java 模版引擎,Thymeleaf 为开发工作流程带来优雅自然的模版,由于其非侵入的特性,可以让页面不管是在静态原型下还是用作模版引擎时都有良好的页面展现。
<table>
<thead>
<tr>
<th th:text="#{msgs.headers.name}">Name</th>
<th th:text="#{msgs.headers.price}">Price</th>
</tr>
</thead>
<tbody>
<tr th:each="prod: ${allProducts}">
<td th:text="${prod.name}">Oranges</td>
<td th:text="${#numbers.formatDecimal(prod.price, 1, 2)}">0.99</td>
</tr>
</tbody>
</table>
3.1 引入 Thymeleaf
<!-- thymeleaf 模版-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
3.2 使用 Thymeleaf
根据 Spring Boot 自动配置原理,先看一下 Thymeleaf 的配置类,从中可以看出 Thymeleaf 的相关配置。我们可以知道 默认存放目录是 templates 文件夹,文件后缀为 .html 且开启了缓存。
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
/**
* Whether to enable template caching.
*/
private boolean cache = true;
为了在开发中编写模版文件时不用重启,可以在配置中关闭缓存。
# 关闭模版缓存
spring.thymeleaf.cache=false
# 如果需要进行其他的配置,可以参考配置类:ThymeleafProperties
# org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties
编写 Controller 响应信息。
/**
* 获取ID为1的用户信息
*
* @return
*/
@GetMapping(value = "/user/1")
public String getUserById(Model model) {
User user1 = new User("Darcy", "password", 24, new Date(), Arrays.asList("Java", "GoLang"));
User user2 = new User("Chris", "password", 22, new Date(), Arrays.asList("Java", "Web"));
ArrayList<User> userList = new ArrayList<>();
userList.add(user1);
userList.add(user2);
model.addAttribute("userList", userList);
model.addAttribute("user", user1);
return "user";
}
因为 Thymelaf 默认模版位置在 templates 文件夹下,因此在这个文件夹下编写页面信息。
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Thymeleaf 的基本使用</title>
<!-- 引入JS文件 -->
<!--<script th:src="@{/static/js/alert.js}"></script>-->
</head>
<body>
<div>
<p><b>Hello Thymeleaf Index</b></p>
用户名称:<input th:id="${user.username}" th:name="${user.username}" th:value="${user.username}">
<br/>
用户技能:<input th:value="${user.skills}">
<br/>
用户年龄:<input th:value="${user.age}">
<br/>
用户生日:<input th:value="${#dates.format(user.birthday,'yyyy-MM-dd hh:mm:ss ')}">
</div>
<div th:object="${user}">
<p><b>Hello Thymeleaf Index</b></p>
用户名称:<input th:id="*{username}" th:name="*{username}" th:value="*{username}">
<br/>
用户技能:<input th:value="*{skills}">
<br/>
用户年龄:<input th:value="*{age}">
<br/>
用户生日:<input th:value="*{#dates.format(birthday,'yyyy-MM-dd hh:mm:ss')}">
</div>
<div>
<p><b>Text 与 utext</b></p>
<!-- th:text 显示HTML源码,作为字符串 -->
<span th:text="${user.username}">abc</span>
<br>
<span th:utext="${user.username}">abc</span>
</div>
<div>
<p><b>URL 的引用</b></p>
<a th:href="@{https://www.baidu.com}">网站网址</a>
</div>
<div>
<p><b>表单的使用</b></p>
<form th:action="@{/th/postform}" th:object="${user}" method="post">
用户名称:<input type="text" th:field="*{username}">
<br/>
用户技能:<input type="text" th:field="*{skills}">
<br/>
用户年龄:<input type="text" th:field="*{age}">
<input type="submit">
</form>
</div>
<div>
<p><b>判断的使用</b></p>
<div th:if="${user.age} == 18">18岁了</div>
<div th:if="${user.age} gt 18">大于18岁</div>
<div th:if="${user.age} lt 18">小于18岁</div>
<div th:if="${user.age} ge 18">大于等于</div>
<div th:if="${user.age} le 18">小于等于</div>
</div>
<div>
<p><b>选择框</b></p>
<select>
<option>请选择一本书</option>
<option th:selected="${user.username eq 'admin'}">管理员</option>
<option th:selected="${user.username eq 'Darcy'}">Darcy</option>
<option th:selected="${user.username eq 'Chris'}">Chris</option>
</select>
</div>
<div>
<p><b>遍历功能</b></p>
<table>
<tr>
<th>用户名称</th>
<th>年龄</th>
<th>技能</th>
</tr>
<tr th:each="u:${userList}">
<td th:text="${u.username}"></td>
<td th:text="${u.age}"></td>
<td th:text="${u.skills}"></td>
</tr>
</table>
</div>
<div>
<p><b>Switch功能</b></p>
<div th:switch="${user.username}">
<p th:case="'admin'">欢迎管理员</p>
</div>
</div>
</body>
</html>
访问页面可以看到数据正常显示。

文章代码已经上传到 GitHub Spring Boot Web开发 - 静态资源。
文章代码已经上传到 GitHub Spring Boot Web开发 - 模版引擎。
<完>
本文原发于个人博客:https://www.codingme.net 转载请注明出处

Springboot 系列(五)Spring Boot web 开发之静态资源和模版引擎的更多相关文章
- Springboot 系列(六)Spring Boot web 开发之拦截器和三大组件
1. 拦截器 Springboot 中的 Interceptor 拦截器也就是 mvc 中的拦截器,只是省去了 xml 配置部分.并没有本质的不同,都是通过实现 HandlerInterceptor ...
- Springboot 系列(七)Spring Boot web 开发之异常错误处理机制剖析
前言 相信大家在刚开始体验 Springboot 的时候一定会经常碰到这个页面,也就是访问一个不存在的页面的默认返回页面. 如果是其他客户端请求,如接口测试工具,会默认返回JSON数据. { &quo ...
- spring boot系列(二)spring boot web开发
json 接口开发 在以前的spring 开发的时候需要我们提供json接口的时候需要做如下配置: 1 添加jackjson等jar包 2 配置spring controller扫描 3 对接的方法添 ...
- SpringBoot系列:Spring Boot使用模板引擎FreeMarker
一.Java模板引擎 模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档. 在jav ...
- SpringBoot系列:Spring Boot使用模板引擎Thymeleaf
一.Java模板引擎 模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档. 在jav ...
- SpringBoot系列:Spring Boot使用模板引擎JSP
一.Java模板引擎 模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档. 在jav ...
- Spring Boot Web 开发注解篇
本文提纲 1. spring-boot-starter-web 依赖概述 1.1 spring-boot-starter-web 职责 1.2 spring-boot-starter-web 依赖关系 ...
- 四、Spring Boot Web开发
四.Web开发 1.简介 使用SpringBoot: 1).创建SpringBoot应用,选中我们需要的模块: 2).SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可 ...
- SpringBoot系列:Spring Boot集成Spring Cache,使用RedisCache
前面的章节,讲解了Spring Boot集成Spring Cache,Spring Cache已经完成了多种Cache的实现,包括EhCache.RedisCache.ConcurrentMapCac ...
随机推荐
- Asp.Net 中Grid详解两种方法使用LigerUI加载数据库数据填充数据分页
1.关于LigerUI: LigerUI 是基于jQuery 的UI框架,其核心设计目标是快速开发.使用简单.功能强大.轻量级.易扩展.简单而又强大,致力于快速打造Web前端界面解决方案,可以应用于. ...
- css3新增动画
1.transiition过渡:样式改变就会执行transition (1)格式:transiition:1s width linear,2s 1s height; (2)参数: transition ...
- 兄弟俩畅游Tomcat城市的SpringMVC科技园区
Tomcat城市 Tomcat这座城市的历史相当悠久了,经历过几次大的变迁后,呈现出非常明显的地域特征. 从城市往西走,过了城乡结合部以后,可以说是满目疮痍.一片破败,这就是Servlet地区,这座城 ...
- 【重学计算机】操作系统D4章:设备管理
1. IO的控制方式 演进过程:轮询 --> 中断 --> DMA --> IO通道 经典布局:南北桥 PS:详见<计算机组成原理> 2. IO的实现 软件实现层次:硬件 ...
- win10安装gitLab
从控制面板选择hyper-V进行安装 1.打开控制面板选择程序=>选择启用或关闭windows功能=>选择Hyper-v 安装ubuntu 1.下载ubuntu系统(本次安装为18.04. ...
- 什么是ZooKeeper?
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 上次写了一篇 什么是消息队列?以后,本来想入门一下K ...
- Docker镜像细节
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾前面: 为什么需要Docker? Docker入 ...
- Asp.Net Core 轻松学-多线程之Task(补充)
前言 在上一章 Asp.Net Core 轻松学-多线程之Task快速上手 文章中,介绍了使用Task的各种常用场景,但是感觉有部分内容还没有完善,在这里补充一下. 1. 任务的等待 在使用 ...
- MySQL8.0新特性——支持原子DDL语句
MySQL 8.0开始支持原子数据定义语言(DDL)语句.此功能称为原子DDL.原子DDL语句将与DDL操作关联的数据字典更新,存储引擎操作和二进制日志写入组合到单个原子事务中.即使服务器在操作期间暂 ...
- Linux下使用ntpdate进行时间同步
转摘自Linux下使用ntpdate进行时间同步https://www.cnblogs.com/zhi-leaf/p/6281549.html1.安装ntpdate,执行以下命令 # yum inst ...