SpringBoot笔记(1)-SpringBoot基础入门

SpringBoot简介

Spring生态众多,它向我们提供了多方面的功能,包括Web开发、数据访问、安全控制、分布式、消息服务、移动开发、批处理等等。这些功能并不是通过某个框架直接提供的,而是由Spring生态中的不同框架提供。例如利用SpringMVC + Spring Framework我们可以完成基本的Web开发。

不过有之前SSM开发的的经验,我们可以知道在SSM中,需要编写众多的配置文件,被认为是“配置地狱”。而利用SpringBoot,就能帮助我们快速创建出生产级别的Spring的应用。

SpringBoot的主要功能在于能够简化配置,整合一系列的技术栈。它的底层还是Spring Framework,但是利用一系列启动器starter,大大简化构建配置。利用SpringBoot,我们可以创建独立Spring应用,自动配置Spring以及第三方功能,同时提供生产级别的监控、健康检查以及外部配置等,并且在SpringBoot中内置了Web服务器,无需额外安装Web Server。总结来说,SpringBoot是整合Spring技术栈的一站式框架,是简化Spring技术栈开发的快速开发脚手架。

SpringBoot的官方地址如下:Spring Boot

快速开始

项目启动

下面我们就快速开发一个SpringBoot项目。首先创建一个Maven工程,在其中引入如下依赖,包括父项目依赖spring-boot-starter-parent以及web开发的启动器spring-boot-starter-web

1
2
3
4
5
6
7
8
9
10
11
12
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

之后我们创建一个主程序,内容如下:

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

其中使用注解@SpringBootApplication标识主程序类,表示这是一个SpringBoot程序,在其中的main方法中调用run方法,启动项目,这也是整个项目的开启。

之后我们可以编写业务逻辑,在控制层中创建Controller,这里的类位于主程序所在的包下的子包controller中:

1
2
3
4
5
6
7
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "Hello, SpringBoot!";
}
}

这里控制层组件的书写方式与SpringMVC中相同,使用@RequestMapping来指定映射的url路径,而@RestController@Controller@ResponseBody的复合注解,表示该类是控制层的类,并且其中的所有方法的返回值都放在响应体中。

接下来,我们就可以启动主程序MainApplication中的主方法,整个SpringBoot项目就会启动起来,并且我们访问http://localhost:8080/hello,可以发现浏览器中显示了返回值“Hello, SpringBoot!”。这已经说明我们的SpringBoot项目启动了,相比于SSM已经简单了很多。

我们可以在resources文件夹中创建application.properties文件,其中配置相关属性。例如我们可以在其中配置Tomcat的端口号,只需要在该配置文件中指定server.port=8888即可。事实上,针对SpringBoot所有相关属性都能在这个文件中进行配置,详细配置项地址为Common Application properties (spring.io)

可以发现,在之前的Java Web项目中,我们创建Web项目需要修改Maven的打包方式为war,但是通过SpringBoot,我们可以直接打包出一个可运行的jar包,之后在服务器上直接运行这个jar包就可以提供服务。不过需要在Maven配置文件中添加下面的插件,打包后直接运行java -jar即可。

1
2
3
4
5
6
7
8
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

这里可能在IDEA中报红,添加上版本号即可。

在IDEA中的项目启动

在IDEA中,Build Project能够帮助我们构建项目。它可以将项目中的代码编译成字节码文件,在生成的target目录下,会存在classes、generated-sources、generated-test-sources、test-classes等目录。首次点击Bulid Project 会编译整个项目,包括其中的测试类。之后第二次点击则只会编译修改过的文件。这是普通项目的构建方式。当然我们也可以直接使用main方法启动,默认会查看会进行编译。

此外,在Maven项目中,我们还可以使用Maven 编译,即Maven complie。它也能够完成项目的编译,生成字节码文件。但是同时如果配置了pom中的插件,有对应的功能的话也会生效。不过不会生成jar包。Maven complie每次都是重新编译,而不是仅编译修改过的文件。在生成的target目录下,有classes、generated-sources、maven-status目录。在maven-status目录中,有createdFiles.lst和inputFiles,里面是全路径字节码文件和全路径类文件。

而Maven package也会编译项目,同时会生成jar包。生成的target目录下,有classes、generated-sources、generated-test-sources、maven-archiver、maven-status、surefire-reports、test-classes、jar文件等。同时每次编译也是重新编译。我们配置的spring-boot-maven-plugin提供spring-boot:run启动方式,它会调用Maven的编译打包。

总结来说,如果是普通的项目,我们可以直接使用main方法启动,默认会进行编译操作。而在SpringBoot项目中,在pom.xml中配置了相关的插件,则建议使用maven来进行启动。可以直接使用spring-boot:run来运行,也可以每次使用maven complie之后运行main方法。

特性说明

依赖管理特性

在之前SSM项目的开发中,我们需要在Maven中手动引入非常多的依赖,并且自己管理相应的版本问题,不过在SpringBoot中,我们却不需要这样做。这是由于SpringBoot的依赖管理特性。我们引入了父项目:

1
2
3
4
5
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
</parent>

而这个项目也有自己的父项目:

1
2
3
4
5
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.5</version>
</parent>

在这个项目spring-boot-dependencies中,有<properties>标签,其中声明了众多属性,并且有对应的属性值,就是开发中常用的依赖版本号,规定了引入依赖的默认版本。因此我们在引入依赖的时候,如果在其中有默认版本号,就可以不写version。

当然在一些场景下,我们需要特定版本的依赖。此时我们就可以利用Maven的就近原则,在项目的pom.xml中重写属性<properties>,将我们需要的版本在其中重新设置,对默认的版本进行覆盖:

1
2
3
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>

除了父项目之外,我们还引入了场景启动器spring-boot-starter-web,这表示SpringBoot就某种场景下的开发所描述的一组依赖,只要我们引入了对应的starter,在这个场景下的常规依赖都会自动引入。SpringBoot提供给我们的场景启动器有很多(Developing with Spring Boot),均以spring-boot-starter-*的形式命名。我们也可以自定构造场景启动器,或者使用第三方场景启动器,此时的推荐命名形式为*-spring-boot-starter

自动配置特性

在SSM项目的开发中,我们需要完成众多的配置,包括包扫描、Bean管理、Web配置等等。但是在SpringBoot项目中,已经帮助我们完成了一些基本的配置,例如:

  • Tomcat的配置:内嵌Web Server,引入Tomcat依赖,配置Tomcat。

  • SpringMVC的配置:引入SpringMVC的全套组件,自动配置SpringMVC常用功能组件。

  • Web常见功能的配置:自动配置Web的常见功能,例如字符编码问题等。

  • 组件扫描的配置:

    • 按照默认的包结构进行组件扫描,默认情况下,从主程序所在的包开始,该包以及其所有子包中的组件都会被扫描,交由IOC容器管理。
    • 如果想要改变扫描路径,可以使用@SpringBootApplication注解中的scanBasePackages属性指定扫描路径
    • 也可以使用@ComponentScan来指定扫描路径,不过这个注解不能和@SpringBootApplication一起使用,因此@SpringBootApplication是一个复合注解,等同于@SpringBootConfiguration+@EnableAutoConfiguration+@ComponentScan

在上面也提到我们可以通过application.properties配置文件来添加配置。这里的各种配置都拥有默认值,并且配置的值最终会映射到某个类上,成为其中的属性值。这个类也会被Spring管理,我们可以从IOC容器中得到对应的类,然后访问对应的属性。

在主程序类MainApplication中,我们调用了run方法开启项目。实际上这个方法是有返回值的,返回值是一个IOC容器,类型为ConfigurableApplicationContext。取到IOC容器后,我们可以查看其中管理的Bean对象,发现通过自动配置添加了很多。

1
2
3
4
5
6
7
8
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}

SpringBoot会默认在底层配置好所有的组件,但是如果用户自己配置了,就以用户配置的优先。用户可以自己提供@Bean来替换底层的组件,也可以通过配置文件设置值的方式修改对应组件的参数。

在开发SpringBoot项目的时候,我们首先需要引入场景依赖,之后可以查看SpringBoot自动配置了哪些组件。在配置文件中设置debug=true,可以开启自动配置报告。之后随着开发过程,判断是否需要修改SpringBoot自动配置的组件,修改的方式可以通过配置文件、也可以自定义替换组件。

底层注解

SpringBoot在底层帮助我们自动进行了依赖配置,完成自动装配,配置的过程和原理依赖了许多注解。下面介绍一些SpringBoot底层常用的注解。

@Configuration 配置类

在Spring中,我们可以使用配置文件,基于XML来管理Bean对象。在SpringMVC中,我们也可以使用配置类来代替配置文件,在其中管理IOC容器中的Bean对象。

我们可以创建自己的配置类,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Configuration()
public class MyConfig {

@Bean
public Person person1(){
Person person = new Person("me", 18);
person.setPet(petCat()); // Person组件依赖了Pet组件
return person;
}

@Bean("cat")
public Pet petCat(){
return new Pet("cat");
}
}

首先我们使用@Configuration注解标识我们的自定义类,通知SpringBoot这个一个配置类。之后,使用@Bean注解标识其中的方法,该方法所返回对象会被添加到IOC容器中进行管理。默认情况下以方法的名称作为Bean对象的id,方法的返回类型为组件类型。或者可以在@Bean注解中指定value值,表示Bean对象的名称。需要注意的是,配置类本身也是一个组件,交由IOC容器管理。

@Configuration注解中,可以指定proxyBeanMethods。它表示代理Bean的方法,接收一个布尔值。默认情况下该值为true,保证多次调用@Bean修饰的方法,返回的组件都是单例的。如果该值为false,则多次调用方法,返回的组件是新创建的。

该值为true时对应Full模式,在每次方法调用的时候都会检查是否是单例,而该值为false的时候对应Lite模式,不会进行检查,因此可以加速容器的启动过程。一般来说,如果类组件之间没有依赖关系,则可以使用Lite模式来进行加速,如果有依赖关系,则使用Full模式,保证依赖对象是单例的。

在SpringBoot中,我们仍然可以使用@Bean@Component@Controller@Service@Repository等注解。这些是Spring的基本注解,在SpringBoot中也并未改变它们原来的功能。

@Import 组件导入

@Import注解也能够帮助我们完成组件导入。在其中我们需要给定对应类的Class对象,之后就会在容器中自动创建出对应类型的组件,组件的名称默认为全类名。

1
2
3
4
@Import({Person.class, Pet.class})
@Configuration
public class MyConfig {
}

@Conditional 条件装配

条件装配表示满足某个条件后才进行组件注入。条件装配的基础注解为@Conditional,其下有很多其他条件装配注解,代表不同的条件。例如其中@ConditionalOnMissingBean注解,在其中指定name属性为cat,表示当IOC容器中没有名称为cat的Bean,才能执行组件注入。

条件装配的注解可以添加在方法上,则只对方法返回的Bean对象是否注解生效,也可以添加在类上,则对类中所有注入的Bean对象生效。

@ImportResouce 配置文件导入

在Spring中我们可以使用.xml文件来管理Bean对象,在SpringBoot中,我们仍然可以继续复用这些配置文件,只需要利用@ImportResouce注解进行声明,在其中指定对应配置文件的位置即可:

1
2
3
4
@ImportResource("classpath:spring.xml")
public class MyConfig {
...
}

@ConfigurationProperties 配置绑定

在利用配置文件的时候,我们希望能够读取properties文件中的内容,并将其封装的JavaBean中,之后通过调用JavaBean的一些方法来获得其中的属性值。在SpringBoot中提供有配置绑定的功能,用于将配置文件中的值绑定到IOC中的Bean对象上。

假设现在我们的application.properties中有如下两个属性:

1
2
mybook.name=DeathNote
mybook.author=huangmu

我们创建一个类Book,其中有属性name和author,我们希望能够将Book类交由IOC容器管理,并且将上面这些属性绑定到IOC容器中管理的Book对象上。

第一种方式:使用@ConfigurationProperties+@Component

我们需要在类Book上添加这两个属性,将其交由容器管理,并且指定它对应属性的前缀:

1
2
3
4
5
@Component
@ConfigurationProperties(prefix = "mybook")
public class Book {
...
}

第二种方式:使用@EnableConfigurationProperties+@ConfigurationProperties

我们需要在配置类中开启配置绑定功能,并将其注册到容器中。同时仍然需要在Book类上指定对应属性的前缀:

1
2
3
4
@EnableConfigurationProperties(Book.class)
public class MyConfig {
...
}
1
2
3
4
@ConfigurationProperties(prefix = "mybook")
public class Book {
...
}

之后通过调用run方法得到IOC容器,再从IOC容器中获取对应Book类型的Bean对象,输入即可发现被绑定上了对应的属性。


SpringBoot笔记(1)-SpringBoot基础入门
http://example.com/2022/11/02/SpringBoot笔记-1-SpringBoot基础入门/
作者
EverNorif
发布于
2022年11月2日
许可协议