springboot基础知识集结,你get到了吗!

一、SpringBoot的特点

Spring Boot 主要目标是:

  • 为所有 Spring 的开发者提供一个非常快速的、广泛接受的入门体验
  • 开箱即用(启动器starter-其实就是SpringBoot提供的一个jar包),但通过自己设置参数(.properties),即可快速摆脱这种方式。
  • 提供了一些大型项目中常见的非功能性特性,如内嵌服务器、安全、指标,健康检测、外部化配置等
  • 绝对没有代码生成,也无需 XML 配置。

更多细节,可以到官网查看。

二、 SpringBoot的核心功能

  • 起步依赖

    起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。

    简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。

  • 自动配置

    Spring Boot的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定Spring配置应该用哪个,不该用哪个。该过程是Spring自动完成的。

三、SpringBoot原理分析

起步依赖原理分析
分析spring-boot-starter-parent

按住Ctrl点击pom.xml中的spring-boot-starter-parent,跳转到了spring-boot-starter-parent的pom.xml,xml配置如下(只摘抄了部分重点配置):

 <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.2.2.RELEASE</version>
    <relativePath>../../spring-boot-dependencies</relativePath>
  </parent>

按住Ctrl点击pom.xml中的spring-boot-starter-dependencies,跳转到了spring-boot-starter-dependencies的pom.xml,xml配置如下(只摘抄了部分重点配置):

 <properties>
    <activemq.version>5.15.11</activemq.version>
    <antlr2.version>2.7.7</antlr2.version>
    <appengine-sdk.version>1.9.77</appengine-sdk.version>
    <artemis.version>2.10.1</artemis.version>
    <aspectj.version>1.9.5</aspectj.version>
    <assertj.version>3.13.2</assertj.version>
    <atomikos.version>4.0.6</atomikos.version>
    <awaitility.version>4.0.1</awaitility.version>
    <bitronix.version>2.1.4</bitronix.version>
    <build-helper-maven-plugin.version>3.0.0</build-helper-maven-plugin.version>
  	... ... ...
</properties>
 <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot</artifactId>
        <version>2.2.2.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-test</artifactId>
        <version>2.2.2.RELEASE</version>
      </dependency>
      	... ... ...
	</dependencies>
</dependencyManagement>
 <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.johnzon</groupId>
          <artifactId>johnzon-maven-plugin</artifactId>
          <version>${johnzon.version}</version>
        </plugin>
        <plugin>
          <groupId>org.jetbrains.kotlin</groupId>
          <artifactId>kotlin-maven-plugin</artifactId>
          <version>${kotlin.version}</version>
        </plugin>
          	... ... ...
    	</plugins>
  	</pluginManagement>
</build>

从上面的spring-boot-starter-dependencies的pom.xml中可以发现,一部分坐标的版本、依赖管理、插件管理已经定义好,所以我们的SpringBoot工程继承spring-boot-starter-parent后已经具备版本锁定等配置了。所以起步依赖的作用就是进行依赖的传递。spring-boot-starter-web分析源码也是一样,可自行查看

四、自动配置原理解析

按住Ctrl点击查看启动类MySpringBootApplication上的注解@SpringBootApplication

@SpringBootApplication
public class TestApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class);
    }
}
@SpringBootApplication的源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    .....
}
  • @SpringBootConfiguration:等同与@Configuration,既标注该类是Spring的一个配置类

  • @EnableAutoConfiguration:SpringBoot自动配置功能开启

@EnableAutoConfiguration源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
	... ... ...
}
  • @Import(AutoConfigurationImportSelector.class) 导入了AutoConfigurationImportSelector类

按住Ctrl点击查看AutoConfigurationImportSelector源码

@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
				annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}


	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				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;
	}

其中,**SpringFactoriesLoader.loadFactoryNames **方法的作用就是从META-INF/spring.factories文件中读取指定类对应的类名称列表

在这里插入图片描述

spring.factories 文件中有关自动配置的配置信息如下

... ... ...

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\

... ... ...

上面配置文件存在大量的以Configuration为结尾的类名称,这些类就是存有自动配置信息的类,而SpringApplication在获取这些类名后再加载

  • 源码示例

以ServletWebServerFactoryAutoConfiguration为例来分析源码:

//声明这个类是一个配置类
@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
//判断你是否引入了相关依赖,引入依赖后该条件成立,当前类的配置才会生效
@ConditionalOnClass(ServletRequest.class)
//满足项目的类是是Type.SERVLET类型,也就是一个普通web工程
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
		ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
		ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
		ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
	... ... ...
}

@EnableConfigurationProperties(ServerProperties.class) 代表加载ServerProperties服务器配置属性类

进入ServerProperties.class源码如下:

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {

	/**
	 * Server HTTP port.
	 */
	private Integer port;

	/**
	 * Network address to which the server should bind.
	 */
	private InetAddress address;
  
  	... ... ...
  
}

prefix = “server” 表示SpringBoot配置文件中的前缀,SpringBoot会将配置文件中以server开始的属性映射到该类的字段中。

@ComponentScan

源码翻译:

配置组件扫描的指令。提供了类似与<context:component-scan>标签的作用

通过basePackageClasses或者basePackages属性来指定要扫描的包。如果没有指定这些属性,那么将从声明这个注解的类所在的包开始,扫描包及子包

而@SpringBootApplication注解声明的类就是main函数所在的启动类,因此扫描的包是该类所在包及其子包。因此,一般启动类会放在一个比较前的包目录中。

五、SpringBoot的配置文件

SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用application.properties或者application.yml(application.yaml)进行配置。SpringBoot默认会从Resources目录下加载application.properties或application.yml(application.yaml)文件。

application.yml配置文件
语法示例

普通数据:

  • 语法: key: value

  • 示例代码:

  • name: test
    
  • 注意:value之前有一个空格

对象数据:

  • 语法:

    ​ key:

    ​ key1: value1

    ​ key2: value2

    ​ 或者:

    ​ key: {key1: value1,key2: value2}

  • 示例代码:

  • person:
      name: test
      age: 18
      addr: shenzhen
    #或者
    person: {name: test,age: 18,addr: shenzhen}
    
  • 注意:key1前面的空格个数不限定,在yml语法中,相同缩进代表同一个级别

Map数据 :

同上面的对象写法

数组(List、Set)数据:

  • 语法:

    ​ key:

    ​ - value1

    ​ - value2

    或者:

    ​ key: [value1,value2]

  • 示例代码:

  • city:
      - shenzhen
      - shanghai
      - shandong
      - chongqing
      
    #或者
    city: [shenzhen,shanghai,shandong,chongqing]
    
    #集合中的元素是对象形式
    student:
      - name: zhangsan
        age: 18
        score: 100
      - name: lisi
        age: 28
        score: 88
      - name: wangwu
        age: 38
        score: 90
    
  • 注意:value1与之间的 - 之间存在一个空格

SpringBoot多环境配置

在实际开发的过程中,项目会经历很多的阶段(开发->测试->上线),每个阶段的配置也会不同,例如:端口、上下文根、数据库等,那么这个时候为了方便在不同的环境之间切换,SpringBoot提供了多环境配置,简单示例如下:

application-dev.properties

#开发环境

#设置内嵌Tomcat默认端口号
server.port=8080

application-product.properties

#生产环境

#配置内嵌Tomcat默认端口号
server.port=80

application-test.properties

#测试环境

#配置内嵌Tomcat端口号
server.port=8081

● 在总配置文件application.properties进行环境的激活

#SpringBoot的总配置文件

#激活开发环境
#spring.profiles.active=dev

#激活测试环境
#spring.profiles.active=test

#激活生产环境
spring.profiles.active=product

六、 SpringBoot配置信息的查询

SpringBoot的官方文档:https://docs.spring.io/spring-boot/docs/2.0.1.RELEASE/reference/htmlsingle/#common-application-properties

例如:

# EMBEDDED SERVER CONFIGURATION (ServerProperties)
server.port=8080 # Server HTTP port.
server.servlet.context-path= # Context path of the application.
server.servlet.path=/ # Path of the main dispatcher servlet.

那么可以通过配置application.poperties 或者 application.yml 来修改SpringBoot的默认配置

例如:

application.yml文件

server:
  port: 6666

七、springboot读取配置文件方式

@PropertySource配合@value使用

引入Druid连接池依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.6</version>
</dependency>

创建一个jdbc.properties文件,编写jdbc属性:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test
jdbc.username=root
jdbc.password=root

然后编写代码:

@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
    @Value("${jdbc.url}")
    String url;
    @Value("${jdbc.driverClassName}")
    String driverClassName;
    @Value("${jdbc.username}")
    String username;
    @Value("${jdbc.password}")
    String password;
    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}

解读:

  • @Configuration:声明我们JdbcConfig是一个配置类

  • @PropertySource:指定属性文件的路径是:classpath:jdbc.properties

    若此例jdbc的属性放在application.yml,那么可以不使用@PropertySource@Value默认读取;

  • 通过@Value为属性注入值

  • 通过@Bean将 dataSource()方法声明为一个注册Bean的方法,Spring会自动调用该方法,将方法的返回值加入Spring容器中。

@ConfigurationProperties使用

在上面的案例中,我们实验了java配置方式。不过属性注入使用的是@Value注解。这种方式虽然可行,但是不够强大,因为它只能注入基本类型值。

在SpringBoot中,提供了一种新的属性注入方式,支持各种java基本数据类型及复杂类型的注入。

新建一个类,用来进行属性注入:
@ConfigurationProperties(prefix = "jdbc")
public class JdbcProperties {
    private String url;
    private String driverClassName;
    private String username;
    private String password;
    // ... 略
    // getters 和 setters
}

  • 在类上通过@ConfigurationProperties注解声明当前类为属性读取类

  • prefix="jdbc"读取属性文件中,前缀为jdbc的值。

  • 在类上定义各个属性,名称必须与属性文件中jdbc.后面部分一致

  • 需要注意的是,这里并没有指定属性文件的地址,所以我们需要把jdbc.properties名称改为application.properties,这是SpringBoot默认读取的属性文件名:

在JdbcConfig中使用这个属性:
@Configuration
@EnableConfigurationProperties(JdbcProperties.class)
public class JdbcConfig {
	//@Autowired注入
    //private JdbcProperties prop;
    
    //构造函数注入
    //private JdbcProperties prop;
	//public JdbcConfig(Jdbcproperties prop){
    //this.prop = prop;}
    
    //声明有@Bean的方法参数注入
    @Bean
    public DataSource dataSource(JdbcProperties jdbc) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(jdbc.getUrl());
        dataSource.setDriverClassName(jdbc.getDriverClassName());
        dataSource.setUsername(jdbc.getUsername());
        dataSource.setPassword(jdbc.getPassword());
        return dataSource;
    }
}
  • 通过@EnableConfigurationProperties(JdbcProperties.class)来声明要使用JdbcProperties这个类的对象
  • 然后使用@Autowired注入或构造函数注入或声明有@Bean的方法参数注入
@ConfigurationProperties更优雅的注入

如果一些属性只有一个Bean需要使用,那就无需将其注入到一个类(JdbcProperties)中。而是直接在需要的地方声明即可:

@Configuration
public class JdbcConfig {
    
    @Bean
    // 声明要注入的属性前缀,SpringBoot会自动把相关属性通过set方法注入到DataSource中,前提是该类必须有对应属性的set方法!
    @ConfigurationProperties(prefix = "jdbc")
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        return dataSource;
    }
}

直接把@ConfigurationProperties(prefix = "jdbc")声明在需要使用的@Bean的方法上,然后SpringBoot就会自动调用这个Bean(此处是DataSource)的set方法,然后完成注入。使用的前提是:该类必须有对应属性的set方法!

八、SpringBoot事务管理

SpringBoot 使用事务非常简单,底层依然采用的是Spring本身提供的事务管理

• 在入口类中使用注解 @EnableTransactionManagement 开启事务支持

• 在访问数据库的Service方法上添加注解 @Transactional 即可

例如

@SpringBootApplication
@EnableTransactionManagement //SpringBoot开启事务的支持
public class Application {

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

}
@Override
@Transactional //添加此注解说明该方法添加的事务管理
public int update(Student student) {

    int updateCount = studentMapper.updateByPrimaryKeySelective(student);

    System.out.println("更新结果:" + updateCount);

    //在此构造一个除数为0的异常,测试事务是否起作用
    int a = 10/0;

    return updateCount;
}

九、SpringBoot打包方式

SpringBoot打war包部署

1.程序入口类需扩展继承 SpringBootServletInitializer类并覆盖configure方法(这是使用外置tomcat打包)

@SpringBootApplication
public class Application extends SpringBootServletInitializer{
   public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
   }
   @Override
   protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
//参数为当前Spring Boot启动类Application.class
      return builder.sources(Application.class);
   }
}

2.在 pom.xml中添加(修改)打包方式为war

<packaging>war</packaging>

3.在 pom.xml中配置springboot打包的插件(默认自动加)

<!--SpringBoot 的打包插件-->
<plugin>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

4.在pom.xml中配置将配置文件编译到类路径

<!--mybatis的mapper.xml-->
    <resource>
        <directory>src/main/java</directory>
        <includes>
            <include>**/*.xml</include>
        </includes>
    </resource>
    <!--src/main/resources下的所有配置文件编译到classes下面去-->
    <resource>
        <directory>src/main/resources</directory>
        <includes>
            <include>**/*.*</include>
        </includes>
    </resource>
    <resource>
        <!--源文件位置-->
        <directory>src/main/webapp</directory>
        <!--编译到META-INF/resources,该目录不能随便写-->
        <targetPath>META-INF/resources</targetPath>
        <includes>
            <!--要把哪些文件编译过去,**表示webapp目录及子目录,*.*表示所有-->
            <include>**/*.*</include>
        </includes>
    </resource>

5.在pom.xml的build标签下通过finalName指定打war包的名字

<!--指定打war包的名字-->
<finalName>JavaDemo-springboot-war</finalName>

6.通过Maven package命令打war包到target目录下

在这里插入图片描述
在这里插入图片描述

7、将target目录下生成的war包拷贝到tomcat的webapps目录,并启动tomcat,大功告成!

SpringBoot打Jar包部署

1.在 pom.xml中添加(修改)打包方式为war

<packaging>war</packaging>

2.在 pom.xml中配置springboot打包的插件(默认自动加)

<!--SpringBoot 的打包插件-->
<plugin>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

3、通过maven- package命令打包

4、通过java -jar jar包名称命令运行

十、定时任务@Scheduled注解使用

cron表达式语法

[秒] [分] [小时] [日] [月] [周] [年]

注:[年]不是必须的域,可以省略[年],则一共6个域
在这里插入图片描述

通配符说明:

  • * 表示所有值。 例如:在分的字段上设置 *,表示每一分钟都会触发。
  • ? 表示不指定值。使用的场景为不需要关心当前设置这个字段的值。例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为”?” 具体设置为 0 0 0 10 * ?
  • - 表示区间。例如 在小时上设置 “10-12”,表示 10,11,12点都会触发。
  • , 表示指定多个值,例如在周字段上设置 “MON,WED,FRI” 表示周一,周三和周五触发
  • / 用于递增触发。如在秒上面设置”5/15” 表示从5秒开始,每增15秒触发(5,20,35,50)。 在月字段上设置’1/3’所示每月1号开始,每隔三天触发一次。
  • L 表示最后的意思。在日字段设置上,表示当月的最后一天(依据当前月份,如果是二月还会依据是否是润年[leap]), 在周字段上表示星期六,相当于”7”或”SAT”。如果在”L”前加上数字,则表示该数据的最后一个。例如在周字段上设置”6L”这样的格式,则表示“本月最后一个星期五”
  • W 表示离指定日期的最近那个工作日(周一至周五). 例如在日字段上置”15W”,表示离每月15号最近的那个工作日触发。如果15号正好是周六,则找最近的周五(14号)触发, 如果15号是周未,则找最近的下周一(16号)触发.如果15号正好在工作日(周一至周五),则就在该天触发。如果指定格式为 “1W”,它则表示每月1号往后最近的工作日触发。如果1号正是周六,则将在3号下周一触发。(注,”W”前只能设置具体的数字,不允许区间”-“)。
  • # 序号(表示每月的第几个周几),例如在周字段上设置”6#3”表示在每月的第三个周六.注意如果指定”#5”,正好第五周没有周六,则不会触发该配置(用在母亲节和父亲节再合适不过了) ;小提示:’L’和 ‘W’可以一组合使用。如果在日字段上设置”LW”,则表示在本月的最后一个工作日触发;周字段的设置,若使用英文字母是不区分大小写的,即MON与mon相同。
示例

在启动类开启计划任务

@EnableScheduling//开启计划任务 表达式参考http://cron.qqe2.com/
public class Application {
	
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
	
}

服务类

  
//@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。
//该注解的方法在整个Bean初始化中的执行顺序:
//Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
	@PostConstruct
   @Override
   public void init() {
      initAccessToken();
  
   }


/**
	 * 初始化AccessToken 一小时执行一次
	 */
	@Scheduled(cron = "0 0 0/1 * * ?")
	@Override
	public void initAccessToken() {
		log.error("<====初始化  AccessToken  一分钟一次 !==>");
		try {
			WxParament.ACCESS_TOKEN = GetToken.getAccessToken(ymlParament.getH_app_id(), ymlParament.getH_app_secret());
		} catch (Exception e) {
			log.error("<====initAccessToken初始化失败!==>" + e);
			e.printStackTrace();
		}
		log.info("<====初始化initAccessToken成功,值为==>" + WxParament.ACCESS_TOKEN);
	}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值