zoukankan      html  css  js  c++  java
  • SpringBoot:模板引擎 thymeleaf、ContentNegotiatingViewResolver、格式化转换器

    模板引擎 thymeleaf、ContentNegotiatingViewResolver视图解析器(内容协商视图解析器)、格式化转换器

    模板引擎 thymeleaf

    SpringBoot给我们推荐的Thymeleaf,模板引擎有非常多,但再多的模板引擎,他们的思想都是一样的,什么样一个思想呢我们来看一下这张图。

    1418974.png

    模板引擎的使用:是为了实现数据分离(动态数据与静态数据)和代码重用

    1、Thymeleaf 官网
    2、Github 
    3、Spring官方文档

    thymeleaf 的依赖:

    <!--thymeleaf模板-->
    <dependency>
      <groupId>org.thymeleaf</groupId>
      <artifactId>thymeleaf-spring5</artifactId>
    </dependency>
    
    <dependency>
      <groupId>org.thymeleaf.extras</groupId>
      <artifactId>thymeleaf-extras-java8time</artifactId>
    </dependency>
    

    我们要使用thymeleaf,需要在html文件中导入命名空间的约束,

    <html xmlns:th="http://www.thymeleaf.org">
    

    Thymeleaf 的配置类

    1582264270113.png

    @ConfigurationProperties(
        prefix = "spring.thymeleaf"
    )
    public class ThymeleafProperties {
        private static final Charset DEFAULT_ENCODING;
        public static final String DEFAULT_PREFIX = "classpath:/templates/";
        public static final String DEFAULT_SUFFIX = ".html";
        private boolean checkTemplate = true;
        private boolean checkTemplateLocation = true;
        private String prefix = "classpath:/templates/";
        private String suffix = ".html";
        private String mode = "HTML";
        private Charset encoding;
    }
    

    我们可以在其中看到默认的前缀和后缀!我们只需要把我们的html页面放在类路径下的templates下,thymeleaf就可以帮我们自动渲染了。

    thymeleaf语法

    我们可以使用任意的 th:* 来替换Html中原生属性的值

    1197701508.png

    // 常用的标签	#4
    Variable Expressions: ${...}:获取变量值、获取对象的属性、调用方法;
    Message Expressions: #{...}:获取国际化内容;
    Link URL Expressions: @{...}:定义URL;
    <link th:href="@{/css/dashboard.css}" rel="stylesheet">
    <script th:src="@{/js/jquery-3.2.1.slim.min.js}"></script>
    
    Fragment Expressions: ~{...}:片段引用表达式
    <div th:insert="~{commons :: main}">...</div>
    
    // 常用的运算符
    Boolean operations:(布尔运算)
        Binary operators: and , or
        Boolean negation (一元运算符): ! , not
    
    
    Comparisons and equality:(比较运算)
        Comparators: > , < , >= , <= ( gt , lt , ge , le )
        Equality operators: == , != ( eq , ne )
          
    Arithmetic operations:(数学运算)
        Binary operators: + , - , * , / , %
        Minus sign (unary operator): -
          
    Text operations:(文本操作)
        String concatenation: +
        Literal substitutions: |The name is ${name}|
          
    Conditional operators:条件运算(三元运算符)
        If-then: (if) ? (then)
        If-then-else: (if) ? (then) : (else)
        Default: (value) ?: (defaultvalue)
    
    // ======================================
    
    Literals(字面量)
          Text literals: 'one text' , 'Another one!' ,…
          Number literals: 0 , 34 , 3.0 , 12.3 ,…
          Boolean literals: true , false
          Null literal: null
          Literal tokens: one , sometext , main ,…
    
    Special tokens:
        No-Operation: _ 
    
    // ======================================
    Selection Variable Expressions: *{...}:选择表达式:和${}在功能上是一样;
       补充:配合 th:object="${session.user}:
    
       <div th:object="${session.user}">
        <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
        <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
        <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
        </div>
    
    // =======================================
    // 内置的工具对象	#19
    
    #execInfo :有关正在处理的模板的信息。
    #messages :在变量表达式中获取外部化消息的方法,与使用{{…}语法获取外部化消息的方法相同。
    #uri:转义部分url/uri的方法
    #conversions :执行配置的转换服务(如果有的话)的方法。
    #dates :java.util.Date对象的方法:格式化、组件提取等。
    #calendars :类似于日期,但适用于java.util.Calendar对象。
    #numbers :格式化数字对象的方法。
    #strings :字符串对象的方法:contains、startsWith、prepending/appending等。
    #objects :通常用于对象的方法。
    #bools:布尔求值的方法。
    #arrays :数组的方法。
    #lists:列表的方法。
    #sets :集合的方法。
    #maps :Map的方法。
    #aggregates :在数组或集合上创建聚合的方法。
    #ids:处理可能重复的id属性的方法(例如,作为迭代的结果)。
    
    // 内置的基本对象: #18
    #ctx : the context object.
    #vars: the context variables.
    #locale : the context locale.
    #request : (only in Web Contexts) the HttpServletRequest object.
    #response : (only in Web Contexts) the HttpServletResponse object.
    #session : (only in Web Contexts) the HttpSession object.
    #servletContext : (only in Web Contexts) the ServletContext object.
    

    很多样式,我们即使现在学习了,也会忘记,所以我们在学习过程中,需要使用什么,根据官方文档来查询,才是最重要的,要熟练使用官方文档!

    简单使用:

    th:each

    • controller
    @GetMapping("/emps")
    public String list(Model model) {
    
      Collection<Employee> emps = employeeDao.getAllEmployee();
      model.addAttribute("emps", emps);
    
      return "emp/list";
    }
    

    1582269235830.png

    • list.html

    1582269329503.png

    th:fragment

    • bar.html
    <!--导航栏-->
    <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
        <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" th:text="${session.loginUser}"></a>
        <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
        <ul class="navbar-nav px-3">
            <li class="nav-item text-nowrap">
                <a class="nav-link" th:href="@{/user/logout}">注销</a>
            </li>
        </ul>
    </nav>
    

    1582291404023.png

    <div th:replace="~{commons/bar::topbar}"></div>
    

    ContentNegotiatingViewResolver

    目的:看看该 ContentNegotiatingViewResolver 视图解析器作用

    首先在 WebMvcAutoConfiguration 找到注册的 Bean

    @Bean
    @ConditionalOnBean(ViewResolver.class)
    @ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)
    public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
       ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
       resolver.setContentNegotiationManager(beanFactory.getBean(ContentNegotiationManager.class));
      	// ContentNegotiatingViewResolver使用所有其他视图解析器来定位
        // 设置该视图为较高的优先级
       resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
       return resolver;
    }
    

    点进 ContentNegotiatingViewResolver

    1582287785274.png

    找到对应的解析视图的代码:resolveViewName()

    注解说明:@Nullable 即参数可为null

    1582286625610.png

    点进去

    1582286852497.png

    1582287445079.png

    由此可得结论:ContentNegotiatingViewResolver 这个视图解析器就是用来组合所有的视图解析器的

    继续往下看 getCandidateViews()方法

    1582288939064.png

    getBestView()方法

    1582289310798.png

    最终上述我们获得的视图都会返回到 调用者处。即 DiapatcherServlet 的 resolverViewName()方法

    1582290418316.png

    简要的调用关系如下:

    ViewResolver.png

    因此,如果我要自定义视图解析器,需要首先实现 ViewResolver 接口,然后再将实现了该接口的类交给 Spring 的 Ioc 容器托管,使之成为一个 Bean。

    public class MyViewResolver implements ViewResolver {
        @Override
        public View resolveViewName(String viewName, Locale locale) throws Exception {
            return null;
        }
    }
    
    @Configuration
    public class MyMvcConfig implements WebMvcConfigurer {
      	// 在容器中注册 bean
        @Bean
        public ViewResolver myViewResolver() {
            return new MyViewResolver();
        }
    
    }
    

    如何检验我们写的视图解析器起效了?

    在DispathcerServlet类的 doDispatch()方法内 Debug一下即可:

    1582270635554.png

    1582270545388.png

    ContentNegotiatingViewResolverViewResolver 的实现类,该解析基于 请求文件名(也就是:文件扩展名) 或请求头  Accept 解析视图。

    ContentNegotiatingViewResolver 不会自行解析视图,而是委托给其他 ViewResolvers。

    默认情况下,这些其他视图解析器会从应用程序上下文中自动获取。

    此视图解析器通过配置的 ContentNegotiationManager 确定请求的媒体类型(也就是Mime 类型)。

    确定请求的媒体类型后,此解析器向每个委托视图解析器查询 View,并确定请求的媒体类型是否与视图的 MediaType 兼容。返回最兼容的视图。

    请注意,这些默认视图是作为候选者提供的,但仍需要具有请求的内容类型(通过文件扩展名,参数,Accept 请求头)。

    例如,如果请求路径为:localhost:8080/view.html,则此视图解析器将查找具有  text / html内容类型。如果请求头是:Accept: text/html ;也具有相同的结果。

    格式化转换器

    WebMvcAutoConfiguration中:

    @Bean
    @Override
    public FormattingConversionService mvcConversionService() {
       WebConversionService conversionService = new WebConversionService(this.mvcProperties.getDateFormat());
       addFormatters(conversionService);
       return conversionService;
    }
    

    点击:getDateFormat()

    1582292497247.png

    发现SpringBoot默认的日期格式为:dd/MM/yyyy

    我们可以在配置文件中配置日期格式化的规则,如果我们没配,会使用SpringBoot默认的日期格式。

    • application.yaml
    # 自定义日期格式化
    spring.mvc.date-format=yyyy-MM-dd
    

    1582292699691.png

  • 相关阅读:
    [转]TOP 1比不加TOP慢的疑惑
    .ETL构建数据仓库五步法
    MySQL与Oracle的语法区别
    MySQL的表分区
    ORACLE分区表的使用和管理
    Oracle与MySQL的几点区别
    数据仓库超级大表分区方式改变
    Windows平台下MySQL常用操作与命令
    PowerDesigner使用教程 —— 概念数据模型
    MYSQL千万级数据量的优化方法积累
  • 原文地址:https://www.cnblogs.com/rainszj/p/12730712.html
Copyright © 2011-2022 走看看