Springboot 系列(五)Spring Boot web 开发之静态资源和模版引擎

简介: 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 /public or /resources or /META-INF/resources) in the classpath or from the root of the ServletContext.


2.1 默认映射


官方文档告诉我们 Spring Boot 对于静态资源的映射目录是 /static , /public , /resources 以及 /META-INF/resource。除此之外其实还映射了 /webjars/**classpath:/META-INF/resources/webjars


很明显此处是自动配置实现的,通过查看源码分析这段配置。

微信图片_20220413133318.jpg    Mvc静态资源映射

微信图片_20220413133321.jpg

                                                     静态资源映射


而对于网站图标,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 默认的静态资源映射规则,可以直接把需要的静态资源放在响应的文件夹下然后直接引用即可。

微信图片_20220413133451.jpg

                                                   静态资源映射


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

微信图片_20220413133508.jpg

                                                  静态资源映射


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 资源。

微信图片_20220413133546.png

                                        WebJars 引入 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 快速开发的思想而被官方推荐。

微信图片_20220413133628.png

                                               模版引擎原理


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>


访问页面可以看到数据正常显示。


微信图片_20220413133715.png

                                                          访问测试

相关文章
|
20天前
|
数据库 开发者 Python
web应用开发
【9月更文挑战第1天】web应用开发
34 1
|
8天前
|
数据可视化 图形学 UED
只需四步,轻松开发三维模型Web应用
为了让用户更方便地应用三维模型,阿里云DataV提供了一套完整的三维模型Web模型开发方案,包括三维模型托管、应用开发、交互开发、应用分发等完整功能。只需69.3元/年,就能体验三维模型Web应用开发功能!
32 8
只需四步,轻松开发三维模型Web应用
|
7天前
|
缓存 前端开发 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版)
|
7天前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
7天前
|
Java 数据库连接 Maven
Spring基础1——Spring(配置开发版),IOC和DI
spring介绍、入门案例、控制反转IOC、IOC容器、Bean、依赖注入DI
Spring基础1——Spring(配置开发版),IOC和DI
|
17天前
|
数据采集 Java 数据挖掘
Java IO异常处理:在Web爬虫开发中的实践
Java IO异常处理:在Web爬虫开发中的实践
|
19天前
|
前端开发 安全 Java
技术进阶:使用Spring MVC构建适应未来的响应式Web应用
【9月更文挑战第2天】随着移动设备的普及,响应式设计至关重要。Spring MVC作为强大的Java Web框架,助力开发者创建适应多屏的应用。本文推荐使用Thymeleaf整合视图,通过简洁的HTML代码提高前端灵活性;采用`@ResponseBody`与`Callable`实现异步处理,优化应用响应速度;运用`@ControllerAdvice`统一异常管理,保持代码整洁;借助Jackson简化JSON处理;利用Spring Security增强安全性;并强调测试的重要性。遵循这些实践,将大幅提升开发效率和应用质量。
45 7
|
15天前
|
缓存 Java 应用服务中间件
随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架
【9月更文挑战第6天】随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架。Nginx作为高性能的HTTP反向代理服务器,常用于前端负载均衡,提升应用的可用性和响应速度。本文详细介绍如何通过合理配置实现Spring Boot与Nginx的高效协同工作,包括负载均衡策略、静态资源缓存、数据压缩传输及Spring Boot内部优化(如线程池配置、缓存策略等)。通过这些方法,开发者可以显著提升系统的整体性能,打造高性能、高可用的Web应用。
44 2
|
17天前
|
NoSQL 前端开发 Java
使用 Spring Boot + Neo4j 实现知识图谱功能开发
在数据驱动的时代,知识图谱作为一种强大的信息组织方式,正逐渐在各个领域展现出其独特的价值。本文将围绕使用Spring Boot结合Neo4j图数据库来实现知识图谱功能开发的技术细节进行分享,帮助读者理解并掌握这一技术栈在实际项目中的应用。
80 4
|
19天前
|
安全 Java 开发者
强大!Spring Cloud Gateway新特性及高级开发技巧
在微服务架构日益盛行的今天,网关作为微服务架构中的关键组件,承担着路由、安全、监控、限流等多重职责。Spring Cloud Gateway作为新一代的微服务网关,凭借其基于Spring Framework 5、Project Reactor和Spring Boot 2.0的强大技术栈,正逐步成为业界的主流选择。本文将深入探讨Spring Cloud Gateway的新特性及高级开发技巧,助力开发者更好地掌握这一强大的网关工具。
72 6