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

                                                          访问测试

相关文章
|
9月前
|
缓存 安全 Java
《深入理解Spring》过滤器(Filter)——Web请求的第一道防线
Servlet过滤器是Java Web核心组件,可在请求进入容器时进行预处理与响应后处理,适用于日志、认证、安全、跨域等全局性功能,具有比Spring拦截器更早的执行时机和更广的覆盖范围。
|
9月前
|
前端开发 Java 应用服务中间件
《深入理解Spring》 Spring Boot——约定优于配置的革命者
Spring Boot基于“约定优于配置”理念,通过自动配置、起步依赖、嵌入式容器和Actuator四大特性,简化Spring应用的开发与部署,提升效率,降低门槛,成为现代Java开发的事实标准。
|
9月前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
9月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
650 4
|
9月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
787 2
|
10月前
|
人工智能 Java 机器人
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
Spring AI Alibaba集成Ollama,基于Java构建本地大模型应用,支持流式对话、knife4j接口可视化,实现高隐私、免API密钥的离线AI服务。
7367 2
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
存储 JSON Java
978 0
|
10月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
2986 0
|
前端开发 Java Maven
Spring 和 Spring Boot 之间的比较
本文对比了标准Spring框架与Spring Boot的区别,重点分析两者在模块使用(如MVC、Security)上的差异。Spring提供全面的Java开发基础设施支持,包含依赖注入和多种开箱即用的模块;而Spring Boot作为Spring的扩展,通过自动配置、嵌入式服务器等功能简化开发流程。文章还探讨了两者的Maven依赖、Mvc配置、模板引擎配置、启动方式及打包部署等方面的异同,展示了Spring Boot如何通过减少样板代码和配置提升开发效率。总结指出,Spring Boot是Spring的增强版,使应用开发、测试与部署更加便捷高效。
1786 11