• SpringBoot入门及深入


    一:SpringBoot简介

      当前互联网后端开发中,JavaEE占据了主导地位。对JavaEE开发,首选框架是Spring框架。在传统的Spring开发中,需要使用大量的与业务无关的XML配置才能使Spring框架运行起来,这点备受许多开发者诟病。随着Spring4.x发布,Spring已经完全脱离XML,只使用注解就可以运行项目。为了进一步简化Spring应用的开发,SpringBoot诞生了。它是由Pivotal团队提供的全新框架,其设计目的是简化Spring应用的搭建及开发过程,并迎合时下流行的分布式微服务设计思想,越来越多企业在使用SpringBoot

    1:设计初衷

      SpringBoot为我们开发者提供了一种更快速、体验更好的开发方式,我们可以开箱即用,无需像写Spring那样配置各种XML文件,虽然Spring3.0时引入了基于java的配置,但是编写这些配置无疑是在浪费大量时间,其实SpringBoot还内置Tomcat

    2:核心功能

    一:独立的运行Spring
        SpringBoot 可以以jar包形式独立运行,运行一个SpringBoot项目只需要通过java -jar xx.jar来运行
    二:内置Servlet容器
        Spring Boot可以选择内嵌Tomcat、jetty或者Undertow,这样我们无须以war包形式部署项目
    三:简化Maven配置
        SpringBoot提供了一系列的start pom来简化Maven的依赖加载,例如,当你使用了spring-boot-starter-web
    四:自动装配
        SpringBoot会根据在类路径中的jar包,类、为jar包里面的类自动配置Bean,这样会极大地减少我们要使用的配置。
    当然,SpringBoot只考虑大多数的开发场景,并不是所有的场景,若在实际开发中我们需要配置Bean,而SpringBoot
    没有提供支持,则可以自定义自动配置 五:准生产的应用监控 SpringBoot提供基于http ssh telnet对运行时的项目进行监控 六:无代码生产和xml配置 SpringBoot不是借助与代码生成来实现的,而是通过条件注解来实现的,这是Spring4.x提供的新特性

    Spring Boot只是Spring本身的扩展,使开发,测试和部署更加方便

    3:本文开发环境需求

      SpringBoot 2.4.1正式发行版要求Java8并且兼容Java15;对应的Spring版本是5.3.2;而且要求Maven 3.3+ 但是最好使用3.5.4稳定版本,而Servlet容器的版本为Tomcat9.0(Servlet Version 4.0)、Jetty 9.4(Servlet Version 3.1)、Undertow 2.0(Servlet Version 4.0)  

     二:SpringBoot入门搭建

    1:手动搭建案例

      我们以一个简单的SpringBoot案例来突显出Spring的繁琐,我接下来将使用SpringBoot来实现一个简单的带Controller的案例

    第一步:使用IDEA构建一个普通的Maven项目
    第二步:在构建好的maven工程中对pom文件修改
    第三步:编写启动引导类
    第四步:编写Controller
    第五步:访问(默认8080端口) 以本案例http://localhost:8080/index/test
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
             http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <!--
            在编写SpringBoot的项目时我们得继承SpringBoot的父POM文件,
            这一点和我们以前使用Spring导入的坐标不太一样,细心的会查看
            继承的父POM文件后发现SpringBoot为我们提前导入了大量的坐标,
            这就解决了我们平常导入坐标版本冲突问题
        -->
        <parent>
            <artifactId>spring-boot-starter-parent</artifactId>
            <groupId>org.springframework.boot</groupId>
            <version>2.4.1</version>
        </parent>
    
        <groupId>org.example</groupId>
        <artifactId>demo0023</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
            <!--
                要编写SpringMVC相关代码我们还得导入web的starter依赖
                SpringBoot为了我们导入的方便,把一系列的关于SpringMVC的坐标打包结合到了
                这个我下面导入的坐标里面
            -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
        </dependencies>
    </project>
    pom.xml里面添加相应坐标
    package cn.xw;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    /**
     * 启动引导类
     */
    //加上此注解代表当前类就是SpringBoot启动类,否则就是普通类
    @SpringBootApplication
    public class SpringBoot5Application {
        //SpringBoot程序入口
        public static void main(String[] args) {
    
            //main函数里面的args参数是一个String数组,所以在main函数运行的
            //同时可以接收参数,接收过来的参数交给了SpringBoot,用于后期运行配置,后面介绍
            //第一个参数通过反射是告诉SpringBoot哪个是启动引导类
            //还有这个方法有个返回值,返回IOC容器
            SpringApplication.run(SpringBoot5Application.class, args);
        }
        /**
         * 注意:此类只会扫描加载当前包及其子包里面的全部类,然会把它们加载IOC容器中
         */
    }
    启动引导类编写
    package cn.xw.controller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController //结合@ResponseBody 和 @Controller 两注解
    @RequestMapping("/index")
    public class IndexController {
        @RequestMapping("/test")
        public String testMethod() {
            System.out.println("访问到此方法");
            return "Hello !!";
        }
    }
    Controller编写

    2:使用Spring Initializr快速搭建

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <!--SpringBoot父POM坐标-->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.4.1</version>
            <relativePath/>
        </parent>
        <groupId>cn.xw</groupId>
        <artifactId>springboot_test</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>springboot_test</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <!--WEB开发Starter-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--SpringBoot的开发者工具-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <!--SpringBoot测试Starter-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <!--SpringBoot的Maven插件-->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    自动创建的Maven坐标说明

    三:SpringBoot基本分析

    1:坐标中starters分析及依赖管理

      starter是依赖关系的整理和封装。是一套依赖坐标的整合,可以让导入应用开发的依赖坐标更方便。利用依赖传递的特性帮我们把一些列指定功能的坐标打包成了一个starter,我们只需要导入starter即可,无需导入大量坐标;每个Starter包含了当前功能下的许多必备依赖坐标这些依赖坐标是项目开发,上线和运行必须的。同时这些依赖也支持依赖传递。如下Starter:

    <!--导入WEB开发Starter-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    <dependencies>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter</artifactId>
          <version>2.4.1</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-json</artifactId>
          <version>2.4.1</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-tomcat</artifactId>
          <version>2.4.1</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>5.3.2</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>5.3.2</version>
          <scope>compile</scope>
        </dependency>
      </dependencies>
    spring-boot-starter-web内部封装的一些列坐标

    封装成各个Starter的好处就是让我们更加专注于业务开发,无需关心依赖导入,依赖冲突,及依赖的版本

    问:为什么导入的一些Starter不需要写版本呢?

      不指定版本是因为maven有依赖传递的特性,可推测starter在父级定义了并锁定了版本;spring-boot-dependencies.xml 文件可以给大家一个答案;继承关系为 spring-boot-starter-parent.xml ==> spring-boot-dependencies.xml 这里面锁定了我们常用的坐标及Stater

    编写SpringBoot项目继承spring-boot-starter-parent的好处和特点

    ①:默认编译Java 1.8
    ②:默认编码UTF-8
    ③:通过spring-boot-denpendencies的pom管理所有公共Starter依赖的版本
    ④:spring-boot-denpendencies通过Maven的依赖传递和版本锁定特性来实现版本管理
    ⑤:随用随取,不用继承父类所有的starter依赖。

    POM文件中的Maven插件功能

    <build>
      <plugins>
            <!-- 作用:将一个SpringBoot的工程打包成为可执行的jar包 -->
          <plugin>
              <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
      </plugins>
    </build>

    补充:可选择的启动器官网介绍,需要则查询这个手册

     2:自动配置(AutoConfiguration)分析

      所有我们要配置的项目Pivotal团队的开发人员,帮我们写好了,怎么实现的,主要是通过@Configuration实现 SpringBoot采用约定大于配置设计思想,将所有可能遇到的配置信息提前配置好,写在自动配置的jar包中。每个Starter基本都会有对应的自动配置。SpringBoot帮我们将配置信息写好,存放在一个jar包中:spring-boot-autoconfigure-2.4.1.jar;jar包里,存放的都是配置类,让配置类生效的"规则类"

    接下来我来介绍一个我们常见的配置类
    一:找到项目的External Libraries
    二:查找Maven:org.springframework.boot:spring-autoconfigue:2.4.1
    三:内部有个spring-boot-autoconfigue-2.4.1.jar
    四:点击org ==> web ==> servlet ==> ServletWebServerFactoryAutoConfiguration类
    
    @Configuration(proxyBeanMethods = false)  //代表是个配置类 SpringBoot为我们提供的每个配置类都有此注解
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    @ConditionalOnClass(ServletRequest.class)
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @EnableConfigurationProperties(ServerProperties.class)
    @Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
            ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
            ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
            ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
    public class ServletWebServerFactoryAutoConfiguration { ... }
    
    补充:我们回到之前点击META-INF ==> spring.factories 这里面配置的是SpringBoot的全部配置类
    补充:我们回到之前点击META-INF ==> spring-configuration-metadata.json 这里面配置着各种配置类的信息参数

    问:SpringBoot提供这么多配置类,难道是程序运行后就全部导入吗?

      不会全部导入,只会根据当前项目的需求选择性的装配所需的配置类,这也是SpringBoot的自动装配一大特性;我们也可以设想一下,一次性装配全部配置类,那该多慢呀;

    问:SpringBoot怎么知道程序运行后就自动装配呢?

      我们找到SpringBoot入口函数,点开 @SpringBootApplication 注解会发现里面有个 @EnableAutoConfiguration 这个注解就是开启自动配置的

    问:开启自动装配后,它咋知道要加载指定配置呢?那么多配置类呢

      我们继续看上面的 ServletWebServerFactoryAutoConfiguration 配置类

    @Configuration(proxyBeanMethods = false)
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    //配置类能否被自动装配主要看 @ConditionalOnClass注解 
    //此注解是否可以加载到一个叫 ServletRequest.class文件,一旦存在则自动装配
    @ConditionalOnClass(ServletRequest.class)
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @EnableConfigurationProperties(ServerProperties.class)
    @Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
            ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
            ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
            ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
    public class ServletWebServerFactoryAutoConfiguration { ... }

      有了自动配置后,那么基本全部采用默认配置(这也就是为啥说约定大于配置的思想);那么要修改默认配置也是可以的,我们只需在配置文件配置指定的参数即可 官方全部可配置属性  如下常见配置:

    # 端口配置
    server.port=8888
    # 配置context-path项目访问根路径
    server.servlet.context-path=/demo
    # 开启debug模式,详细日志输出,用于开发的一种设置 默认是false
    debug=true
    # 配置日志  logging.level.{指定包下的日志}=debug
    logging.level.cn.xw=debug

     四:SpringBoot的配置文件

      SpringBoot是约定大于配置的,配置都有默认值。如果想修改默认配置,可以使用application.properties或application.yml或application.yaml自定义配置。SpringBoot默认从Resource目录加载自定义配置文件。application.properties是键值对类型;application.yml是SpringBoot中一种新的配置文件方式,在使用自定义配置时名称一定要为application,因为是提前约定好的,而且三个后缀名的文件都写上是有个先后顺序,后面可覆盖前面

    <includes>
         <include>**/application*.yml</include>
         <include>**/application*.yaml</include>
         <include>**/application*.properties</include>
    </includes>
    # properties类型配置文件 application.properties
    server.port=8080
    server.address=127.0.0.1
    
    <!--xml类型配置文件 application.xml-->
    <server>
        <port>8080</port>
        <address>127.0.0.1</address>
    </server>
    
    # yml/yaml类型配置文件 application.yml/ymal
    server: 
        port: 8080
        address: 127.0.0.1
    三种类型文件的配置方式

    1:yml/yaml配置文件语法及使用

       YML文件格式是YAML(YAML Aint Markup Language)编写的文件格式。可以直观被电脑识别的格式。容易阅读,容易与脚本语言交互。可以支持各种编程语言(C/C++、Ruby、Python、Java、Perl、C#、PHP)。以数据为核心,比XML更简洁。扩展名为.yml或.yaml  官方网站  在线properties转yml

    1:大小写敏感
    2:数据值前边必须有空格,作为分隔符
    3:使用缩进表示层级关系
    4:缩进不允许使用tab,只允许空格
    5:缩进的空格数不重要,只要相同层级的元素左对齐即可
    6:"#"表示注释,从这个字符一直到行尾,都会被解析器忽略。
    7:数组和集合使用 "-" 表示数组每个元素
    # 单个值指定
    name: 小周
    # 单引号忽略转义字符
    message1: 'hello 
     world'
    # 双引号识别转义字符 打印时会换行
    message2: "hello 
     world"
    
    # 对象方式指定 普通写法
    student:
      name: 张三
      age: 25
      address: 安徽六安
    # 对象方式指定 行内写法
    teacher: { name: 李老师, age: 50, address: 上海 }
    
    # 数组方式 普通写法
    hobby:
      - baseball
      - basketball
      - volleyball
    # 数组方式 行内写法
    likes: [ baseball, basketball, volleyball ]
    
    # 集合方式 map等格式
    peoples:
      key1: zhangsan
      key2: anhui
      key3: xiezi
    # 集合方式 map等格式 行内写法
    peoples1: { key1 : zhangsan, key2 : anhui , key3 : shanghai}
    # 这上面的key~ 是具体的key名称
    
    ######## 其它方式扩展
    # 配置引用
    bookName: 零基础学Java
    person:
      name: xiaowu
      likeBookName: ${bookName}
    
    # 配置随机数 其中有int 和 long两种根据情况选择
    # 随机字符串
    StringA: ${random.value}
    # 随机数
    numberB: ${random.int}
    # 随机产出小于10的数
    numberC: ${random.int(10)}
    # 随机产出10~100之间的数 大于10小于100
    numberD: ${random.int(10,100)}
    # 随机产出一个uuid字符串
    uuid: ${random.uuid}
    yml基本格式写法

    2:配置文件与配置类属性映射

    (1):java配置获取基本的配置文件信息.properties类型

    三:配置类 jdbcConfig.java
    //声明此类为配置类
    @Configuration
    //导入外部配置文件 因为这个配置类是自定义的,不受SpringBoot帮我们管理
    @PropertySource(value="classpath:application.properties")
    public class JdbcConfig {
    
        @Value(value = "${jdbc.datasource.driver-class-name}")
        private String driver;
        @Value("${jdbc.datasource.url}")
        private String url;
        @Value("${jdbc.datasource.username}")
        private String username;
        @Value("${jdbc.datasource.password}")
        private String password;
    
        @Bean(value = "dataSource")
        public DataSource getDataSource() {
            System.out.println(driver);
            //创建连接池 并加入容器
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName(driver);
            dataSource.setUrl(url);
            dataSource.setUsername(username);
            dataSource.setPassword(password);
            return dataSource;
        }
    }
    
    四:Controller 通过访问运行程序 这里就先不写测试类
    @RestController //结合@ResponseBody 和 @Controller 两注解
    @RequestMapping("/index")
    public class IndexController {
    
        @Autowired
        private DataSource dataSource;
    
        @RequestMapping("/test")
        public String testMethod() {
            System.out.println("访问到此方法"+dataSource);
            return "Hello !!";
        }
    }
    
    //打印
    访问到此方法{
        CreateTime:"2021-01-09 15:22:49",
        ActiveCount:0,
        PoolingCount:0,
        CreateCount:0,
        DestroyCount:0,
        CloseCount:0,
        ConnectCount:0,
        Connections:[
        ]
    }
    基本数据获取.properties

    (2):java配置获取基本的配置文件信息并注入.yml/.yaml类型

    1、使用注解@Value映射
      @value注解将配置文件的值映射到Spring管理的Bean属性值,只能映射基本数据类型
    2、使用注解@ConfigurationProperties映射
      通过注解@ConfigurationProperties(prefix=''配置文件中的key的前缀")可以将配置文件中的配置自动与实体进行映射。
      使用@ConfigurationProperties方式必须提供Setter方法,使用@Value注解不需要Setter方法
    注:使用@ConfigurationProperties要在主函数上开启@EnableConfigurationProperties
    /**
     * @author: xiaofeng
     * @date: Create in $DATE
     * @description: 学生对象
     * @version: v1.0.0
     */
    @Component  //一定要保证被映射注入的是个组件
    @ConfigurationProperties(prefix = "student")  //可以之间映射对象 
    public class Student {
        private Integer id;                     //id
        private String name;                    //姓名
        private String address;                 //住宅
        private List<String> hobbys;            //爱好
        private Map<String, List<Integer>> score;//各科得分
        private Map<String,Teacher> teachers;    //各科老师
        //...省略get/set 这个一定要写 我为了代码少没复制
    }
    
    /**
     * @author: xiaofeng 
     * @date: Create in $DATE
     * @description: 老师对象
     * @version: v1.0.0
     */
    public class Teacher {
        private String name;
        private String message;
    }
    
    //注:在添加完@ConfigurationProperties后如果没有spring-boot-configuration-processor编译器会弹出提示
    //提示信息:Spring Boot Configuration Annotation Processor.....
    //pom.xml添加这个配置注解处理器
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    //然后去主函数类上面添加@EnableConfigurationProperties 开启配置注解处理器
    POJO实体类
    student:
      id: 1001
      name: 张三
      address: 安徽六安
      hobbys:
        - baseball
        - basketball
        - volleyball
      score:
        yuwen:
          - 66
          - 88
        shuxue:
          - 85
          - 99
      #简写 score: { "yuwen" : [58,99], "shuxue" : [88,96] }
      # 这里通过外界传入值 注意引号别忘了
      teachers:
        yuwenTeacher: { name: "${teacherNameA}", message: "${teacherMessageA}" }
        shuxueTecher: { name: "${teacherNameB}", message: "${teacherMessageB}" }
    
    teacherNameA: 张老师
    teacherMessageA: 教语文
    teacherNameB: 李老师
    teacherMessageB: 教数学
    application.yml配置文件
    //通过web的方式加载程序运行
    @RestController //结合@ResponseBody 和 @Controller 两注解 @RequestMapping("/index") public class IndexController { //注入 @Autowired private Student student; @RequestMapping("/test") public String testMethod() { System.out.println(student.toString()); //Student{ // id=1001, // name='张三', // address='安徽六安', // hobbys=[baseball, basketball, volleyball], // score={yuwen=[66, 88], shuxue=[85, 99]}, // teachers={yuwenTeacher=Teacher{name='张老师', message='教语文'}, // shuxueTecher=Teacher{name='李老师', message='教数学'}}} return "Hello !!"; } }

     五:SpringBoot与其它技术集成

     1:SpringBoot集成MyBatis  建表语句

      集成Mybatis完成查询全部

    (1):使用注解方式完成集成

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
             https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.4.1</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>cn.xw</groupId>
        <artifactId>demomybatiss</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>demomybatiss</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
        <dependencies>
            <!--web启动器-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--spring-boot启动器-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.4</version>
            </dependency>
            <!--工具-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <!--mysql驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <!--测试 这里没用到-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    pom.xml文件
    spring:
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/demo_school?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
        username: root
        password: 123
    # 加上 ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 是为了防止SpringBoot报时区错误
    # com.mysql.jdbc.Driver 这种的已经过时了,但是不代表就剔除了 可以用
    resources下的application.yml配置文件
    ///////////POJO
    /**
     * @author: xiaofeng
     * @date: Create in $DATE
     * @description: 学生实体类
     * @version: v1.0.0
     */
    public class Student implements Serializable {
        private int id;            //id
        private String name;       //姓名
        private String sex;        //性别
        private int age;           //年龄
        private double credit;      //成绩/学分
        private double money;      //零花钱
        private String address;    //住址
        private String enrol;      //入学时间
        //private int fid;    //外键 家庭
        //private int tid;    //外键 老师
        //构造器(无参构造器必须有)/set/get/toString  你们补充一下
    }
    
    /////////// Mapper
    //此注解org.apache.ibatis.annotations.Mapper 是mybatis提供的加入容器
    //Mapper 可以说等于 @Component、@Repository、@Server、@Controller
    @Mapper
    public interface StudentMapper {
        //查询全部
        @Select("select * from student")
        @Results(id = "studentMapper", value = {
                @Result(id = true, column = "sid", property = "id"),
                @Result(column = "sname", property = "name"),
                @Result(column = "ssex", property = "sex"),
                @Result(column = "sage", property = "age"),
                @Result(column = "scredit", property = "credit"),
                @Result(column = "smoney", property = "money"),
                @Result(column = "saddress", property = "address"),
                @Result(column = "senrol", property = "enrol")
        })
        List<Student> findAll();
    }
    
    ///////////Service
    /**
     * @author: xiaofeng
     * @date: Create in $DATE
     * @description: 学生业务接口
     * @version: v1.0.0
     */
    public interface StudentService {
        //查询全部
        List<Student> findAll();
    }
    /**
     * @author: xiaofeng
     * @date: Create in $DATE
     * @description: 学生业务实现
     * @version: v1.0.0
     */
    @Service    //注入到容器
    public class StudentServiceImpl implements StudentService {
    
        //注入对象  如果是IDEA编译器这边会有个红线错误,不影响
        @Autowired
        private StudentMapper studentMapper;
    
        //查询全部
        @Override
        public List<Student> findAll() {
            return studentMapper.findAll();
        }
    }
    
    //////////Controller
    @RestController
    @RequestMapping("/student")
    public class StudentController {
    
        @Autowired
        private StudentService studentService;
    
        @RequestMapping("/findAll")
        public List<Student> findAll() {
            System.out.println("访问成功");
            //这里通过json把对象写到浏览器,要序列化对象
            return studentService.findAll();
        }
    }
    POJO、Mapper、Service、Controller文件

    注:使用http://localhost:8080/student/findAll访问,还有就是Mapper文件夹里面的代码一定要写在主函数类当前包及其子包下,如果不在则需要在入口类添加@MapperScan或者@MapperScans注解扫描一下,这个是mybatis提供的

    (2):使用Mapper.xml映射完成集成

    spring:
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/demo_school?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
        username: root
        password: 123
    
    # spring继承mybatis环境
    # type-aliases-package:pojo别名扫描包
    # mapper-locations:加载mybatis映射文件
    mybatis:
      type-aliases-package: cn.xw.pojo
      mapper-locations: classpath:mapper/*Mapper.xml
    
    # 加上 ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 是为了防止SpringBoot报时区错误
    # com.mysql.jdbc.Driver 这种的已经过时了,但是不代表就剔除了 可以用
    更改application.yml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="cn.xw.mapper.StudentMapper">
        <!--名称字段不一样可以使用这个映射名称对应-->
        <resultMap id="studentMapper" type="student">
            <id column="sid" property="id"/>
            <result column="sname" property="name"/>
            <result column="ssex" property="sex"/>
            <result column="sage" property="age"/>
            <result column="sscore" property="credit"/>
            <result column="smoney" property="money"/>
            <result column="saddress" property="address"/>
            <result column="senrol" property="enrol"/>
        </resultMap>
        <!--查询全部学生    要使用上面的resultMap才可以-->
        <select id="findAll" resultMap="studentMapper">
            select * from student;
        </select>
    </mapper>
    在resources下创建mapper/StudentMapper.xml

    删除之前在Mapper使用注解的SQL语句删除,只留方法

     2:Spring Boot 集成 Redis

      springBoot集成Redis后,以上个案例的基础上做个查询学生缓存,如果第一次查询则缓存到redis服务器里,然后从redis读取数据返回到客户端

     <!--导入redis启动器-->
    <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    @RestController
    @RequestMapping("/student")
    public class StudentController {
    
        @Autowired
        private StudentService studentService;
    
        //注入redis模板对象
        @Autowired
        private RedisTemplate redisTemplate;
    
        @RequestMapping("/findAll")
        public List<Student> findAll() {
            System.out.println("访问成功");
    
            //获取类名
            String className = studentService.getClass().getName();
    
            //以类名+方法名的方式作为key来查询redis缓存数据
            List<Student> studentList = (List<Student>) redisTemplate.boundValueOps(className + "findAll").get();
            //redis没有数据 查询数据库放入到redis
            if (studentList == null) {
                System.out.println("从数据库查询数据放入到redis");
                //查询数据库
                studentList = studentService.findAll();
                //把查询到的数据放入redis中 key为类名加findAll
                redisTemplate.boundValueOps(className + "findAll").set(studentList);
            } else {
                System.out.println("从redis读取数据缓存");
            }
            //这里通过json把对象写到浏览器,要序列化对象
            return studentList;
        }
    }
    更改StudentController

    3:Spring Boot 集成定时器

         使用SpringBoot完成一个简易的定时器,每5秒输出一下当前的时间到控制台;

      首先在入口函数类上面加@EnableScheduling注解,代表开启定时器

    @Component
    public class TimerUtil {
        /**
         * @Scheduled 设置方法执行规则  就是定时任务设置
         * cron: 设置一个String类型的cron表达式  这个属性和下面6个不要混用
         * fixedDelay       以一个固定的延迟时间,上个任务完成后多久执行下一个任务
         * fixedDelayString 和上面一样字符串形式传值
         * fixedRate        以一个固定的频率运行,不管上一个任务执行时间
         * fixedRateString  和上面一样字符串形式传值
         * initialDelay         当项目初始化后多久触发事务的执行
         * initialDelayString   和上面一样字符串形式传值
         */
        //使用cron表达式
        @Scheduled(initialDelay=10000,fixedDelay = 5000)
        public void myTask(){
            System.out.println("当前时间:"+new Date());
        }
    }
    //注:写在入口函数类可扫描的范围包下
    编写定时器类

    4:Spring Boot 集成Test单元测试

    <!--测试启动start-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    //@RunWith(SpringRunner.class) 在老版的SpringBoot项目需要这个
    //2.2.0.RELEASE以后,springboot测试类不再需要@Runwith的注解
    @SpringBootTest //注明为SpringBoot测试类 class DemomybatissApplicationTests { //注入StudentService对象 @Autowired private StudentService studentService; @Test void contextLoads() { System.out.println(studentService.findAll()); } }

    5:Spring Boot 发送HTTP请求

      要在SpringBoot内部发送HTTP请求就得用到RestTemplate模板,它是Rest的HTTP客户端模板工具类;对基于HTTP客户端进行了封装;还实现了对象与JSON的序列化与反序列化;不限定客户端类型,目前常用的3种客户端都支持:HttpClient、OKHttp、JDK原生URLConnection(默认方式)

    @SpringBootApplication
    @EnableScheduling //开启定时器注解
    public class DemomybatissApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemomybatissApplication.class, args);
        }
        //注册RestTemplate对象放入IOC容器
        @Bean
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
    }
    入口函数类更改
    //@RunWith(SpringRunner.class) 在老版的SpringBoot项目需要这个
    @SpringBootTest //注明为SpringBoot测试类
    class DemomybatissApplicationTests {
        
        //注入RestTemplate对象
        @Autowired
        private RestTemplate restTemplate;
    
        @Test
        void contextLoads() {
            //String.class代表以字符串形式接收结果
            String forObject = restTemplate.getForObject("http://baidu.com", String.class);
            System.out.println(forObject);
            //打印
            //<html>
            //<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
            //</html>
        }
    }
    编写RestTemplate发送Http请求测试类

    6:扩展

      SpringBoot除了上面几个集成外还集成 MongoDB、ElasticSearch、Memcached、邮件服务:普通邮件、模板邮件、验证码、带Html的邮件、RabbitMQ消息中间件、Freemarker或者Thymeleaf等等

     六:SpringBoot打包部署

       启动方式有两种,一种是打成jar直接执行,另一种是打包成war包放到Tomcat服务下,启动Tomcat

    1:打成Jar包部署运行

      注:pom文件里的<packaging>jar</packaging>必须为jar,默认就是jar

    /**
     * 第一步:使用IDEA工具把写的代码通过maven的package打包
     * 第二步:找到打包后的target文件夹里面,把xxx.jar包扔给测试
     * 第三步:自己测试的话使用cmd执行下面命令,前提得检查自己的pom.xml文件中是否有springboot的maven插件
     * java -jar  xxxx.jar
     * 补充:在运行的时候传递参数 通过main函数的args接收
     * java -jar  xxxx.jar --server.port=8888
     * 补充:在运行的时候配置jvm参数,使占用更少的内存
     * java -Xmx80m -Xms20m -jar xxxx.jar
     */

     2:打成War包部署运行

      注:pom文件里的<packaging>war</packaging>必须为jar,默认就是war

    创建一个类如:ServletInitializer.java,继承 SpringBootServletInitializer ,覆盖 configure(),
    把启动类 Application 注册进去。外部 Web 应用服务器构建 Web Application Context 的时候,
    会把启动类添加进去。
    
    //如下代码创建的类 除了类名和注册的启动类不一样,其它是固定写法
    //WEB-INF/web.xml
    public class ServletInitializer extends SpringBootServletInitializer {
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
            //DemoApplication是自己当前项目的主函数
            return builder.sources(DemoApplication.class);
        }
    }

    七:SpringBoot热部署

      我们在之前每次写完代码之后都要重新部署运行,这样特别浪费时间,其实SpringBoot是支持热部署的,但是我们得有相对应的参数配置,导入坐标

    检查当前的pom.xml必须有此配置才可以,然后正常启动运行即可
    <!--
    工具 用于设置热部署,optional必须为true--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>

    当我们的代码写文运行后,后期更改了代码无需重写部署,只需要按CTRL+F9(Build Project),这是快速构建项目,或点击有上角的锤子;

    如果还觉得麻烦,那就设置,一旦更改代码,IDEA失去焦点就自动构建代码,我们要设置一下IDEA配置

     八:SpringBoot配置文件深入

    1:多环境配置文件

      我们在开发Spring Boot应用时,通常同一套程序会被安装到不同环境,比如:开发dev、测试test、生产pro等。其中数据库地址、服务器端口等等配置都不同,如果每次打包时,都要修改配置文件,那么非常麻烦。profile功能就是来进行动态配置切换的。

    (1):单文件的多环境配置

    # 在只有application.yml一个文件下配置多个配置环境就需要使用 " --- " 分隔界限
    # 为了规范 Dev为开发  Test为测试  Pro为生产
    # 配置完以后在这里选择要使用的配置环境
    spring:
      profiles:
        # 开启哪个环境下的配置文件
        active: oo
        # 引用包含哪个配置文件
        include: global
    
    # 开发环境配置  Dev
    ---
    server.port: 8881
    # 设置当前的配置界限为 dev开发环境
    spring.profiles: dev
    
    # 测试环境配置  Test
    ---
    server.port: 8882
    spring.profiles: test
    
    # 生产上线环境配置  Pro
    ---
    server.port: 80
    spring.profiles: pro
    
    # 全局的配置供include包含使用
    ---
    server.servlet.context-path: /littleBird
    spring.profiles: global
    单个application.yml配置文件完成多环境配置  不推荐

    (2):多文件的多环境配置 

    ⭐:application.yml 主配置文件(必须有)
    # 为了规范 Dev为开发  Test为测试  Pro为生产
    # 配置完以后在这里选择要使用的配置环境
    spring:
      profiles:
        # 开启哪个环境下的配置文件
        active: dev
        # 引入包含共有配置 
        include: common
    
    ⭐:application-dev.yml/properties 开发环境配置
    # 开发环境
    server.port: 8881
    
    ⭐:application-test.yml/properties 测试环境配置
    # 测试环境
    server.port: 8882
    
    ⭐:application-pro.yml/properties 生产环境配置
    # 上线环境
    server.port: 80
    
    ⭐:application-common.yml/properties 公共环境配置
    # 公共配置 供其包含导入
    server.servlet.context-path: /littleBird
    多文件配置多环境 推荐

    (3):profile激活方式

       在上面我介绍了使用配置文件来指定配置环境:spring.profiles.active=xx;可是这个是有局限性的,除了这种方式激活还要另外2种

    配置文件:  再配置文件中配置:spring.profiles.active=dev
    虚拟机参数:在VM options 指定:-Dspring.profiles.active=dev
    命令行参数:java –jar xxx.jar --spring.profiles.active=dev
    优先级:命令行参数 > 虚拟机参数 > 配置文件

    2:松散绑定

      不论配置文件中的属性值是短横线、驼峰式还是下换线分隔配置方式,在注入配置时都可以通过短横线方式取出值使用范围:properties文件、YAML文件、系统属性

    ⭐命名各种方式的名称 application.yml文件下定义方式
    # 短横线分隔
    parameter1: 
      spring-boot: 
        student-name: zhangsan 
    # 驼峰式
    parameter2:
      springBoot:
        studentName: lisi 
    # 下划线分隔
    parameter3:
      spring_boot:
        student_name: wangwu
    
    ⭐命名各种方式的名称 application.properties文件下定义方式
    # 短横线分隔
    parameter1.spring-boot.student-name=zhangsan
    # 驼峰式
    parameter2.springBoot.studentName=lisi
    # 下划线分隔
    parameter3.spring_boot.student_name: wangwu
    
    ⭐取出方式:使用短横线分隔可以取出上面的任意一直格式
    注:在@Value获取上面的3种方式命名的配置只能使用短横线分隔通配
    否则配置文件写啥名,获取就写啥名,一一对应
    @Value(value="${parameter1.spring-boot.student-name}")
    @Value(value="${parameter2.spring-boot.student-name}")
    @Value(value="${parameter3.spring-boot.student-name}")
    松散绑定配置文件介绍

    3:配置路径及其加载顺序

    4:外部配置加载顺序  官方文档

      外部加载顺序就是说在程序运行时加载外部的配置信息的顺序,如我们常用的命令行下指定额外信息 java -jar  xxx.jar --server.port=8888

    # 这个是2.1.11版本的springboot之前的信息,中文的看的清楚,以具体版本为准
    1:开启 DevTools 时, ~/.spring-boot-devtools.properties
    2:测试类上的 @TestPropertySource 注解
    3:@SpringBootTest#properties 属性
    4:==命令?参数(--server.port=9000 )==
    5:SPRING_APPLICATION_JSON 中的属性
    6:ServletConfig 初始化参数
    7:ServletContext 初始化参数
    8:java:comp/env 中的 JNDI 属性
    9:System.getProperties()
    10:操作系统环境变量
    11:random.* 涉及到的 RandomValuePropertySource
    12:jar 包外部的 application-{profile}.properties 或 .yml
    13:jar 包内部的 application-{profile}.properties 或 .yml
    14:jar 包外部的 application.properties 或 .yml
    15:jar 包内部的 application.properties 或 .yml
    16:@Configuration 类上的 @PropertySource
    17:SpringApplication.setDefaultProperties() 设置的默认属性
    中文介绍

     5:修改配置文件位置及默认名称

      我们知道配置文件只能以application.yml/properties来定义,但是名称不一样是可以指定具体文件名,也可以把配置文件放入其它位置并指定都是可以的;指定的方式我以cmd下指定参数 java -jar xxx.jar  --xxx  -xxx 方式指定,或在IDEA里面指定-xxx参数

    # 自定义配置文件名称
    --spring.config.name=myApplication
    # 指定配置文件存储位置 或 指定配置文件存储位置及配置文件名称
    --spring.config.location=classpath:/myconfig/myApplication.yml
    注:多个配置参数以空格隔开 --xxx -xxx

     九:SpringBoot监听器

      我们知道JavaEE包括13门规范,其中Servlet规范包括三个技术点:Servlet、Listener、Filter;而本章介绍的是监听器,监听器就是监听某个对象的状态变化;SpringBoot中的监听器有很多种:如下

    ①:CommandLineRunner 应用程序启动完成后
    ②:ApplicationRunner 应用程序启动完成后
    
    ③:ApplicationContextInitializer 程序运行初始化前
    ④:SpringApplicationRunListener 多功能监听器

    1:对开发者有益的监听器

    @Component  //实现CommandLineRunner接口的监听器必须要加入IOC容器
    public class MyCommandLineRunner implements CommandLineRunner {
        //注 参数args是主函数入口的args传来的
        @Override
        public void run(String... args) throws Exception {
            System.out.println("应用程序启动完成后 打印:CommandLineRunner");
        }
    }
    CommandLineRunner 监听器使用
    @Component  //实现ApplicationRunner接口的监听器必须要加入IOC容器
    public class MyApplicationRunner implements ApplicationRunner {
    
        //注 参数args是主函数入口的args传来的
        @Override
        public void run(ApplicationArguments args) throws Exception {
            System.out.println("应用程序启动完成后 打印:ApplicationRunner");
        }
    }
    ApplicationRunner 监听器使用

    2:对框架开发者有意义的监听器 功能多

    public class MyApplicationContextInitializer implements ApplicationContextInitializer {
        @Override
        public void initialize(ConfigurableApplicationContext applicationContext) {
            System.out.println("程序运行初始化前 打印:ApplicationContextInitializer");
        }
    }
    ApplicationContextInitializer 监听器使用
    public class MySpringApplicationRunListener implements SpringApplicationRunListener {
        //注意:此构造方法必须要写 不写就给你报个错误
        public MySpringApplicationRunListener(SpringApplication application, String[] args) {}
        @Override
        public void starting(ConfigurableBootstrapContext bootstrapContext) {
            System.out.println("应用程序开始启动==>starting");
        }
        @Override
        public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
            System.out.println("环境准备完成==>environmentPrepared");
        }
        @Override
        public void contextPrepared(ConfigurableApplicationContext context) {
            System.out.println("Spring容器准备完成==>contextPrepared");
        }
        @Override
        public void contextLoaded(ConfigurableApplicationContext context) {
            System.out.println("Spring容器加载完成==>contextLoaded");
        }
        @Override
        public void started(ConfigurableApplicationContext context) {
            System.out.println("应用程序启动完成==>started");
        }
        //注:running成功与failed异常只会存在一个
        @Override
        public void running(ConfigurableApplicationContext context) {
            System.out.println("应用程序开始运行==>running");
        }
        @Override
        public void failed(ConfigurableApplicationContext context, Throwable exception) {
            System.out.println("应用程序运行时抛出异常==>failed");
        }
    }
    SpringApplicationRunListener 监听器使用
    # 说明 在resources目录下创建META-INF文件夹 并在里面创建一个spring.factories
    # 主要目的是解耦:将监听器的配置权交给第三方厂商、插件开发者
    # 框架提供接口,实现类由你自己来写,释放原生API能力,增加可定制性
    # META-INF/spring.factories文件中配置接口的实现类名称
    
    # 配置ApplicationContextInitializer监听器的配置
    # 左边监听器的全路径名称=右边实现此监听器的全路径名
    org.springframework.context.ApplicationContextInitializer=cn.xw.lintener.MyApplicationContextInitializer
    # 配置SpringApplicationRunListener监听器的配置
    # 左边监听器的全路径名称=右边实现此监听器的全路径名
    org.springframework.boot.SpringApplicationRunListener=cn.xw.lintener.MySpringApplicationRunListener
    使用ApplicationContextInitializer/SpringApplicationRunListener监听器必看 配置一些信息才可使用

     十:自动配置实现分析

      我们在导入spring-boot-starter-web启动器无需其它配置就可以之间用,还有我们导入spring-boot-starter-data-redis启动器后可以直接使用@Autowired直接注入RedisTemplate对象,很奇怪吧,这就是SpringBoot自动配置特性,在下几节我慢慢引入

     1:@Import注解进阶

      当我们需要导入某个类到spring容器中去,但spring恰好无法扫描到这个类,而我们又无法修改这个类(jar包形式)。我们就可以通过@import(xxx.class)是将这个类导入到spring容器中

    (1):直接导入

    //配置类  springConfig
    @Configuration
    @Import(value={DateConfig.class})  //直接导入
    public class SpringConfig { }
    
    //普通类,里面有个@Bean注入方法  DateConfig
    //被任何一个配置类引用,当前自己类也变为子配置类
    public class DateConfig {
        //创建时间对象放入容器
        @Bean
        public Date createDate() { return new Date(); }
    }

    (2):通过配置类导入

    @Configuration
    public class SpringConfig {
        //创建时间对象放入容器
        @Bean
        public Date createDate() { return new Date(); }
    }
    
    @SpringBootApplication
    @Import(value={SpringConfig.class}) //导入配置类
    public class LintenerDemoApplication {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext run = SpringApplication.run(LintenerDemoApplication.class, args);
            //打印时间对象
            System.out.println(run.getBean(Date.class));
        }
    }

    (3):通过ImportSelector接口实现类导入  高级方式

    //普通类 里面有个@Bean注入对象
    public class DateConfig {
        //创建时间对象放入容器
        @Bean
        public Date createDate() { return new Date(); }
    }
    
    //创建一个类实现ImportSelector
    public class MyImportSelector implements ImportSelector {
        //这个方法是返回配置类的全类名,导入多少都行,最后通过@Import导入
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            //返回一个数组
            return new String[]{"cn.xw.config.DateConfig"};
        }
    }
    
    @SpringBootApplication
    @Import(value={MyImportSelector.class}) //导入配置类
    public class LintenerDemoApplication {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext run = SpringApplication.run(LintenerDemoApplication.class, args);
            //打印时间对象
            System.out.println(run.getBean(Date.class));
        }
    }
    使用ImportSelector接口

     2:@Configuration注解进阶

      相对这个注解大家肯定不陌生,只要是Spring注解配置类都有这玩意;其实只要添加@Configuration注解的类里面可以衍生出各种条件注解供我们使用,前提只能在注解类下使用,它就是@Conditional条件注解,这个条件注解又衍生出各种详细的条件注解

    注:@EnableAutoConfiguration 其本质是 @Import 和 @Configuration的组合

    一:class类条件
        @ConditionalOnClass == 存在指定类条件
        @ConditionalOnMissingClass == 不存在指定类条件
    二:属性条件
        @ConditionalOnProperty == 属性条件,还可以为属性设置默认值
    三:Bean条件
        @ConditionalOnBean == 存在Bean条件
        @ConditionalOnMissingBean == 不存在Bean条件
        @ConditionalOnSingleCondidate == 只有一个Bean条件
    四:资源条件
        @ConditionalResource == 资源条件
    五:Web应用条件
        @ConditionalOnWebApplication == web应用程序条件
        @ConditionalOnNotWebApplication == 不是web应用程序条件
    六:其他条件
        @ConditionalOneExpression == EL表达式条件
        @ConditionalOnJava == 在特定的Java版本条件

       @Configuration还有一些加载顺序的方式

    1:@AutoConfigureBefore==在那些自动配置之前执行
    2:@AutoConfigureAfter==在那些自动配置之后执行
    3:@AutoConfigureOrder==自动配置顺序

     (1):@ConditionalOnClass  与 @ConditionalOnProperty 介绍

    @ConditionalOnClass注解属性介绍
        Class<?>[] value():以类的class形式的数组
        String[] name():以类的全路径名的字符串数组
    
    @ConditionalOnProperty注解属性介绍
        value 和 name:数组,获取对应property名称的值,它们只能存在其中一个
        prefix:配置属性名称的前缀,比如spring.http.encoding
        havingValue:可与name组合使用,比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置
        matchIfMissing:缺少该配置属性时是否可以加载。如果为true,没有该配置属性时也会正常加载;反之则不会生效
    //学生类
    public class Student {
        private String name;
        private String identity;
        //省略了get/set,
    }
    
    //老师类
    public class Teacher {
        private String name;
        private String identity;
        //省略了get/set,
    }
    
    
    //需求,当创建Teacher加入容器时得判断当前是否存在Student这个类
    @Configuration
    @ConditionalOnClass(name = "cn.xw.pojo.Student")
    public class SpringConfig {
        
        //可以通过spring.myconfig.enable=true开启 或者false 关闭容器注册
        @Bean(value = "teacher")
        @ConditionalOnProperty(prefix = "spring.myconfig", name = "enable", havingValue ="true", matchIfMissing = true)
        public Teacher createTeacher() {
            Teacher teacher = new Teacher();
            teacher.setName("张老师");
            teacher.setIdentity("老师");
            return teacher;
        }
    }
    
    @SpringBootApplication
    //导入配置类
    @Import(value={SpringConfig.class})
    public class LintenerDemoApplication {
        public static void main(String[] args) {
            ConfigurableApplicationContext run = SpringApplication.run(LintenerDemoApplication.class, args);
            //打印时间对象
            System.out.println(run.getBean(Teacher.class).getName());
        }
    }
    
    //application.properties
    # 关闭容器注册
    spring.myconfig.enable=false
    案例讲解注解
    //注解类
    @Configuration(proxyBeanMethods = false)
    //条件注解 确保存在RedisOperations类
    @ConditionalOnClass(RedisOperations.class)
    //@Import 和  @ConfigurationProperties结合  RedisProperties类就是我们配置额外变量的spring.redis
    @EnableConfigurationProperties(RedisProperties.class)
    //导入配置类
    @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
    public class RedisAutoConfiguration {
    
        @Bean
        //判断不存在redisTemplate的Bean条件
        @ConditionalOnMissingBean(name = "redisTemplate")
        //判断只有一个RedisConnectionFactory的Bean条件
        @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
        public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<Object, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }
    
        //下面差不多
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
        public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
            StringRedisTemplate template = new StringRedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }
    }
    RedisTemplate自动注入分析

     十一:自定义auto-Configuration及starter

       我们平常导入是第三方mybatis-spring-boot-starter启动器都是由第三方提供给,特点就是以mybatis开头,那下面我们自定义starter也得是自定义名称开头,我们要自定义auto-Configuraction并使用必备的四个角色功能主体框架、自动配置模块、starter模块、开发者引用

    1:定制自动配置必要内容
        autoconfiguration模块,包含自动配置代码。自定义 *-spring-boot-autoconfigure。
        starter模块。自定义 *-spring-boot-starter
    2:自动配置命名方式
        官方的Starters
            spring-boot-starter-*  如:spring-boot-starter-web
        非官方的starters
            *-spring-boot-starter  如:mybatis-spring-boot-starter
    3:SpringBoot起步依赖,Starter Dependencies

       接下来我要创建一个第三方模块,功能主体模块是一个图形打印模块,根据配置文件的不同打印出不同的图案,还要就是一个自动配置模块和starter模块咯,最后由我来在普通的springboot应用中调用这个自定义的自动配置

    (1):功能主体模块

    ⭐主体功能模块maven坐标
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
             http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>cn.tx</groupId>
        <artifactId>graphic-printing</artifactId>
        <version>1.0-SNAPSHOT</version>
        <!--设置maven使用什么版本的jdk解析编译-->
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
        </properties>
    </project>
    ⭐主体功能模块具体类方法
    //图形打印对象
    public class GraphicPrintingUtil {
        private Integer width = 4;
        private Integer height = 3;
        //别忘了添加get/set方法,后面会参数注入
    
        //打印图形 方法
        public void graphicPrinting() {
            System.out.println(">图形开始打印<");
            for (int i = 1; i <= height; i++) {
                for (int j = 1; j <= width; j++) {
                    System.out.print(" * ");
                }
                System.out.println();
            }
        }
    }
    功能主体代码 模块名:graphic-printing

    (2):自动配置模块

    ⭐自动配置模块maven坐标
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
             http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <!--导入Springboot父坐标-->
        <parent>
            <artifactId>spring-boot-starter-parent</artifactId>
            <groupId>org.springframework.boot</groupId>
            <version>2.4.1</version>
        </parent>
        <!--当前本项目的一些信息-->
        <groupId>cn.tx</groupId>
        <artifactId>graphic-spring-boot-autoconfigure</artifactId>
        <version>1.0-SNAPSHOT</version>
        <!--坐标-->
        <dependencies>
            <!--导入SpringBoot的自动配置坐标 因为代码中要写配置注解-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-autoconfigure</artifactId>
            </dependency>
            <!--导入我们之前创建的主体模块graphic-printing-->
            <dependency>
                <groupId>cn.tx</groupId>
                <artifactId>graphic-printing</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>
    </project>
    ⭐自动配置模块具体类方法
    ## GraphicConfiguration类
    @Configuration  //注解类
    @Import(value = {GraphicProperties.class})  //导入配置类
    @ConditionalOnClass(GraphicPrintingUtil.class)//判断当前项目是否存在GraphicPrintingUtil类
    public class GraphicConfiguration {
        @Bean
        @ConditionalOnProperty(prefix = "graphic.printing", name = "enable", havingValue = "true", matchIfMissing = true)
        //@ConfigurationProperties(prefix = "graphic.config") 可以使用此注解直接注入 注入时值可有可无
        public GraphicPrintingUtil createGraphicPrintingUtil(GraphicProperties g) {
            //创建图形打印对象,主体模块上的对象
            GraphicPrintingUtil printingUtil = new GraphicPrintingUtil();
            //设置宽高
            printingUtil.setHeight(g.getHeight());
            printingUtil.setWidth(g.getWidth());
            return printingUtil;
        }
    }
    
    ##  GraphicProperties 配置类
    //这里报红不管他,后面使用者导入<artifactId>spring-boot-configuration-processor</artifactId>
    @ConfigurationProperties(prefix = "graphic.config")
    public class GraphicProperties {
        private Integer width;
        private Integer height;
        //别忘了写get/set
    }
    自动配置代码 模块名:graphic-spring-boot-autoconfigure
    # 注册自定义自动配置
    # 前面是固定的,后面是自定义配置类
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.tx.config.GraphicConfiguration
    在resources下创建META-INF文件夹,并在下面创建spring.factories配置

    (3):stater模块

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
             http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <!--自己项目坐标-->
        <groupId>cn.tx</groupId>
        <artifactId>graphic-spring-boot-starter</artifactId>
        <version>1.0-SNAPSHOT</version>
        <dependencies>
            <!--主体功能模块-->
            <dependency>
                <groupId>cn.tx</groupId>
                <artifactId>graphic-printing</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <!--自动配置类autoconfigure-->
            <dependency>
                <groupId>cn.tx</groupId>
                <artifactId>graphic-spring-boot-autoconfigure</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>
    </project>
    stater模块 模块名:graphic-spring-boot-starter

      注:此模块啥都不用,只要pom.xml文件即可

    (3):开发者引用

    注:此模块和正常SpringBoot一样,可以使用脚手架构建
    ⭐使用者maven坐标
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
             https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <!--springboot父坐标-->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.4.1</version>
            <relativePath/>
        </parent>
        <!--本项目的坐标信息-->
        <groupId>cn.xw</groupId>
        <artifactId>test001</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>test001</name>
        <description>Demo project for Spring Boot</description>
        <properties>
            <java.version>1.8</java.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
            <!--导入我们自定义的stater启动器-->
            <dependency>
                <groupId>cn.tx</groupId>
                <artifactId>graphic-spring-boot-starter</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <!--一定要导入,是为了注入配置文件里面的数值-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <optional>true</optional>
            </dependency>
        </dependencies>
        <!--maven插件-->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    ⭐使用者具体类方法
    @SpringBootApplication
    public class Test001Application {
        public static void main(String[] args) {
            ConfigurableApplicationContext run = SpringApplication.run(Test001Application.class, args);
            //ConfigurableApplicationContext是ClassPathXmlApplicationContext子类
            run.getBean(GraphicPrintingUtil.class).graphicPrinting();
        }
    }
    ⭐配置文件application.properties
    graphic.printing.enable=true
    graphic.config.width=10
    graphic.config.height=15
    开发者模块 模块名:test001

     十二:切换内置web应用服务器

    SpringBoot的web环境中默认使用tomcat作为内置服务器,其实还提供了另外2种内置服务器供我们选择,我们可以很方便的进行切换。
    1:Tomcat:这个是使用最广泛但性能不太好的web应用服务器  默认
    2:Jetty:Jetty 是一个开源的servlet容器,它为基于Java的web容器,例如JSP和servlet提供运行环境。
    3:Undertow: 是红帽公司开发的一款基于 NIO 的高性能 Web 嵌入式服务器

      Tomcat方式:Tomcat started on port(s): 8080 (http) with context path ''
      Jetty方式:Jetty started on port(s) 8080 (http/1.1) with context path '/'
      Undertow方式:Undertow started on port(s) 8080 (http)

    <!--导入web的starter启动器-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <!--一定要排除tomcat的starter   因为默认就是tomcat-->
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-tomcat</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!--导入jetty容器依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jetty</artifactId>
            </dependency>
    切换为Jetty
     <!--导入web的starter启动器-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <!--一定要排除tomcat的starter   因为默认就是tomcat-->
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-tomcat</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!--导入undertow容器依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-undertow</artifactId>
            </dependency>
    切换Undertow

     十三:SpringBoot生产级监控

      SpringBoot自带监控功能Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、配置属性、日志信息等

     1:项目集成Actuator监控服务

      其实导入健康服务特别简单,任何一个SpringBoot只需要加入一个监控启动器则可开启监控服务,然后项目正常运行即可

    <!--监控服务Actuator启动器-->
    <
    dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>

      保存SpringBoot导入监控坐标后启动程序,在程序运行的情况下访问 http://localhost:8080/actuator 则可监控程序

     

     补充:默认只可以监控这几项,其实可以监测很多模块

     路径                描述                                默认开启
    /beans            显示容器的全部的Bean,以及它们的关系        N
    /env            获取全部环境属性                           N
    /env/{name}        根据名称获取特定的环境属性值                N
    /health            显示健康检查信息                           Y
    /info            显示设置好的应用信息                       Y
    /mappings        显示所有的@RequestMapping信息               N
    /metrics        显示应用的度量信息                           N
    /scheduledtasks    显示任务调度信息                           N
    /httptrace        显示Http Trace信息                          N
    /caches            显示应用中的缓存                           N
    /conditions        显示配置条件的匹配情况                        N
    /configprops    显示@ConfigurationProperties的信息           N
    /loggers        显示并更新日志配置                            N
    /shutdown        关闭应用程序                               N
    /threaddump        执行ThreadDump                              N
    /headdump        返回HeadDump文件,格式为HPROF               N
    /prometheus        返回可供Prometheus抓取的信息               N
    监控应用endpoint

    常用application.properties配置

    # 暴露所有的监控点
    management.endpoints.web.exposure.include=*
    # 定义Actuator访问路径
    management.endpoints.web.base-path=/act
    # 开启endpoint 关闭服务功能  访问关闭路径只能发送post请求才可关闭
    management.endpoint.shutdown.enabled=true

    .

  • 相关阅读:
    Fusion access
    组网架构
    DHCP中继
    Vxlan配置
    redis多实例
    ansible实现redis角色
    ansible如何ssh免密链接(基于key验证)
    MySQL主从复制
    MySQL范例
    Ubuntu2004安装
  • 原文地址:https://www.cnblogs.com/antLaddie/p/14253334.html
Copyright © 2020-2023  润新知