SpringBoot
SpringBoot是一个全新开源的轻量级框架。它基于Spring4.0设计,进一步简化了Spring的配置,更加简单的完成整个搭建和开发。
微服务架构
https://martinfowler.com/articles/microservices.html
第一个SpringBoot程序
可以去官网去创建一个springboot的项目(用idea自带创建也是通过官网创建的),配置什么的自己选择,注意要添加一个Spring Web的依赖,不然不能用作Web开发,然后GENERATE下载项目到本地,用idea导入项目就可以了。
在项目自带的Application类的同级目录下(一定要同级目录,不然SpringBoot无法扫描到你写的类)创建包和类,现创建一个Hello的类。
@Controller
@ResponseBody//将返回的数据写给浏览器,对象就会返回JSON数据
//这两个由@RestController替换,因为这两个注解已经被RestController注解包括了。
public class Hello {
@GetMapping("/hello")
public String hello(){
return "Hello World!";
}
}
然后通过Application类来运行,然后打开你的http://localhost:8080/hello就能看到HelloWorld了。
SpringBoot程序详解
分析一下我们的第一个SpringBoot程序。
Pom.xml
<?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.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yw</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>My first springboot demo</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--Web场景启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!--打包工具-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-
父项目
<!--Springboot的父项目--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <!--点进去发现还有一个父项目--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.3.4.RELEASE</version> </parent> <!-- 点进去看到有很多properties,这些都是依赖的版本,即这个父项目管理了所有用到的依赖的版本,这就是为什么导入依赖时候不用声明版本号的原因。 --> -
导入的Spring Web的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency><!--spring-boot-starter-web里的内容--> <?xml version="1.0" encoding="UTF-8"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <!-- This module was also published with a richer model, Gradle metadata, --> <!-- which should be used instead. Do not delete the following line which --> <!-- is to indicate to Gradle or any Gradle module metadata file consumer --> <!-- that they should prefer consuming it instead. --> <!-- do_not_remove: published-with-gradle-metadata --> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.3.4.RELEASE</version> <name>spring-boot-starter-web</name> <description>Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container</description> <url>https://spring.io/projects/spring-boot</url> <organization> <name>Pivotal Software, Inc.</name> <url>https://spring.io</url> </organization> <licenses> <license> <name>Apache License, Version 2.0</name> <url>https://www.apache.org/licenses/LICENSE-2.0</url> </license> </licenses> <developers> <developer> <name>Pivotal</name> <email>info@pivotal.io</email> <organization>Pivotal Software, Inc.</organization> <organizationUrl>https://www.spring.io</organizationUrl> </developer> </developers> <scm> <connection>scm:git:git://github.com/spring-projects/spring-boot.git</connection> <developerConnection>scm:git:ssh://git@github.com/spring-projects/spring-boot.git</developerConnection> <url>https://github.com/spring-projects/spring-boot</url> </scm> <issueManagement> <system>GitHub</system> <url>https://github.com/spring-projects/spring-boot/issues</url> </issueManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.3.4.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> <version>2.3.4.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <version>2.3.4.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.2.9.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.9.RELEASE</version> <scope>compile</scope> </dependency> </dependencies> </project>
spring-boot-starter,SpringBoot的场景启动器。那什么是场景启动器呢?在SpringBoot框架中,开发者已经帮我们模拟了很多个使用SpringBoot的开发场景,并将这些场景需要的依赖和配置全部写入到这些场景启动器当中。比如我们现在是开发web的场景,我们就导入了这个Spring Web的依赖,主要就是这个spring-boot-starter-web的web场景启动器,里面都是我们开发web需要的依赖以及一些配置。
主程序
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
@SpringBootApplication这个注解标注了这是SpringBoot的主配置类,SpringBoot通过这个主配置类的main方法来启动这个SpringBoot的应用。查看里面的源码就会发现这个注解是由很多注解组成的,下面详细分析一下。
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
@SpringBootConfiguration
这个注解表示这个类是一个SpringBoot的配置类,点开里面发现还有个**@Configuration**注解,这个注解表示这是个Spring的配置类。
@Configuration
public @interface SpringBootConfiguration {
在点开就发现了这个**@Component**,所以发现这个配置类是容器的一个组件。
@Component
public @interface Configuration {
@EnableAutoConfiguration
这个注解告诉了SpringBoot要开启自动配置功能。
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
**@Import(AutoConfigurationImportSelector.class)**这是导入组件的选择器,会给容器导入很多这个场景所需要的所有组件并配置号这些组件。
@AutoConfigurationPackage这个注解表示自动配置包,点进去发现有一个这样的注解
@Import(AutoConfigurationPackages.Registrar.class)
这个注解是Spring的底层注解,@Import指定了AutoConfigurationPackages.Registrar.class这个类给容器导入一些组件。
所以这个@EnableAutoConfiguration就是将主配置类同目录下的包与类的所有组件扫描到Spring容器里面,这就是为什么一定要在同目录下创建包与类,因为不同目录就不会扫描得到。
Resource文件夹
-
static文件夹 保存静态资源的文件夹,比如js,css文件等。
-
templates文件夹 保存模板页面的文件夹,因为SpringBoot默认jar包嵌入式的Tomcat,所以不支持JSP页面,所以需要用到模板引擎来配置页面。
-
application.properties(application.yml) SpringBoot的配置文件(名字是固定的不能修改),因为SpringBoot已经帮我们配置好了很多配置,想要修改这些默认配置就需要在这个配置文件自己修改,这个配置文件由两种形式,properties和yml形式。
- application.properties的格式是 key=value 子配置就用点,比如service下的port配置就表示为service.port=value
- application.yml的格式是 key: value 注意有空格,因为yml文件对空格很敏感, 具体语法可参照YAML语法,之后就用yaml的这种格式来写配置文件
配置文件值的注入
首先先写个需要注入值的类。
@Component
@ConfigurationProperties(prefix = "user")
public class User {
private String name;
private int age;
private Date birth;
private Boolean happy;
private Map<String,Object> family;
private List<Object> hobby;
private Dog dog;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Boolean getHappy() {
return happy;
}
public void setHappy(Boolean happy) {
this.happy = happy;
}
public Map<String, Object> getFamily() {
return family;
}
public void setFamily(Map<String, Object> family) {
this.family = family;
}
public List<Object> getHobby() {
return hobby;
}
public void setHobby(List<Object> hobby) {
this.hobby = hobby;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", birth=" + birth +
", happy=" + happy +
", hobby=" + hobby +
", family=" + family +
", dog=" + dog +
'}';
}
}
@Component
public class Dog {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- @Component表示这是spring的组件,会被注入到spring的容器中进行管理 2. @ConfigurationProperties(prefix = “user”)表示绑定配置文件中的user的配置,这样就可以进行值的注入了
然后导入一个配置文件处理器的依赖(不导入会爆红虽然没影响),可以去配置文件注入值了。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
这样就可以成功的将值注入了,可以去测试类进行一下测试。
@SpringBootTest
class DemoApplicationTests {
@Autowired
User user; //其实不一定要与配置类中的名称一致,user01也能读取出值
@Test
void contextLoads() {
System.out.println(user);
}
}
得到答案
User{name='Yw', age=20, birth=Wed Oct 21 00:00:00 CST 2020, happy=true, hobby=[play, game], family={father=yww1, mother=yww2}, dog=Dog{name='wwangwang', age=3}}
导入文件资源
@PropertySource
在上述的示例当中,要是总是把注入的值都加进全局的配置文件中就会显得很乱,所以可以新建一个文件在通过@PropertySource标签导入进去也可以实现值的注入,这样application.properties中就可以不用写user的值了,值都写在user.properties即可。
@Component
@ConfigurationProperties(prefix = "user")
@PropertySource(value = {"classpath:user.properties"})
public class User {
注意@PropertySource这个标签导入的是properties的文件,yml文件会出问题。
@ImportResource
这个标签是用来导入spring的配置文件到springBoot中的(即xml格式)
@ImportResource(locations = {"classpath:beans.xml"})
@Bean
这个标签的功能与@ImportResource类似,也是为了导入配置,给容器添加一个组件的。比如写一个配置类。
@Configuration //表示这个类是一个配置类,就像是一个spring的配置文件
public class Config {
@Bean //将方法的返回值注入到容器之中,类似spring配置中
public Hello hello(){
return new Hello();
}
}
- @Configuration 表示这个类是一个配置类,就像是一个spring的配置文件
2. @Bean 将方法的返回值注入到容器之中,类似spring配置中
注入bean的操作,方法名就是这个bean的id。
Profile
properties的多文档
首先就是主要的配置文件application.properties,创建多文档的方式就是按照application-[name].properties的形式命名创建在resources目录下。就比如我创建了一个测试环境的配置,命名为application-dev.properties
yaml的多文档
这个就很方便了,直接在application.yml中就可以创建多个文档配置了。只要通过---就能将配置文件分成不同的文档配置,通过spring.profiles: [name]这个配置就能为这个文档配置取个名字了。
server:
port: 8085
---
server:
port: 8086
spring:
profiles: dev
---
激活指定的Profile
properties
在主配置文件,即application.properties下增加这个配置,就可以激活相应名字的文档配置文件。
spring.profiles.active=dev
yaml
yaml形式也是通过这个配置spring.profiles.active=dev,就能激活相应名字的文档配置文件。
server:
port: 8085
spring:
profiles:
active: dev
---
server:
port: 8086
spring:
profiles: dev
共同的激活方式
-
命令行 比如在打了jar包之后,在命令行运行jar包的时候增加配置就能激活指定配置文件生效。
java -jar ---.jar --spring.profiles.active=dev -
虚拟机参数 修改虚拟机参数也可以修改。
-Dspring.profiles.active=dev
配置文件的优先级
配置文件的优先级由高到低分别为:
- 项目路径下的config文件夹中的配置文件
- 项目路径下的配置文件
- 资源路径下的config文件夹中的配置文件
- 资源路径下的配置文件
springboot会通过优先级来加载配置文件,要是有不止一个配置文件,springboot也是会全部加载这些配置文件。对于设置了相同的配置,优先级高的配置文件设置的就会覆盖掉优先级低的配置文件的设置。就比如每个配置文件都设置了不同的打开端口,就会以优先级高的配置文件的为准。其他不冲突的配置也是生效的。