SpringBoot

概述

SpringBoot快速入门

SpringBoot起步依赖原理分析

spring-boot-starter-parent

spring-boot-starter-web

这几个起步依赖都是springboot定义好了的各种技术jar包最优搭配,不会造成依赖冲突

Springboot配置

配置文件分类

properties

server.port=8080

yml

server:
	port: 8080

yaml

server:
	port: 8080

小结:

  • springboot加载顺序不同,提供了两种配置文件类型:properties和yml/yaml
  • 默认配置文件名称是: application
  • 在同一级目录下配置文件类型的加载顺序优先级是properties>yml>yaml

YAML

yaml不是一种标记语言,他是以数据为核心的,省去其他的繁琐的语法格式

基本语法

  • 大小写敏感
  • 数据值前边必须有空格,作为分隔符
  • 使用缩进表示层级关系
  • 缩进时不允许使用Tab键,只允许使用空格(各个系统Tab对应的空格数目可能不同,导致层次混乱)。
  • 缩进的空格数目不重要,只要相同层级的元素左则对齐即可
  • #表示注释,从这个字符一直到行尾,都会被解析器忽略。

数据格式

  • 对象(map):键值对的集合

    person:
    	name: zhangsan
    #行内写法
    person: {name: zhangsan}
    
  • 数组:一组按次序排列的值

    address:
    	- beijing
    	- shanghai
    #行内写法
    address: [beijing,shanghai]
    
  • 纯量:单个的,不可再分的值

    msg1: 'hello \n word' #单引号忽略转义字符直接输出
    msg2: "hello \n word" #双引号会识别换行
    

参数引用

  • name: lisi
    person: 
    	name: ${name}
    

获取数据

  • //第一种通过@Value注解注入JavaBean属性获取数据
    @Value("键名称")
    	private String name;
    //第二种通过创建Environment对象,通过调用方法获取
    Environment对象获取数据
        private Environment env;
    	env.getProperty("键名称");
    //第三种通过给JavaBean添加@ConfigurationProperties注解来将yaml数据注入JavaBean属性中
    @ConfigurationProperties(prefix = "数据键名称")
    public class Person{
        private String name;
        private int age;
        private String address;
        getter/setter/toString..
    }
    sout(Person)
    

profile

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

  • profile配置方式

    • 多profile文件方式

      • 通过创建多个Properties 使用 spring.profile.active=配置名称

        spring.profile.active=dev/test/pro
        
    • yml多文档方式

      • 通过在yml文档使用---分隔多环境配置,使用spring.profile标识

      • 再使用spring.profile.active=配置名称激活配置

        ---
        server:
        	prot: 8080
        spring:
        	profile: dev
        ---
        server:
        	prot: 8081
        spring:
        	profile: test
        ---
        server:
        	prot: 8082
        spring:
        	profile: pro
        ---
        
  • profile激活方式

    • 配置文件:在配置文件中配置:spring.profiles.active=dev
    • 虚拟机参数:在VM options 指定:-Dspring.profile.active=dev
    • 命令行参数:java -jar xxx.jar --spring.profile.active=dev

内部加载顺序

springboot程序启动时,会从一下位置加载配置文件:

  • file:…/config/:当前项目下的/config目录下
  • file:./ :当前项目根目录
  • classpath:/config/: classpath的/config目录
  • classpath:/ classpath的根目录

加载那些为上文的排列顺序,高优先级配置的属性会生效

外部加载顺序

  • 命令行加载
  • 外部文件加载
    • 外部配置文件在同级目录下会覆盖加载相同的配置
    • 外部配置config文件夹在同级目录内也会覆盖加载相同的配置

Springboot整合其它框架

Springboot高级

Springboot原理分析

自动配置

condition

spring4.0之后添加的条件功能,具体根据条件自动获取对象初始化实现方法

  • 创建配置类添加配置类注解@Configuration

  • 创建方法 返回对象,添加@Bean注解

  • 添加@Conditionl注解传入参数条件加载类

  • 创建条件类实现Condition接口复写matches方法

    //配置类
    @Configuration
    public class UserConfig(){
        @Bean
        @Conditional(ClassCondition.class)
        public User user(){
            return new User();
        }
    }
    //条件类
    public class Classcondition implements Condition {
    @override
    public boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata){
    		return false;
    	}
    }
    
    
condition小结
  • 自定义条件:

    1. 定义条件类:自定义类实现Condition接口,重写matches方法,在matches方法中进行逻辑判断,返回boolean值。matches方法两个参数:

      • context: 上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等。

      • metadata:元数据对象,用于获取注解属性。

    2. 判断条件:在初始化Bean时,使用==@conditional(条件类.class)==注解

  • SpringBoot提供的常用条件注解:

    • conditionalonProperty: 判断配置文件中是否有对应属性和值才初始化Bean
    • conditionalonclass: 判晰环境中是否有对应字节码文件才初始化Bean
    • conditionalonMissingBean: 判断环境中没有对应Bean才初始化Bean
      定义条件类:自定义类实现Condition接口,重写matches方法,在m atches方法中进行逻辑判断,返回

切换内置web服务器

Enable注解

  • SpringBoot不能直接获取在其他工程中定义的Bean

  • 原因是在组件扫描范围,当前引导类所在包及其子包

  • 三种解决方案

    1. 使用@ComponentScan扫描com.itheima.config包

    2. 可以使用@Import注解,加载类。这些类都会被Spring创建,并放入IOC容器

    3. 可以对Import注解进行封装。

    重点:Enable注解底层原理是使用@Import注解实现Bean的动态加载

自定义starter实现

SpringBoot提供的starter以spring-boot-starter-xxx的方式命名的。官方建议自定义的starter使用xxx-spring-boot-starter命名规则。以区分SpringBoot生态提供的starter。

新建一个工程

image-20200919204706917

pom文件

<?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>
    <groupId>com.itheima</groupId>
    <artifactId>redis-spring-boot-autoconfigure</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>redis-spring-boot-autoconfigure</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.0.RELEASE</spring-boot.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--引入jedis依赖-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

定义实体映射配置信息类

@ConfigurationProperties(prefix = "demo") 它可以把相同前缀的配置信息通过配置项名称映射成实体类,比如我们这里指定 prefix = “demo” 这样,我们就能将以demo为前缀的配置项拿到了。
ps:其实这个注解很强大,它不但能映射成String或基本类型的变量。还可以映射为List,Map等数据结构。

package com.itheima.redis.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;


@ConfigurationProperties(prefix = "redis")
public class RedisProperties {
    private String host = "localhost";
    private int port = 6379;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }
}

定义配置类

这里,我们将DemoService类定义为一个Bean,交给Ioc容器。

  • @Configuration 注解就不多说了。

  • @EnableConfigurationProperties 注解。该注解是用来开启对3步骤中 @ConfigurationProperties 注解配置Bean的支持。也就是@EnableConfigurationProperties注解告诉Spring Boot 能支持@ConfigurationProperties。当然了,也可以在 @ConfigurationProperties 注解的类上添加 @Configuration 或者 @Component 注解

  • @ConditionalONClass 注解控制指定的Bean是否存在。简单来说也就是我们可以通过检测指定Bean是否存在类路径上,控制 @Configuration 注解的配置类是否生效。

package com.itheima.redis.config;

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;

@Configuration
@EnableConfigurationProperties(RedisProperties.class)
@ConditionalOnClass(Jedis.class)
public class RedisAutoConfiguration {
    /**
     * 提供jedis的Bean
     */
    @Bean
    @ConditionalOnMissingBean(name = "jedis")
    public Jedis jedis(RedisProperties redisProperties) {
        System.out.println("RedisAutoConfiguration...");
        return new Jedis(redisProperties.getHost(), redisProperties.getPort());
    }
}

最重要的

如图,新建META-INF文件夹,然后创建spring.factories文件,

img

在该文件中加入如下配置,该配置指定上步骤中定义的配置类为自动装配的配置。

image-20200919212642929

前面是固定的springboot自动装配类全包名,后面是配置类

测试工程引入配置工程starter测试

Springboot监听

springboot四个监听

  • 自定义监听器的启动时机:MyApplicationRunner和MyCommandLineRunner都是当项目启动后执行,使用@Component放入容器即可使用

ApplicationRunner

MyApplicationRunner

/**
 * 当项目启动后执行run方法。
 */
@Component
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("ApplicationRunner...run");
        System.out.println(Arrays.asList(args.getSourceArgs()));
    }
} 

CommandLineRunner

MyCommandLineRunner

@Component
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("CommandLineRunner...run");
        System.out.println(Arrays.asList(args));
    }
}

ApplicationContextInitializer

MyApplicationContextInitializer的使用要在resource文件夹下添加META-INF/spring.factories

org.springframework.context.ApplicationContextInitializer=com.itheima.springbootlistener.listener.MyApplicationContextInitializer
@Component
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("ApplicationContextInitializer....initialize");
    }
}

SpringApplicationRunListener

MySpringApplicationRunListener的使用要添加构造器

public class MySpringApplicationRunListener implements SpringApplicationRunListener {

    public MySpringApplicationRunListener(SpringApplication application, String[] args) {
    }

    @Override
    public void starting() {
        System.out.println("starting...项目启动中");
    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        System.out.println("environmentPrepared...环境对象开始准备");
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        System.out.println("contextPrepared...上下文对象开始准备");
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        System.out.println("contextLoaded...上下文对象开始加载");
    }

    @Override
    public void started(ConfigurableApplicationContext context) {
        System.out.println("started...上下文对象加载完成");
    }

    @Override
    public void running(ConfigurableApplicationContext context) {
        System.out.println("running...项目启动完成,开始运行");
    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        System.out.println("failed...项目启动失败");
    }
}

SpringBoot流程分析-初始化

  1. 配置启动引导类(判断是否有启动主类)

  2. 判断是否是Web环境

  3. 获取初始化类、监听器类

1571369439416

SpringBoot流程分析-run**

  1. 启动计时器

  2. 执行监听器

  3. 准备环境

  4. 打印banner:可以resource下粘贴自定义的banner

  5. 创建context

    refreshContext(context);
    

    执行refreshContext方法后才真正创建Bean

1571373793325

Springboot监控

导入坐标

<dependency>
    <groupld>org.springframework.boot</groupld>
    <artifactld>spring-boot-starter-actuator</artifactld>
</dependency>

访问localhost:8080/actuator

Springboot项目部署

SpringBoot 项目开发完毕后,支持两种方式部署到服务器:

①jar包(官方推荐)

②war包

更改pom文件中的打包方式为war

修改启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class SpringbootDeployApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootDeployApplication.class, args);
    }


    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(SpringbootDeployApplication.class);
    }
}

指定打包的名称

 <build>
        <finalName>springboot</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

asset表 assetId ,assetSn assetName

department表 departmentName

上一篇 下一篇