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

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

转载声明:转载请注明出处,本技术博客是本人原创文章

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 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
         groupIdorg.springframework.boot/groupId
         artifactIdspring-boot-starter-web/artifactId
         exclusions
               exclusion
                   artifactIdspring-boot-starter-json/artifactId
                   groupIdorg.springframework.boot/groupId
               /exclusion
         /exclusions
    /dependency 
    dependency
         groupIdcom.alibaba/groupId
         artifactIdfastjson/artifactId
         version1.2.47/version
    /dependency
    

    编写转换器处理 json 的日期格式同时处理中文乱码问题。

    
    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
    
        /**
         * 自定义JSON转换器
         *
         * @param converters
         */
        @Override
        public void configureMessageConverters(ListHttpMessageConverter? converters) {
            FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
            FastJsonConfig fastJsonConfig = new FastJsonConfig();
            fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
            //日期格式化
            fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
            //处理中文乱码问题
            ListMediaType 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

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

    而对于网站图标,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 ListResource resolveFaviconLocations() {
        String[] staticLocations = getResourceLocations(
                this.resourceProperties.getStaticLocations());
        ListResource 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
         groupIdorg.webjars/groupId
         artifactIdbootstrap/artifactId
         version4.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
                groupIdorg.springframework.boot/groupId
                artifactIdspring-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"));
            ArrayListUser 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
        titleThymeleaf 的基本使用/title
        !-- 引入JS文件 --
        !--script th:src="@{/static/js/alert.js}"/script--
    /head
    body
    
    div
        pbHello 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}"
        pbHello 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
        pbText 与 utext/b/p
        !-- th:text 显示HTML源码,作为字符串 --
        span th:text="${user.username}"abc/span
        br
        span th:utext="${user.username}"abc/span
    /div
    
    div
        pbURL 的引用/b/p
        a th:href="@{https://www.baidu.com}"网站网址/a
    /div
    
    div
        pb表单的使用/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
        pb判断的使用/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
        pb选择框/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
        pb遍历功能/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
        pbSwitch功能/b/p
        div th:switch="${user.username}"
            p th:case="'admin'"欢迎管理员/p
        /div
    /div
    /body
    /html
    

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

    文章代码已经上传到 GitHub Spring Boot Web开发 - 静态资源(https://github.com/niumoo/springboot/tree/master/springboot-web-staticfile)。
    文章代码已经上传到 GitHub Spring Boot Web开发 - 模版引擎(https://github.com/niumoo/springboot/tree/master/springboot-web-template)。

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

    ▲长按图片识别二维码关注

    原文始发于微信公众号(扣钉博客):

    本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

    转载声明:转载请注明出处,本技术博客是本人原创文章

    本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

    原文链接:blog.ouyangsihai.cn >> Springboot 系列(五)Spring Boot web 开发之静态资源和模版引擎


     上一篇
    Springboot 系列(四)Spring Boot 日志框架 Springboot 系列(四)Spring Boot 日志框架
    注意:本 Spring Boot 系列文章基于 Spring Boot 版本 v2.1.1.RELEASE 进行学习分析,版本不同可能会有细微差别。 前言Spring 框架选择使用了 JCL 作为默认日志输出。而 Spring Boot
    2021-04-06
    下一篇 
    Springboot 系列(六)Spring Boot web 开发之拦截器和三大组件 Springboot 系列(六)Spring Boot web 开发之拦截器和三大组件
    1. 拦截器Springboot 中的 Interceptor 拦截器也就是 mvc 中的拦截器,只是省去了 xml 配置部分。并没有本质的不同,都是通过实现 HandlerInterceptor 中几个方法实现。几个方法的作用一一如下。
    2021-04-06