前言
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/public
or/resources
or/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 ...
随机推荐
-
ormlite的使用方法
ormlite是什么? 简单来说,就是我们定义一个实体类,利用这个框架,它可以帮我们吧这个实体映射到我们的数据库中,在Android中是SQLite,数据中的字段就是我们定义实体的成员变量. 官网地址 ...
-
jquery.SuperSlide.2.1.2--轮播(兼容到IE7 适用于整屏)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...
-
block_dump观察Linux IO写入的具体文件(mysqld)
一.使用方法: 二.基本原理: 三.总结 很多情况下开发者调测程序需要在Linux下获取具体的IO的状况,目前常用的IO观察工具用vmstat和iostat,具体功能上说当然是iostat更胜一筹 ...
-
aliyun.com
https://help.aliyun.com/knowledge_detail/39495.html?spm=5176.7839494.2.1.AhdvPM
-
微信iOS客户端升级内核对自定义分享的影响
上周,业务同学反应,公司的商品详情页,在有的Iphone手机上自定义分享信息失效.在自己手机上一直无法重现,在一个同事的手机上也重现了. 后来看到<微信iOS客户端将升级为WKWebview内核 ...
-
关于 asp.net 点击确定按钮 获取不到新值问题
点击事件内,可以使用request.form[" kk"] 获取到值,但是this.txt.Text 确实旧值, 尼玛,居然没加isPostBack重新加载了数据 ,request ...
-
js对象以及DOM
JavaScript的对象 在JavaScript中除了null和undefined以外其他的数据类型都被定义成了对象,也可以用创建对象的方法定义变量,String.Math.Array.Date.R ...
-
Android导航抽屉-Navigation Drawer
Google今年七月份的时候更新了他们的Google+应用,采用了新的导航方式并抛弃了navigationdrawer.一时之间,又引发了一系列关于NavigationDrawer利弊的讨论,不过对于 ...
-
ad采样后幅度的衰减
adc采集到的信号对低频有一定的衰减.因为要确定衰减的程度.通过da输出到示波器上观察. 数据如下: 输入 输出(enable) 输出(disable) 1v(20hz) 1v 0.88v 1v(10 ...
-
count_char
import java.util.Scanner; public class count_char { public static void main(String args[]) { int cou ...