Spring Boot学习笔记

一、Spring Boot入门

1.Spring Boot介绍

Spring Boot 是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。

Spring Boot特性

1.1特性介绍

  • 创建独立的Spring应用程序
  • 嵌入的Tomcat,无需部署WAR文件
  • 简化Maven配置
  • 自动配置Spring
  • 提供生产就绪功能,如指标,健康检查和外部配置
  • 开箱即用,没有代码生成,也无需XML配置。

1.2 特性理解

  • 为基于Spring的开发提供更快的入门体验
  • 开箱即用,没有代码生成,也无需XML配置,同时也可以修改默认值来满足特定的需求。
  • 提供了一些大型项目中常见的非功能特性,如嵌入式服务器、安全、指标、健康检测、外部配置等。
  • Spring Boot并不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式。

2.微服务

  • 微服务是一种架构风格
  • 提倡在开发应用时,一个应用应该是一组小型服务;可以通过HTTP的方式进行互通

2.1单体应用

  • All In One ,
  • 是传统的架构,
  • 优点:开发、部署、运维要简单,
  • 缺点:牵一发动全身,不适合大型应用
  • 在多个服务器上复制这个单体进行扩展

2.2 微服务

  • 一个微服务架构把每个功能元素放进一个独立的服务中
  • 通过跨域服务器分发这些服务进行扩展,只在需要时进行扩展
  • 每一个功能元素都是一个可以替换和独立升级的软件单元

3.环境准备

  • Spring Boot推荐使用jdk的版本:1.7及以上
  • maven:3.3及以上版本
  • intellij idea
  • Spring Boot

Maven设置:

给maven的settings.xml配置文件的profiles标签添加

表明使用jdk1.8进行开发

 1 <profile>
 2     <id>jdk-1.8</id>
 3     <activation>
 4     <activeByDefault>true/ activeByDefault>
 5     <jdk>1.8</jdk>
 6 </activation>
 7     <properties>
 8         <maven. compiler .source>1。8</maven.compiler.source>
 9         <maven. compi ler. target>1.8</maven.compller.target>
10         <maven. compiler. compilerverslon>1.8</maven.compiler.compllerversion>
11     </propert1es>
12 </profile>

 

Idea设置

进入设置页面 Ctrl+Alt+S

Build,Execution,Deployment–>Build Tools–>Maven

设置maven为本地的maven, 库也为本地maven库

4.Spring Boot HelloWorld

一个功能:

浏览器发送hello请求,服务器接受请求并处理,响应Hello World字符串;

 4.1、创建一个maven工程;(jar)

4.2、导入spring boot相关的依赖

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

4.3、编写一个主程序;启动Spring Boot应用

/**
 *  @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
 */
@SpringBootApplication
public class HelloWorldMainApplication {
​
    public static void main(String[] args) {
​
        // Spring应用启动起来
        SpringApplication.run(HelloWorldMainApplication.class,args);
    }
}

4.4、编写相关的Controller、Service

@Controller
public class HelloController {
​
    @ResponseBody
    @RequestMapping("/hello")
    public String hello(){
        return "Hello World!";
    }
}
​

4.5、运行主程序测试

4.6、简化部署

<!-- 这个插件,可以将应用打包成一个可执行的jar包;-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

将这个应用打成jar包,直接使用java -jar的命令进行执行;

5.Hello World 的探究

1)pom文件

a.父项目

1 <parent>
2         <groupId>org.springframework.boot</groupId>
3         <artifactId>spring-boot-starter-parent</artifactId>
4         <version>2.2.0.RELEASE</version>
5         <relativePath/> <!-- lookup parent from repository -->
6     </parent>

其中有各种依赖的版本,Spring Boot 通过此父项目真正管理Spring Boot里面的所有依赖版本(Spring Boot的依赖仲裁中心)

以后导入依赖不需要版本,(没有depenencies中依赖管理的需要自己声明版本号)

b.导入的依赖

1 <dependency>
2             <groupId>org.springframework.boot</groupId>
3             <artifactId>spring-boot-starter-web</artifactId>
4         </dependency>

spring-boot-stater-web

spring-boot-stater:Spring Boot 场景启动器:帮我们导入了web模块正常运行的组件

Spring Boot将所有的功能都抽取出来,做成一个个的staters(启动器),只需要在项目中引入这些启动器,相关的依赖就能自动导入

2)主程序类,主入口类

1 @SpringBootApplication
2 public class CaitApplication {
3 
4     public static void main(String[] args) {
5         SpringApplication.run(CaitApplication.class, args);
6     }
7 
8 }

@SpringBootApplication 核心注解,标注在某个类上说明这个类是Spring Boot的主配置类,Spring Boot 一个运行这个类的main方法来启动应用:

 

 1 @Target({ElementType.TYPE})
 2 @Retention(RetentionPolicy.RUNTIME)
 3 @Documented
 4 @Inherited
 5 @SpringBootConfiguration
 6 @EnableAutoConfiguration
 7 @ComponentScan(
 8     excludeFilters = {@Filter(
 9     type = FilterType.CUSTOM,
10     classes = {TypeExcludeFilter.class}
11 ), @Filter(
12     type = FilterType.CUSTOM,
13     classes = {AutoConfigurationExcludeFilter.class}
14 )}
15 )
16 @ConfigurationPropertiesScan
17 public @interface SpringBootApplication {
  • @SpringBootConfiguration Spring Boot 的配置类;

    • 标注在某个类上,表示这是一个Spring Boot 的配置类
    • @Configuration 配置类上来标注这个注解;(Spring4.X)
      • 配置类————配置文件;
  • @EnableAutoConfiguration 开启自动配置功能;

    • 以前我们需要配置的东西,Spring Boot 帮我们自动配置;

    • @EnableAutoConfiguration告诉SpringBoot开启自动配置功能;这样自动配置才能生效

      • @AutoConfigurationPackage : 自动配置包
      • @**Import({AutoConfigurationImportSelector.class})**Spring的底层注解,给容器中导入一个组件;导入的组件有AutoConfigurationImportSelector.class
1 @Target({ElementType.TYPE})
2 @Retention(RetentionPolicy.RUNTIME)
3 @Documented
4 @Inherited
5 @AutoConfigurationPackage
6 @Import({AutoConfigurationImportSelector.class})
7 public @interface EnableAutoConfiguration {

6.使用Spring Initializer快速创建Spring Boot 项目

SpringBoot学习第一步:搭建基础

IDEA对SpringBoot的项目支持可以说是点击就能完成基础的搭建,

流程如下

1.左上角File选项,New project,选择Spring Initializr

2.设置项目信息,Group 会自动创建Group文件夹,包含项目的代码;Artifact 的名字必须使用小写与下划线构成!!

3.选择web项目,右上角可以选择SpringBoot 的版本,一定要使用relese版本(正式版),不要使用SNAPSHOT版本

4.确定project的名字与位置,名字就是项目文件夹的名字

点击finish就好啦,一个SpringBoot+Maven项目就搞定了,最后创建三个基础包!

默认生成的Spring Boot 项目:

  • 主程序已经生成,我们只需要我们自己的逻辑
  • resouces文件夹中目录结构
    • static:保存所有的静态资源:js,css,images;
    • templates:保存所有的模板页面:(Spring Boot 默认jar包嵌入式的Tomcat,默认不支持Jsp页面);可以使用模板引擎(freemarker、thymeleaf);
    • application.properties:Spring Boot 应用默认配置文件

 

二、Spring Boot 配置

1. 配置文件

Spring Boot 默认使用两种配置文件

  • application.properties
  • application.yml
配置文件的作用:修改Spring Boot自动配置的默认值;Spring Boot在底层自动配置好

YAML(YAML Ain’t Markup Language )语言的文本,

  • YAML A Markup Language :是一个标记语言
  • YAML isn’t Markup Language : 不是一个标记语言(XML类型标记文件)

标记语言:

  • 以前的标记语言大多数使用的是 XXXX.xml
  • YAML :以数据为中心,比json、xml等更适合做配置文件

2. YAML语法

1)基本语法

K:(空格)Value 表示一对键值对(空格必备)

以**空格**的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的

server:
    port: 8081
    path: /hello

属性与值也是大小写敏感的

2)值的写法

字面量:普通的值(数字,字符串,布尔)

key: value (中间有空格)字面直接来写;

  • 字符串默认不用加上单引号和双引号

    • “”:双引号不会转义字符串里面的特殊字符;特殊字符会作为本身想表达的意思

      • example: “zhangsan \n list”:输出:zhangshan (换行) list
    • ‘’:单引号 会转义特殊字符,特殊字符最终只是一个普通的字符串数据

      • example: “zhangsan \n list”:输出:zhangshan \n list

对象、Map(属性和值)(键值对)

key: value

​对象还是key: value的方式

example: create a object with propertities : lastName age

friends:
    lastName: zhangshan
    age: 22

行内写法:用一行表示

friends: {lastName: zhangshan , age: 18}

数组(List、Set):

用-值表示数组中的一个元素

pets:
    -cat
    -dog
    -pig

行内写法:

pets: [cat,dog,pig]

附:Spring Boot单元测试

可以在测试期间很方便的类似编码一样进行自动注入容器的功能

package com.cait.cait;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class CaitApplicationTests {

    @Autowired
    要进行测试的类
    @Test
    void contextLoads() {
        进行操作
    }

}

3. 通过配置文件注入

1) 数据绑定到基础数据类型

@Value

String LastName;

是Spring 底层的一个注解,

对应的xml

<bean class="person">
    <property name="LastName" value="字面量/${key}/#{SpEL}"></property>
</bean>

2) 将数据绑定到类中 含配置文件与类绑定的方法

注: prefix必须全部为小写,配置的类名不能使用大写!!!!!,如 subMit是错误的!!

首先类与配置文件要对应,在类前注释 @ConfigurationProperties(prefix=“pets”)

  • @ConfigurationProperties 告诉SpringBoot将本类中的所有属性和配置文件中相关属性进行绑定;

  • perfix=“pets”:配置文件中,该前缀下面的所有属性,进行一一映射

  • 若报错,点击提示,官方说明应该添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>   
    <artifactId>spring-boot-configuration-processor</artifactId> 
    <optional>true</optional>
</dependency>
  • 只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能

  • 添加@Component注解加入容器组件

总结:导入配置文件处理器,以后进行配置文件操作就有提示,类中属性的名要对应,类名可以不同,加入注解@ConfigurationProperties(prefix = “属性的前缀”)

<dependency>
    <groupId>org.springframework.boot</groupId>   
    <artifactId>spring-boot-configuration-processor</artifactId> 
    <optional>true</optional>
</dependency>

配置文件少用中文!!!

若输出为乱码,原因是idea使用的是utf8

打开Setting,搜索file encoding(文件编码),选择UTF8,同时选择需要在运行时转译为ascii

  •  Transparent native to ascii conversion

3) @Value 获取值和 @ConfigurationProperties获取值的比较

类型@ConfigurationProperties@Value
功能 批量注入配置文件中的属性 一个个指定
松散绑定(松散语法) supported unsupported,要严格对应名
SpEL unsupported supported
JSR303 supported unsupported
复杂类型封装 supported unsupported, only simple type is permitted

配置文件yml于properties他们都能获取到值

  • 如果说,我们只是在某个业务逻辑中需要获取一下文件中的某项值,使用@Value
  • 如果单独写了一个JavaBean来匹配配置文件中的值,使用@ConfigurationProperties

4) 配置文件注入值数据校验

5) @PropertySource & @ImportResource

  • @PropertySource:加载指定的配置文件(非默认的application.yml)

  • 参数Value指文件,encoding指编码,也很重要!!!

注:@PropertySource默认只能支持properties文件!!!!,

解决方案:SpringBoot配置文件@PropertySource 同时支持properties文件与yaml(yml)

6)Spring配置文件注入

a. @ImportResource: 导入Spring配置文件,让配置文件里面的内容生效;

想让Spring的配置文件生效,加载进来;将@ImportResouce标注在一个类上

@ImportResource(locations= {"classpath:bean.xml"})

导入Spring配置文件:beans.xml并使其生效

b. Spring Boot 推荐给容器添加组件的方式

  • 配置类=======Spring 配置文件

  • 使用@Bean添加

 1 package com.jirath.springboot_learn.config;
 2 
 3 import com.jirath.springboot_learn.service.HelloService;
 4 import org.springframework.context.annotation.Bean;
 5 import org.springframework.context.annotation.Configuration;
 6 
 7 /**
 8  * '@Configuratoin' point out that current object is a Configuration Class,which used to replace the Spring Configuration file before.
 9  */
10 @Configuration
11 public class MyConfig {
12     /**
13      * add current function's returned value to the ContextContainer,
14      * the id of the module in this ContextContainer is the name of function;
15      * @return the object which used to build a Bean
16      */
17     @Bean
18     public HelloService helloService(){
19         return new HelloService();
20     }
21 }

4.配置文件占位符

RandomValuePropertySource: 配置文件中可以使用随机数

random.value 、{random.value}、random.value、{random.int}、random .long 、{random.long}、random.long、{random.int(10)}、random .in  [ 1024 , 65536 ] 、{random.int[1024,65536]}、random.int[1024,65536]、{random.uuid}

属性配置占位符

app.name=MyApp app.description=${app.name} is a Spring Boot application

  • 可以在配置文件中引用前面配置过的属性(优先级前面配置过的这里都能用)

  • ${app.name:defultValue}来指定找不到属性时的默认值

  • 若引用的值不存在,SpringBoot会默认将{}中间的值作为value

用${person.name:(defult)}可以设置默认为defult

5.Profile

在开发过程中会遇到开发和实际生产时项目的配置是不同的情况,应对这种情况,Spring设置了Profile,

Profile是Spring对不同环境提供不同配置功能的支持,可以通过激活、指定参数等方式快速切换环境

1)多Profile文件

我们在主配置文件编写的时候,文件名可以是 application-(profile).properties/yml

!!!注意,文件的profile必须在三个字符以内,否自无法作为配置文件!!

默认使用application.properties的配置:

2)yml支持多文档块方式

spring:
    profiles:
        active: dev
---
server:
    port: 8081
spring:
    profiles: dev
    
---
server:
    port: 8081
spring:
    profiles: prod

3)激活指定Profile

 spring.profiles.active=dev

 

    • 命令行:

    • –spring.profile.active=dev

    • idea测试方法

    • 打包:

      • 打开maven选项,Lifecycle->package
  •      虚拟机方法

    -Dspring-profiles.active=dev

 

6.配置文件的加载位置

spring boot 启动会扫描以下位置的application.properties / yml 文件作为Spring Boot的默认配置文件

  • file:./config
  • file:./
    • 以上两种是在当前项目路径下,即与src同级

    • classpath:/config/

    • classpath:/

    • 以上是按照优先级从高到低的顺序,所有位置的文件都会被加载

    • 高级优先配置内容会覆盖低级优先配置相同的内容,同时满足配置互补

    • 我们也可以通过配置spring.config.location来改变默认配置

 

  • 项目打包好了以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的位置;指定配置文件和默认加载的这些配置文件共同起作用,形成互补配

 

7.Spring Boot 外部配置加载顺序

Spring Boot也可以从以下位置加载配置;优先级从高到低

优先加载带Profile,jar包外部的

  1. 命令行参数

  2. 来自java:comp/env的NDI属性

  3. Java系统属性(System.getProperties())

  4. 操作系统环境变量

  5. RandomValuePropertySource配置的random.*属性值

  6. jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件

  7. jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件

  8. jar包外部的application.properties或application.yml(不带spring.profile)配置文件

  9. jar包内部的application.properties或application.yml(不带spring.profile)配置文件

  10. @Configuration注解类上的@PropertySource

  11. 通过SpringApplication.setDefaultProperties指定的默认属性

8.Spring Boot 自动配置原理

8.1自动配置原理:

  1. Spring Boot启动的时候,加载主配置类,开启了自动配置功能@EnableAutoConfiguration,

  2. @EnableAutoConfiguration的作用:

  • 利用EnableAutoConfigurationImportSelector给容器中导入一些组件

  • 可以查询selectImports()方法的内容;

  • Listconfigurations=getCandidateConfigurations(annotation Metadata,attributes);获取候选的配置

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct."); return configurations; }

public final class SpringFactoriesLoader {
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
    private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap();

    private SpringFactoriesLoader() {
    }

    3.扫描所有jar包类路径下 META-INF/spring.factories

    4.把扫描到的这些文件的内容包装成properties对象

    5.从properties中获取到EnableAutoCongratulation.class类(类名)对应的值,然后把他们添加在容器中

8.2.自动配置原理(细节)

1)@Conditional派生注解(Spring注解版原生的@Conditional作用)

作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的内容才生效

@Conitional扩展注解作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的Java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean
@ConditionalOnMissingBean 容器中不存在指定Bean
@ConditionalOnExpression 满足SpEl表达式指定
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项

自动配置类必须在一定条件下生效

在配置文件中编写

#开启SpringBoot的debug
debug=true

我们可以通过启用debug=true属性;来让控制台打印自动生成报告,这样我们就可以很方便的知道哪些自动配置类生效

Positive matches: 自动配置类启用的

Negative matches: 未匹配到

三、Spring Boot 与日志

1、日志框架

市面上的日志框架

JUL , JCL , Jboss-logging , logback , log4j , log4j2 , slf4j

日志门面(日志抽象层)日志实现
JCL(Jakarta Commons Logging)、SLF4j(Simple Logging Facae For Java)、Jboss-logging log4j、JUL(java.util.logging)、log4j2、logback

左边选一个门面(抽象层)、右边来选一个实现

  • Jboss 太复杂 JCL 最后一次更新在2014年
  • SLF4j log4j logback出自同一人
  • Log4j2 Apache公司的全新日志框架

日志门面:SLF4J;

日志实现:Logback > log4j

SpringBoot :底层是Spring框架,Spring框架默认使用是JCL

SpringBoot 选用SLF4j和logback

2、SLF4j使用

1)如何在系统中使用SLF4j

以后在开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,二傻调用日志抽象层里面的方法;

给系统里面导入slf4j的jar和logback的实现jar

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

slf4j使用的情况

SELF4j关联了logback日志框架后的正确使用情况

调用SELF4j的接口,SELF4j调用底层日志的jar包

通过适配层将两者关联

2)遗留问题

for example:a情况(slf4j+logback):Spring (commons-logging)、Hibernate( jBOSS-logging)、Mybatis…

统一日志记录,即使 是别的框架,和我一起统一使用slf4j进行输出

  1. 将系统中其他日志框架先排出去

  2. 用中间包替换所有的日志框架

  3. 导入slf4j其他的实现

​ ----------------------SpringBoot就是这么实现的

3)SpringBoot日志关系

  1. 使用logback记录日志

  2. 把其他日志转为slf4j

  3. 导入抽象层

  4. 中间替换包(偷梁换柱)

  5. 如果我们要引入其他框架,一定要把这个框架的默认日志依赖移除

3.日志使用

1)默认配置

SpringBoot 默认帮我们配置好了日志;

 1  //记录器
 2     org.slf4j.Logger logger= org.slf4j.LoggerFactory.getLogger(getClass());
 3 
 4     @Test
 5     void contextLoads() {
 6         //日志的级别
 7         //由低到高 trace debug info warn error
 8         //可以调整需要输出的日志级别,日志就只会在这个级别的更高级别生效
 9         logger.trace("这是trance日志");
10         logger.debug("这是debug日志");
11         //SpringBoot 默认使用的是info级别,没有指定级别的就用SpringBoot默认规定的级别:root级别(info)
12         logger.info("这是info日志");
13         logger.warn("这是warn日志");
14         logger.error("这是error日志");
15     }

SpringBoot修改日志默认配置

path和file都存在,file为主

 1 logging.level.com.jirath=trace
 2 #在当前磁盘下新建Spring和log文件夹:使用spring.log作为默认文件
 3 logging.file.path=/spring/log
 4 #不指定路径就在当前项目下生成日志
 5 #logging.file.name=springboot.log
 6 #可以指定完整路径
 7 logging.file.name=E:/springboot.log
 8 #在控制台输出的日志格式
 9 logging.pattern.console================%n%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
10 #指定文件中日志输出格式
11 logging.pattern.file=

SpringBoot 关于日志的其他默认设置:

位于spring-boot-2.2.0.RELEASE.jar!/org/springframework/boot/logging/logback/中,打开即为SpringBoot针对LogBack的配置封装。

其中,SpringBoot将默认级别(root)设置为了info

在配置文件中配置的属性会被一个名为LoggingApplicationListener(单击配置文件配置项即可查看)相似的类接收

LoggingApplicationListener同时与一个LoggingSystemProperties(在logback桶目录下)的类对应在这里获取输入的值,进行解析

在base.xml中SpringBoot针对控制台与文件输出有分别的定义,如图

在文件默认配置中,SpringBoot同时设置了文件在最大数值,当超出数值,日志就会自动分文件记录,如:log1,log2

2)指定配置

在实际使用时,同时会遇到其他功能的需求,自动归档等等等等,

要想使用自己的配置文件,Spring.io中在特性下有一章节专门讲述了SpringBoot配置默认日志的方法:在Spring目录中放logback.xml即可

给类路径下放上每个框架自己的配置文件即可:SpringBoot就不再使用默认配置

Spring Boot includes a number of extensions to Logback that can help with advanced configuration. You can use these extensions in your logback-spring.xml configuration file.

logback.xml:直接被日志框架识别

logback-spring.xml:日志就不直接加载日志配置项,由SpringBoot解析日志配置,就可以使用SpringBoot的高级Profile功能

<springProfile name="dev">
    <!--可以指定某段配置只在某个环境下生效-->
</springProfile>

 

四、SpringBoot与Web开发

1、使用SpringBoot

  1. 创建SpringBoot应用,选中我们需要的模块;

  2. SpringBoot已经默认将这些场景布置好,只需要在配置文件中指定少量配置就可以运行起来;

  3. 自己编写业务代码;

    在这个场景中,SpringBoot帮我们配置

  1. XXXXAutoConfiguration:帮我们给容器中自动配置组件
  2. 在Spring-boot-autoconfigure中找到web模块
  3. 自动配置类在其中
  4. XXXProperties:配置类来封装配置文件的内容

2、SpringBoot对静态页面的映射规则

在WebMvcAutoConfiguration中

2.1 访问静态资源

第一种 导入的webjars

 1 public void addResourceHandlers(ResourceHandlerRegistry registry) {
 2             if (!this.resourceProperties.isAddMappings()) {
 3                 logger.debug("Default resource handling disabled");
 4             } else {
 5                 Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
 6                 CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
 7                 if (!registry.hasMappingForPattern("/webjars/**")) {
 8                     this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
 9                 }
10 
11                 String staticPathPattern = this.mvcProperties.getStaticPathPattern();
12                 if (!registry.hasMappingForPattern(staticPathPattern)) {
13                     this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
14                 }
15 
16             }
17         }
  1. 由上方代码,所有/webjars/**,下的请求都会去classpath:/META-INF/resources/webjars/中寻找资源

    • webjars:以jar包的方式引入静态资源;
    • webJars
    • 将常用的前端框架给了一个Maven依赖的方式
    • 选好要使用的版本,在pom文件中引入即可
    • 引入后在jar包中,设置中显示隐藏文件夹即可打开,符合映射规则
  2. 代码中同时设置了缓存时间,缓存时间可以在resourceProperties中设置

Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
@ConfigurationProperties(
    prefix = "spring.resources",
    ignoreUnknownFields = false
)
public class ResourceProperties {
//可以设置与静态资源有关的参数,缓存时间

第二种"/**"访问当前项目的任何资源

 String staticPathPattern = this.mvcProperties.getStaticPathPattern();
                if (!registry.hasMappingForPattern(staticPathPattern)) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

进入getResoutceLocations

static String[] getResourceLocations(String[] staticLocations) {
        String[] locations = new String[staticLocations.length + SERVLET_LOCATIONS.length];
        System.arraycopy(staticLocations, 0, locations, 0, staticLocations.length);
        System.arraycopy(SERVLET_LOCATIONS, 0, locations, staticLocations.length, SERVLET_LOCATIONS.length);
        return locations;
    }

查看代码是从其他方法中引入了参数(与1版本不同)

返回查看参数的来源

getStaticLocations
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};

总结

"/**"访问当前项目的任何资源(静态资源文件夹)都会在下方的文件夹中找内容

  • “classpath:/META-INF/resources/”,
  • “classpath:/resources/”,非默认的resources,而是新建的resources文件夹
  • “classpath:/static/”
  • “classpath:/public/”,(默认无,需要新建)
  • “/”:当前项目的路径

2.2 欢迎页配置

1 @Bean
2         public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
3             WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
4             welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
5             return welcomePageHandlerMapping;
6         }
1 private Optional<Resource> getWelcomePage() {
2             String[] locations = WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations());
3             return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();
4         }
5 private Resource getIndexHtml(String location) {
6             return this.resourceLoader.getResource(location + "index.html");
7         }

静态资源文件夹下所有index.html页面:被"/**"映射

2.3 图标

所有的**/favicon.ico都是在静态资源环境下找;

同时静态资源的位置是可以改变的

spring.resources.static-location=位置

3、模板引擎

之前多使用jsp页面,可以很方便的嵌入数据等,但SpringBoot 使用嵌入式的tomcat,不支持jsp页面,只能支持HTML,

JSP、Velocity、Freemarker、Thymeleaf;

模板引擎的作用:在写页面时,将一些数据与渲染数据的模板结合输出,JSP与其他的模板引擎都是这一原理

SpringBoot推荐的Thymeleaf;

语法更简单,功能更强大;

引入thymeleaf

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

-   详情见SpringBoot官网文档

-   布局功能的支持程序 thymeleaf3主程序 layout2以上版本

Thymeleaf使用&语法

 1 -   在AutoConf...中有配置类,打开properties有默认自动配置项
 2 
 3 -   ````java
 4         private static final Charset DEFAULT_ENCODING;
 5         public static final String DEFAULT_PREFIX = "classpath:/templates/";
 6         public static final String DEFAULT_SUFFIX = ".html";
 7         private boolean checkTemplate = true;
 8         private boolean checkTemplateLocation = true;
 9         private String prefix = "classpath:/templates/";
10         private String suffix = ".html";
11         private String mode = "HTML";
12         private Charset encoding;
13         private boolean cache;
14         private Integer templateResolverOrder;
15         private String[] viewNames;
16         private String[] excludedViewNames;
17         private boolean enableSpringElCompiler;
18         private boolean renderHiddenMarkersBeforeCheckboxes;
19         private boolean enabled;
20         private final ThymeleafProperties.Servlet servlet;
21         private final ThymeleafProperties.Reactive reactive;
22     //只要我们把HTML文件放在classpath:/templates/,thymeleaf就能自动渲染
23     //同时可以在配置文件中修改配置
24     ````
25 
26 -   [thymeleaf官网](https://www.thymeleaf.org/)
27 
28 -   ![image-20191122231053533](image-20191122231053533.png)
29 
30 -   现代化java服务端的模板引擎
31 
32 -   ![image-20191122231204398](image-20191122231204398.png)
33 
34 -   使用
35 
36 ````ht
37 导入开启thymeleaf的语法空间,开启语法提示
38 <html lang="en"  xmlns:th="http://www.thymeleaf.org">
39 ````
40 
41 ````java 
42 @RequestMapping("/html")
43     public String testHtml(Map<String,Object> map){
44         map.put("hello", "这是Controller中返回的话");
45         return "testPage";
46     }
47 ````
 1 ````html
 2 <!DOCTYPE html>
 3 <html lang="en"  xmlns:th="http://www.thymeleaf.org">
 4 <head>
 5     <meta charset="UTF-8">
 6     <title>test</title>
 7 </head>
 8 <body>
 9 <h1>这是一个测试文字</h1>
10 <!--将div里面的文本内容设置为,可以替换静态的信息-->
11 <div th:text="${hello}">这是静态的语句</div>
12 </body>
13 </html>
14 ````

语法规则

使用${AttributeName}取值

1)、th:text 改变当前元素里面的内容

th:任意html属性 替换原生属性的值

2)表达式

Variable Expressions: ${…} 获取变量值,OGNL;

获取对象的属性、调用方法

  • 使用内置的基本对象内置的一些工具对象
  1. #ctx : the context object.
  2. #vars: the context variables.
  3. #locale : the context locale.
  4. #request : (only in Web Contexts) the HttpServletRequest object.
  5. #response : (only in Web Contexts) the HttpServletResponse object.
  6. #session : (only in Web Contexts) the HttpSession object.
  7. #servletContext : (only in Web Contexts) the ServletContext object.
  8. Established locale country: <span th:text="${#locale.country}">US</span>.
  • 内置的一些工具对象
  1. #execInfo : information about the template being processed.
  2. #messages : methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{…} syntax.
  3. #uris : methods for escaping parts of URLs/URIs
  4. #conversions : methods for executing the configured conversion service (if any).
  5. #dates : methods for java.util.Date objects: formatting, component extraction, etc.
  6. #calendars : analogous to
  7. #dates , but for java.util.Calendar objects. #numbers : methods for formatting numeric objects.
  8. #strings : methods for String objects: contains, startsWith, prepending/appending, etc.
  9. #objects : methods for objects in general.
  10. #bools : methods for boolean evaluation.
  11. #arrays : methods for arrays.
  12. #lists : methods for lists. #sets : methods for sets. #maps : methods for maps.
  13. #aggregates : methods for creating aggregates on arrays or collections.
  14. #ids : methods for dealing with id attributes that might be repeated (for example, as a result of an iteration).
  15. Selection Variable Expressions: *{…} 变量的选择表达式,与${}在性质上是一样的,补充:配合th:object 使用

Message Expressions: #{…} 获取国际化内容

Link URL Expressions: @{…} 定义URL链接

Fragment Expressions: ~{…} 插入文档

Literals(字面量)

  1. Text literals: ‘one text’ , ‘Another one!’ ,…
  2. Number literals: 0 , 34 , 3.0 , 12.3 ,…
  3. Boolean literals: true , false
  4. Null literal: null
  5. Literal tokens: one , sometext , main ,…

Text operations: (文本操作)

  1. String concatenation: +
  2. Literal substitutions: |The name is ${name}|

Arithmetic operations: (数学运算)

  1. Binary operators: + , - , * , / , %
  2. Minus sign (unary operator):

Boolean operations: (布尔运算)

  1. Binary operators: and , or
  2. Boolean negation (unary operator): ! , not

Comparisons and equality:(比较运算)

  1. Comparators: > , < , >= , <= ( gt , lt , ge , le )
  2. Equality operators: == , != ( eq , ne )

Conditional operators:(条件运算)(三元运算符也支持)

  1. If-then: (if) ? (then)
  2. If-then-else: (if) ? (then) : (else)
  3. Default: (value) ?: (defaultvalue)

Special tokens:(特殊)

  1. No-Operation: _ 不做处理
1 OGNL的例子
2 /* * Access to properties using the point (.). Equivalent to calling property getters. */ 
3 ${person.father.name}
4 /* * Access to properties can also be made by using brackets ([]) and writing  * the name of the property as a variable or between single quotes. */ 
5 ${person['father']['name']}
6 /* * If the object is a map, both dot and bracket syntax will be equivalent to  * executing a call on its get(...) method. */ ${countriesByCode.ES} ${personsByName['Stephen Zucchini'].age}
7 /* * Indexed access to arrays or collections is also performed with brackets,  * writing the index without quotes. */ ${personsArray[0].name}
8 /* * Methods can be called, even with arguments. */ ${person.createCompleteName()} ${person.createCompleteNameWithSeparator('-')}

 转载自:https://blog.csdn.net/weixin_44494373/article/details/104566898

posted @ 2020-10-17 22:32  Mandy_liang  阅读(194)  评论(0)    收藏  举报