1.大概介绍:

Thymeleaf和Jsp一样是一个模板引擎,但是它有几个特点:

1.动静结合,就算没有服务器对页面进行解析(解析也就解析th:xxx),它也一样可以运行,比较友好;

2.支持html,后台的数据展示只需要在html中的标签加入额外属性,就可以达到模板+数据的展示方式;

3.对于表单的提交绑定数据,属性的编辑,国际化功能都可以比较快的完成;

4.通常情况下,前端如果想要获取后端的数据,一般都是通过Ajax发送异步请求来获取后台传输的数据,然后通过Js去处理这些数据,最后通过html方法或者是其他的将其拼接成字符串传入html标签中,最后被浏览器解析,从而更新页面数据;

而使用thymeleaf后,可以直接一步到位;

2.使用:

1.首先导入依赖spring-boot-starter-thymeleaf

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

2.thymeleaf的参数配置:

如果你需要重新定义thymeleaf的属性,可以去ThymeleafAutoConfiguration类中,然后和之前一样的操作(像xxxAutoConfiguration这种,一般都是放组件的,一些执行流程,执行方法),然后里面的值就由对应的xxxProperties(也可以理解为实体类)来解决,然后里面绑定的值根据@ConfigurationProperties(prefix="xxx")就知道了:

@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;
    private boolean cache;
    private Integer templateResolverOrder;
    private String[] viewNames;
    private String[] excludedViewNames;
    private boolean enableSpringElCompiler;
    private boolean renderHiddenMarkersBeforeCheckboxes;
    private boolean enabled;
    private final ThymeleafProperties.Servlet servlet;
    private final ThymeleafProperties.Reactive reactive;

3.控制层(简单逻辑):

1.当访问对应请求时,返回到login页面

/**
     * 来登录页
     * @return
     */
    @GetMapping(value = {"/","/login"})
    public String loginPage(){

        return "login";
    }

 输入表单信息userName与password,利用th:action="@{/login}":也就是得到一个当前项目的login请求替换前面默认的action;

<div class="container">
    <!--表单提交(也就是th:action="@{/xxx}"),服务器controller层对对应的请求进行解析-->
    <form class="form-signin" action="index.html" method="post" th:action="@{/login}">
        <div class="form-signin-heading text-center">
            <h1 class="sign-title">Sign In</h1>
            <img src="images/login-logo.png" alt=""/>
        </div>
        <div class="login-wrap">
            <!--            取出msg文本信息-->
            <label style="color: red" th:text="${msg}"></label>
            <input type="text" name="userName" class="form-control" placeholder="User ID" autofocus>
            <input type="password" name="password" class="form-control" placeholder="Password">
            <button class="btn btn-lg btn-login btn-block" type="submit">
                <i class="fa fa-check"></i>
            </button>

            <div class="registration">
                Not a member yet?
                <a class="" href="registration.html">
                    Signup
                </a>
            </div>
            <label class="checkbox">
                <input type="checkbox" value="remember-me"> Remember me
                <span class="pull-right">
                    <a data-toggle="modal" href="#myModal"> Forgot Password?</a>

                </span>
            </label>

        </div>

        <!-- Modal -->
        <div aria-hidden="true" aria-labelledby="myModalLabel" role="dialog" tabindex="-1" id="myModal"
             class="modal fade">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
                        <h4 class="modal-title">Forgot Password ?</h4>
                    </div>
                    <div class="modal-body">
                        <p>Enter your e-mail address below to reset your password.</p>
                        <input type="text" name="email" placeholder="Email" autocomplete="off"
                               class="form-control placeholder-no-fix">

                    </div>
                    <div class="modal-footer">
                        <button data-dismiss="modal" class="btn btn-default" type="button">Cancel</button>
                        <button class="btn btn-primary" type="button">Submit</button>
                    </div>
                </div>
            </div>
        </div>
        <!-- modal -->

    </form>

</div>

4.接下来我们处理这个请求:对于这个这个请求我们首先要有逻辑判断,进行简单的验证(这里不作数据库验证处理): 利用StringUtils的方法hasLength()与equals对userName与password进行验证,符合就放入session中,并且重定向到main页面,否则将错误提示信息传入请求域中并返回login页面;

@PostMapping("/login")
    public String main(User user, HttpSession session, Model model){ //RedirectAttributes

        if(StringUtils.hasLength(user.getUserName()) && "123456".equals(user.getPassword())){
            //把登陆成功的用户保存起来
            session.setAttribute("loginUser",user);
            //登录成功重定向到main.html;  重定向防止表单重复提交
            return "redirect:/main.html";
        }else {
            model.addAttribute("msg","账号密码错误");
            //回到登录页面
            return "login";
        }

    }
@GetMapping("/main.html")
    public String mainPage(HttpSession session,Model model){

        log.info("当前方法是:{}","mainPage");
        return "main";

    }

3.thymeleaf语法:

用thymeleaf处理前端时,我们常常需要将页面中的共同部分拿出来放到一个单独的页面中,这样我们可以利用thymeleaf对共同部分进行拿取;

1.th:fragment="xxx":说明这是个片段,可以在其他页面中被调用插入替换;

2.th:href="@{/css/style.css}":意思就是当前项目下的静态资源路径,static下...

th:src="@{xx/xxx}":与上述差不多,也是路径的

<head th:fragment="commonheader">
    <!--common-->
    <link href="css/style.css" th:href="@{/css/style.css}" rel="stylesheet">
    <link href="css/style-responsive.css" th:href="@{/css/style-responsive.css}" rel="stylesheet">


    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
    <script src="js/html5shiv.js" th:src="@{/js/html5shiv.js}"></script>
    <script src="js/respond.min.js" th:src="@{/js/respond.min.js}"></script>
    <![endif]-->
</head>

<div th:fragment="headermenu" class="..."> ....</div>

 Thymeleaf中的语意还需要根据具体标签来判断,像<link>标签这种里面的th:href,th:src...都只是引入资源;

像如果在<a>标签中的th:href,那就是点击请求,让服务器处理请求的;

<li class="menu-list nav-active"><a href="#"><i class="fa fa-th-list"></i> <span>Data Tables</span></a>
                <ul class="sub-menu-list">
                    <li><a th:href="@{/basic_table}"> Basic Table</a></li>
                    <li><a th:href="@{/dynamic_table}"> Advanced Table</a></li>
                    <li><a th:href="@{/responsive_table}"> Responsive Table</a></li>
                    <li><a th:href="@{/editable_table}"> Edit Table</a></li>
                </ul>
            </li>

当点击这些a标签后,控制器中对应的方法会接收到对应的请求,然后显示对应页面;

这里提一下@RequestParam中的参数:defaultValue:有0、1两种形式,0:地址不需要参数,1:需要带参数;默认defaultValue为1;

@GetMapping("/dynamic_table")
public String dynamic_table(@RequestParam(value="pn",defaultValue="1")Integer pn,Model model){
   //简单遍历表单内容
    List<User>user=Arrays.asList(new User("zhangsan","12345"),
new User("Fairy","1233"));

   model.addAttribute("users",users);
return "table/dynamic_table";//因为thymeleaf的suffix与prefix已经设定好了,而这个页面是在Template下面一个等级的
}
 @GetMapping("/responsive_table")
    public String responsive_table() {
        return "table/responsive_table";
    }

    @GetMapping("/editable_table")
    public String editable_table() {
        return "table/editable_table";
    }
}

抽取公共元素:

 一般来说,我们对公共代码代码块需要使用thymeleaf进行统一命名:th:fragment="xxx",或者在标签中用id

<div id=leftmenu class="xxx">xxx</div>
<script th:fragment>xxx</script>

其他页面中插入公共部分:

三种方式:代替:整个标签容器连同内容一起代替

包括:只替换内容,不替换标签

插入:将公共部分的标签及其内容插入到当前页面标签下(可能会多出不要的标签)

<div th:replace="common :: headermenu"></div>
<div th:include="common :: leftmenu"></div>
<div th:insert="common :: xxx"></div>

5.视图解析的原理流程:

1.当前请求被目标方法处理的过程中,所有数据分为了两个部分:数据and视图地址。他们会被放在·ModelAndViewContainer中;

2.任何方法执行完后都会返回ModelAndView,然后processDispatcherResult会处理派发结果(页面如何响应)

最关键的:render()方法,进行页面渲染逻辑,根据方法的返回值得到View对象;

1.然后遍历所有的视图解析器看能否根据返回值得到View对象

2.得到redirect:/main.html

3.内容协商视图解析器ContentNegotiationViewResolver里面包含了所有视图解析器,利用视图解析器得到视图对象(可以自定义)

4.view.render(modelAndview,req,resp):首先获取请求的url地址,然后resp.sendRedirect(url);