Spring Boot 框架学习笔记(三)(Web开发 & thymeleaf使用 )

九. SpringBoot Web开发

1.引入静态资源

  • 打开WebMvcAutoConfiguration,查看导入静态资源源码:
//配置本地资源映射路径
 public void addResourceHandlers(ResourceHandlerRegistry registry) {
 			//如果静态资源已经自定义,直接返回
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
          		//第一种方法:wenjars引入依赖,路径映射
                this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
                //第二种方法:放于指定文件路径下识别
                this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
                    registration.addResourceLocations(this.resourceProperties.getStaticLocations());
                    if (this.servletContext != null) {
                        ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
                        registration.addResourceLocations(new Resource[]{resource});
                    }

                });
            }
        }
第一种方法:webjars(很少使用)

由上述代码可知,引入webjars.org下的依赖,路径8080/webjars会对应本地依赖库中的路径:
在这里插入图片描述
访问:
在这里插入图片描述

第二种方法,映射指定路径文件(默认使用static)

点击mvcProperties.getStaticPathPattern()查看mvcProperties源码:
private String staticPathPattern = "/**";
默认情况下SpringBoot是帮我们映射的路径是 /** ,如果想要做登录拦截的话,可以在配置文件application.properties中给所有静态资源添加一个前缀统一拦截

再点击resourceProperties.getStaticLocations()查看resourceProperties源码:

  private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
     private String[] staticLocations;
     public Resources() {
        this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
     }

发现这四种路径满足
所以我们可以按此代码中的路径新建文件

所以,有四个位置可以建立静态资源导入路径:
在这里插入图片描述

这四个位置优先级与其在源码中先后顺序一致
new String[] {"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"}

2.定制首页

源码:

@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) { 
	  //处理welcomepage的映射
      WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
    welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
      welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
      return welcomePageHandlerMapping;
        }
private Resource getWelcomePage() {
	//从配置文件中找到静态资源路径并遍历路径数组
    String[] var1 = this.resourceProperties.getStaticLocations();
    int var2 = var1.length;

    for(int var3 = 0; var3 < var2; ++var3) {
        String location = var1[var3];
        Resource indexHtml = this.getIndexHtml(location);
        if (indexHtml != null) {
            return indexHtml;
        }
    }

    ServletContext servletContext = this.getServletContext();
    if (servletContext != null) {
        return this.getIndexHtml((Resource)(new ServletContextResource(servletContext, "/")));
    } else {
        return null;
    }
}

//映射到首页
private Resource getIndexHtml(String location) {
    return this.getIndexHtml(this.resourceLoader.getResource(location));
}

private Resource getIndexHtml(Resource location) {
          try {
              Resource resource = location.createRelative("index.html");
              if (resource.exists() && resource.getURL() != null) {
                  return resource;
              }
          } catch (Exception var3) {
          }

          return null;
      }

遍历静态资源路径,符合index.html命名的进行读取到前端

十. Thymeleaf模版引擎

Spring Boot官方推荐的模版引擎,Thymeleaf是一款渲染XML/HTML/HTM5内容,模版引擎,本身就是HTML文件,可以单独运行(做到跟前端开发人员不冲突)。

(1)提高开发效率:安装Thymeleaf插件

在这里插入图片描述

(2)添加依赖

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

或者在spring官网找thymeleaf配置:

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

(3) Thymeleaf源码

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";
}

(4)Thymeleaf模版设置

# 是否启用模版缓存,开发期间不推荐使用
spring.thymeleaf.cache=false
# 模版模式:支持HTML(4/5) ,如果设置为HTML5就只能支持HTML5
spring.thymeleaf.mode=HTML5
#以下都是默认配置
#检查模版是否存在
spring.thymeleaf.check-template=true
#是否启用模版
spring.thymeleaf.enabled=true
#模版编码
spring.thymeleaf.encoding=UTF-8
# spring.thymeleaf.suffix=.html
# spring.thymeleaf.prefix=classpath:/templates/
# 应该从解析中排除属于列表的名称,可以使用逗号分隔
# spring.thymeleaf.excluded-view-names=

(5)关键:HTML中需要由提示设置

官方文档

<html lang="en" xmlns:th="http://www.thymeleaf.org">引入命名空间,才会有th:*提示

10.1 基本语法使用

测试使用的前端页面:

 <ul>
            <!--转义-->
            <li th:text="${bookName}">恶魔</li>
            <!--解析-->
            <li th:utext="${bookName}">克苏鲁</li>
            <!-- 破坏前端数据:转义 -->
            <li> [[${bookName}]]</li>
        </ul>

(1)${}变量表达式,最常用

@Controller
@RequestMapping("/doom")
public class DataController {
    @GetMapping("test")
    public String m1(Model model){
        model.addAttribute("bookName","<b>夜雨</b>");
        return "demo01";
    }
}

 <!--假设前端页面如下-->
      <!-- 应该尽量不破坏前端的数据,修改元素内容 -->
        <ul>
            <!--转义-->
            <li th:text="${bookName}">恶魔</li>
            <!--解析-->
            <li th:utext="${bookName}">克苏鲁</li>
            <!-- 破坏前端数据:转义 -->
            <li> [[${bookName}]]</li>

在这里插入图片描述

10.2 设置属性值

th:text或者th:utext替换的元素内容,标签中还会涉及很多的属性,关于属性的设置Thymeleaf提供基本上所有的th:HTML属性的形式

控制器:

 @GetMapping("/attr")
    public String m2(Model model) {
        model.addAttribute("bookName", "月色");
        model.addAttribute("author", "夜雨");
        model.addAttribute("price", 666);
        model.addAttribute("css", "color:deeppink");
        model.addAttribute("cssClass", "abc");
        model.addAttribute("title", "提示");
        model.addAttribute("tip", "请输入内容");
        return "demo02";
    }

简单测试:

<h3 th:text="${bookName}"></h3>
<input th:value="${author}" th:placeholder="${tip}" th:style="${css}"><br/>
<p th:text="${price}" th:class="${cssClass}" th:title="${title}"></p>
<p th:text="${price}" th:attr="class=${cssClass},style=${css}"></p><!--等价上一行-->

在这里插入图片描述
针对行内样式测试:

 <h3 >针对样式操作</h3>
        <p class="mydiv" th:text="${bookName}" th:class="${cssClass}"></p><!--覆盖替换-->
        <p class="mydiv" th:text="${bookName}" th:attrappend="class=${' '+cssClass}"></p><!--往后追加-->
        <p class="mydiv" th:text="${bookName}" th:attrprepend="class=${cssClass+' '}"></p><!--往前追加-->

        <!--等价写法-->
        <p class="mydiv" th:text="${bookName}" th:classappend="${cssClass}"></p>
        <p style="font-weight: bold;" th:text="${bookName}" th:styleappend="${css}"></p>

在这里插入图片描述

10.3 简单的运算符

(1)字符串拼接
 <h3>字符串拼接</h3>
   <!--这个不算,但是起到的效果相同-->
   <h3>书名:[[${bookName}]]</h3>
   <!--三种方式-->
   <h3 th:text="'书名:'+${bookName}">书名:小楼一夜</h3>
   <h3 th:text="|书名:${bookName}|">书名:小楼一夜</h3>
   <!-- Thymeleaf内置工具对象 -->
   <h3 th:text="${#strings.concat('书名:',bookName,'!!')}">书名:小楼一夜</h3>

在这里插入图片描述

(2)算术运算符、比较运算符、逻辑运算符、条件运算符

<h3>运算符</h3>
<p th:text="10*20"></p>
<p th:text="${price}"></p>
<p th:text="${price}/2"></p>
<p th:text="${price}>20"></p>
<p th:text="${price}<=20"></p>
<p th:text="${abcdef}">====</p><!-- 数据中没有值得时候为空 在前端页面不显示 -->
<p th:text="${abcdef}==null">====</p><!-- 显示为true -->
<hr/>
<h4>字符串比较</h4>
<p th:text="${#strings.equals('月色',bookName)}">====</p>
<p th:text="${bookName}=='月色'">====</p>
<hr/>
<p th:text="${price}%2==0"></p>
<p th:text="${price}%2 eq 0"></p><!-- 相等 -->
<p th:text="${price}%2 ne 0"></p><!-- 不等 -->
<hr/>
<h4>逻辑运算符</h4>
<p th:text="${price}>10 and ${price}<20"></p>
<hr/>
<h4>条件运算符</h4>
<p th:text="${price}%2==0?'真的结果':'假的结果'"></p>
<p th:text="${price}%2==0?'真的结果'"></p><!--可以少后半部分 如果条件判定假  不显示 为空-->

在这里插入图片描述

10.4 URL:传递参数

解决方式一:<base>标签
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <base th:href="|${#request.getContextPath()}/|">
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <a th:href="|book/add?id=${id}&bookName=${bookName}|">自己拼接,传递参数</a><br/>
        <a th:href="|book/add/${id}/${bookName}|">占位符传递数据</a><br/>
    </body>
</html>
解决方式二:@{}(推荐)
<a th:href="@{/book/add(userId=${uid})}">传递数据一个数据</a><br/>
<a th:href="@{/book/add(userId=${uid},id=${id},name='tomcat',bookName=${bookName})}">传递数据多个数据</a><br/>
<a th:href="@{/book/add?id={uuid}&userName={uName}(uuid=${uid},uName='jackson')}">传递数据多个数据</a><br/>

<a th:href="@{/book/add/{uuid}/{uName}(uuid=${uid},uName=${bookName})}">占位符传递数据</a><br/>

10.5 显示对象数据

@GetMapping("/test04")
public String m5(Model model){
    model.addAttribute(new Book("小楼一夜","夜雨",new Random().nextInt(66)));
    return "demo04";
}
<!-- 第一种写法 -->
<form>
    书名:<input th:value="${book.bookName}"/><br/>
    作者:<input th:value="${book.author}"/><br/>
    价格:<input th:value="${book.price}"/><br/>
</form>
<hr/>
<!-- 第二种写法 -->
<form th:object="${book}">
    书名:<input th:value="*{bookName}"/><br/>
    作者:<input th:value="*{author}"/><br/>
    价格:<input th:value="${book.price}"/><br/>
</form>

10.6 语句控制

Thymeleaf语法中认为是true的情况如下:
  • 值是非空
  • 值是character类型,但不是0
  • 值是非0的数字
  • 值是字符串,但是字符串不能是false/off/no
  • 值不是boolean值
(1)IF和SWITCH语句
@GetMapping("/test06")
public String m6(Model model){
    model.addAttribute("price",new Random().nextInt(30));
    model.addAttribute("num",new Random().nextInt(10));
    return "demo06";
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <p th:if="${price}<15">
            小于15的数据:
            <strong th:text="${price}"></strong>
        </p>
        <p th:unless="${price}<15"><!-- >=15 -->
            大于15的数据:
            <strong th:text="${price}"></strong>
        </p>
        <hr/>
        <p th:switch="${num}">
            <strong th:case="1">夜雨:[[${num}]]</strong>
            <strong th:case="2">月色:[[${num}]]</strong>
            <strong th:case="3">小楼:[[${num}]]</strong>
            <strong th:case="4">听风雨:[[${num}]]</strong>
            <strong th:case="*">毕业:[[${num}]]</strong>
        </p>
    </body>
</html>

(2)循环

@GetMapping("/test07")
public String m7(Model model){
    List<Book> bookList = new ArrayList<>();
    bookList.add(new Book("月色","01",new Random().nextInt(66)));
    bookList.add(new Book("夜雨","02",new Random().nextInt(66)));
    bookList.add(new Book("小楼一夜","03",new Random().nextInt(66)));
    bookList.add(new Book("毕业","04",new Random().nextInt(66)));
    bookList.add(new Book("长亭外","古道边",new Random().nextInt(66)));
    model.addAttribute("bookList",bookList);
    return "demo07";
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <table border="1" style="border-collapse: collapse;width: 500px">
            <tbody>
                <tr th:each="book,vs:${bookList}" th:style="|background:${vs.even?'yellow':'#ccc'}|">
                    <td th:text="${vs.count}"></td>
                    <td th:text="${book.bookName}"></td>
                    <td th:text="${book.price}"></td>
                    <td th:text="${book.author}"></td>
                </tr>
            </tbody>
        </table>
    </body>
</html>

10.7 包含和替换(简述)

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
       <p th:include="commons/header"></p>
       <p th:replace="commons/footer"></p>
    </body>
</html>

包含只是加载,不会让原来的标签(也就是p标签消失)
替换会直接让原来标签消失

10.8 经典回显数据

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <base th:href="|${#request.getContextPath()}/|">
        <meta charset="UTF-8">
        <title>模版引入</title>
    </head>
    <body>
        <h2>下拉框选中[[${num1}]]</h2>
        <select>
            <option value="">请选择爱好</option>
            <option th:each="hobby:${hobbyList}" th:text="${hobby['name']}" th:value="${hobby['id']}"
            th:selected="${hobby['id'] eq num1}"
            ></option>
        </select>
        <h2>下拉框选中[[${num1}]]</h2>
        <select id="hobby">
            <option value="">请选择爱好</option>
            <option th:each="hobby:${hobbyList}" th:text="${hobby['name']}" th:value="${hobby['id']}"></option>
        </select>
        <script>
            var hobbyId = '[[${num1}]]';
            document.getElementById("hobby").value=hobbyId;
        </script>
        <h2>单选框[[${num1}]]</h2>
        <input type="radio" name="hobbyRadio" th:each="hobby:${hobbyList}" th:text="${hobby['name']}" th:value="${hobby['id']}" th:checked="${hobby['id'] eq num1}">
        <h2>多选框[[${num1}]]</h2>
        <input type="checkbox" name="hobbyCheckBox" th:each="hobby:${hobbyList}" th:text="${hobby['name']}" th:value="${hobby['id']}" th:checked="${#arrays.contains(num2,hobby['id'])}">
    </body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月色夜雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值