SpringBoot(一)-基本使用
SpringBoot入门
简介
- JavaEE开发存在的问题(即使使用了SSM ):配置繁多、部署复杂、集成第三方库并不简单,SpringBoot可以很好地解决上述问题
- 官网:https://spring.io/projects/spring-boot
- SpringBoot的特点
- 内置了很多常用配置,让JavaEE开发更加简单
- 项目可以独立运行,无须额外依赖web容器(Tomcat)(内置了web容器)
- 之前使用JavaEE或者SSM都需要本地配置Tomcat才能部署运行项目,现在直接使用SpringBoot自带的Tomcat,这样直接运行别人的任何项目也不用配置Tomcat,可以直接运行项目
创建一个SpringBoot项目
- 创建项目
- File->new->Module->Maven->next->设置路径、设置项目名称即可-OK
-
pom.xml文件添加设置
<!-- 继承父项目,父项目的pom.xml里面有各种库的版本号,这个仅仅是版本号设置dependencyManagement,还需要设置依赖 --> <parent> <artifactId>spring-boot-starter-parent</artifactId> <groupId>org.springframework.boot</groupId> <version>2.3.4.RELEASE</version> </parent> <!-- 依赖--> <dependencies> <!-- web项目(已经集成了SpringMVC中很多的常用库) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
-
添加程序的入口:新建一个Application,作为程序的入口
//com.zh.Application //SpringBoot的入口 @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
-
添加Controller
//com.zh.controller.TestController @RestController public class TestController { @GetMapping("/test") public String test() { return "Hello SpringBoot"; } }
- 启动程序
- 在Application类中直接右击运行main方法即可
- 会自动启动SpringBoot自带的Tomcat
- 在浏览器中输入:
http://localhost:8080/test/
,即可访问
SpringBoot的基础注解
@SpringBootApplication
中包含了3个注解@EnableAutoConfiguration
- 可以根据maven依赖自动构建相关环境(比如pom.xml中依赖为spring-boot-starter-web构建web容器环境等)
@ComponentScan
- 默认会扫描当前类所在的包以及子包中的所有类
- 因此Application这个类一定要放在其他所有类的外层,com.zh下
@SpringBootConfiguration
- 从SpringBoot 2.2.1开始,被SpringBoot扫描到的
@Component
都不用再加@Configuration
- 之前配置类必须要添加
@Configuration
注释,然后方法才能使用@Bean
- 现在可以不使用
@Configuration
注释,直接使用@Component
也能使用@Bean
- 之前配置类必须要添加
- 举例:
-
Person类(不用注解修饰,此时不会被扫描到容器中)
//没有用任何注解,因此不会被扫描到容器中 package com.zh.domain; public class Person {}
-
配置文件SpringConfig,可以配置那些类需要扫描到容器中
//不使用@Configuration,也能使用@Bean @Component public class SpringConfig { //配置将Person类扫描到容器中 @Bean public Person person() { return new Person(); } }
-
Controller
@RestController public class TestController { //bean对象的注入 @Autowired private Person person; @GetMapping("/test") public String test() { return "Hello SpringBoot!!!666!!!" + person; } }
-
可运行jar
- 上面讲过,SpringBoot直接包含了Tomcat,入口程序也有main函数,那么是否可以直接打包成可执行程序呢?
-
如果希望通过mvn package打包出一个可运行的jar,需要pom.xml增加一个插件
<!-- 插件 --> <build> <!-- 设置打包后的jar名称 --> <finalName>sb_hw</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
- 点击右边工具栏maven->项目->lifecycle->package,双击即可打包
- 在target目录下找到sb_hw.jar文件
- 打开终端,cd到该jar目录下,执行
java -jar sb_hw.jar
命令,即可启动服务 - 在浏览器输入
http://localhost:8080/test/
,即可访问 ctrl+c
停止项目- 这个sb_hw.jar文件就可以直接提供给其他人,只要对方安装了JDK环境即可
- 还有一种运行jar包方式:点击右侧工具栏maven->项目->plugins->spring boot ->spring boot:run
热部署
- 之前每次修改一个类的代码,都需要重新部署启动项目,耗时较长,那么可不可以修改后不用重新部署呢?这种方式就叫做热部署
- 增加依赖(Debug模式下,它可以监控classpath的变化)
- 项目编译后所有的字节码文件都在classpath下,如果有任何一个类被修改了,然后重新编译生成新的包,那么classpath就会变化
-
下面依赖仅仅用于监听classpath的变化
<!-- 热部署 ,可以看到只要是org.springframework.boot的库都不需要再加版本号,因为当前项目已经继承父类--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency>
- 重新编译项目(2种方式)
- 方法一:手动编译(Build Project、Build Module)
- 方式一:点击顶部工具栏的Build->Build Project(编译整个项目)
- 方式二:点击顶部工具栏的Build->Build Module。。。(编译当前Module)
- 使用:手动重新编译完,再次刷新页面就可以显示更新后的项目
- 方法二:自动编译
- perferences->Build,Execution,Deployment->Compiler->勾选Build project automatically
- 按下:
Ctrl + Shift + alt + /
或者双击shift->搜索registry
->点击打开->找到compiler.automake.allow.when.app.running,然后勾选,点击close - 使用:可以任意修改项目中的代码,然后鼠标点击其他应用程序(IDEA失去焦点),等一会之后,项目会自动重新编译,刷新页面这显示更新后的项目
- 注意: 这种方法使用起来不好用,等待时间长,所以通常使用手动编译
- 方法一:手动编译(Build Project、Build Module)
- 需要注意的是:使用了spring-boot-devtools后可能会执行2次main方法
- 不用在意,因为devtools也仅限于开发调试阶段使用
应用程序的配置文件
应用程序配置文件(Application Property Files)
- SpringBoot默认会去加载一个应用程序配置文件,文件名为application
-
application配置文件默认可以存放的位置如下所示(按照优先级从高到低排序)
file:./config/ 项目根路径下的config文件夹下 file:./config/*/ 项目根路径下的config文件夹下的任意子文件夹 file:./ 项目根路径下 classpath:/config/ resources文件夹下的config文件夹下 classpath:/ resources文件夹下
file:./
代表项目的根目录classpath:
打包后项目target下classes文件下的根路径target/classes/
- 举例
- 注意: 图片中的1、2、3是无效的,因为他不是项目的根路径,21_SpringBoot_Config仅仅是一个项目下的Module,必须是new->project…创建的项目才是真正的项目根路径
- 最常用的就是直接放在resources下面就行
-
application.properties常用配置如下
//设置端口 server.port=8888 //设置访问根路径 server.servlet.context-path=/cfg
运行参数、VM选项 指定配置文件
- 可以通过运行参数或VM选项,指定项目配置文件的文件名、位置
1.运行参数
-
命令行后直接添加运行参数
//设置配置文件的名称 java -jar myproject.jar --spring.config.name=zhapplication //设置配置文件的位置 java -jar myproject.jar --spring.config.location=F:/zh.properties
- 这种方式只能配置通过java -jar运行项目的方式
- 通过IDEA配置项目运行参数
- IDEA->run->Edit Configurations…->Sprint Boot ->点击需要配置的应用启动类->Propram arguments
- 输入:
--spring.config.location=F:/zh.properties
- 效果等价于第一种
- 通过运行参数设置的数据可以在main函数中获取到,运行参数会传递给main方法的args参数
- 多个运行参数用空格隔离:
--x1 --x2
2.VM选项
- 通过VM(虚拟机)选项配置
- IDEA->run->Edit Configurations…->Sprint Boot ->点击需要配置的应用启动类->VM options
- 输入内容:
-Dspring.config.location=F:/zh.properties
- 通过VM选项设置的数据可以在main函数中获取到
- 可以在main函数中通过System.getProperty、System.getProperties方法获取VM选项设置的参数
- 可以在main函数中通过System.getProperty、System.getProperties方法获取VM选项设置的参数
配置文件的内容
- application.properties文件中都可以配置哪些内容呢?
- 关于服务器的配置内容参考
- 查找spring-boot-autoconfigure.jar/META-INF/spring.factories,然后
- 在项目的External Libraries下找到Maven:org.springframework.boot:spring-boot-autoconfigure.jar
-
找到这个ServletWebServerFactoryAutoConfiguration类中
@EnableConfigurationProperties(ServerProperties.class) ->进入ServerProperties类 能看到ServerProperties类中所有的值都能配置
-
举例
//可以用来修改访问端口 server.port= 8888 //修改项目根目录 server.servlet.context-path=/hello
- 此时项目访问的路径为:
http://localhost:8888/hello/test/
- 查找spring-boot-autoconfigure.jar/META-INF/spring.factories,然后
- 更多配置文件相关的参考资料: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-application-property-files
YAML配置文件
- YAML(YAML Ain’t a Markup Language,YAML不是一种标记语言),SpringBoot更推荐使用YAML作为配置文件,文件扩展名是.yml
- 比较
-
application.properties如下
server.port=8888 server.servlet.context-path=/cfg
-
如果使用 application.yml则如下
server: port: 8888 servlet: context-path: /cfg
-
- YAML格式注意:
- YAML使用空格或TAB作为层级缩进
- 冒号:与后面紧跟的内容之间必须要有空格或TAB
- 字符串可以不用加引号。如果有转义字符,可以使用双引号括住字符串
- 举例:
- 由于接下来项目都是SpringBoot项目,因此可以创建一个父项目,其他子项目依赖于父项目
- file->new->module-> maven->设置路径、项目名称为22_spparent->finish
-
pom.xml中添加springboot依赖
<parent> <artifactId>spring-boot-starter-parent</artifactId> <groupId>org.springframework.boot</groupId> <version>2.3.4.RELEASE</version> </parent> <!-- 依赖--> <dependencies> <!-- web项目(已经集成了SpringMVC中很多的常用库) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 热部署 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies>
- 删除src文件夹,只保留pom.xml
- 右击22_spparent新建一个新的子项目Module->01_yml
- 新建application入口类:
-
新建控制器
@RestController public class TestController { @GetMapping("/test") public String test() { return "test!!!"; } }
-
在resources文件夹下新建application.yml
server: port: 8888 servlet: context-path: /yml //\n代表换行 name: "123\n456"
- 运行application类即可
配置文件内容自动注入
-
以上讲的配置文件的内容都是springboot框架自带的,那么application.properties配置文件中也可以自定义一些字段,如下:
server.port=8888 server.servlet.context-path=/cfg sex=man age=20 //表达一个数组 names=zh, jj, tt, ll //map数据 homes={'gz': 'zhujiang', 'sh': 'lujiazui'}
-
自定义字段配置完了,那么项目中改如何使用呢?主要分为3种使用方式
@Value
注解获取@ConfigurationProperties
注解获取- Enviroment对象获取
@value注解进行注入
-
将上面属性注入给TestController
@RestController //其他配置文件(非application名称)需要用这个先加载,application.properties则不需要使用@PropertySource先加载,因为springboot已经加载了 //@PropertySource("classpath:main.proprties") public class TestController { //注入application.properties配置文件中的数据 @Value("${age}") private Integer age; @Value("${names}") private String[] names; //注入map数据的格式 @Value("#{${homes}}") private Map<String, String> homes; @GetMapping("/test") public String test() { System.out.println(age); System.out.println(names[0]); homes.forEach((k, v) -> System.out.println(k + "_" + v)); return "test_"; } }
- 运行21_SpringBoot_Config项目的application,浏览器输入
http://localhost:8888/cfg/test/
-
则打印:
20 zh gz_zhujiang sh_lujiazui
Enviroment对象获取
-
21_SpringBoot_Config项目新增一个domain
package com.zh.domain; @Component public class Person { // 通过springboot内置的Environment对象直接获取 @Autowired Environment environment; private String sex; @PostConstruct//初始化调用 public void init(){ sex=environment.getProperty("sex"); System.out.println("xxx" + sex); } }
-
启动项目,打印:
xxxman
,environment成功获取到配置文件内容
@ConfigurationProperties注解进行注入
- @value注入特点:
-
bean对象person如下:
//com.zh.domain.Person @Component public class Person { @Value("${id}") private Integer id; @Value("${age}") private Integer age; //set、get方法 }
-
application.yml如下
id: 111 age: 222
-
这种方式能自动注入,但是如果有n个对象,每个对象有n个属性呢?而且有同样的属性名呢? 这样就乱了
-
- 可以使用
@ConfigurationProperties
解决-
bean对象person添加
@ConfigurationProperties
注释://com.zh.domain.Person @Component @ConfigurationProperties("person") public class Person { private Integer id; private Integer age; //set、get方法 }
-
application.yml如下
person: id: 111 age: 222
- 则这样可以解决上面的问题,也不用再写
@Value
注入了 - 上面仍然存在问题:
- 如果bean对象的属性是复杂数据类型呢?数组、bean对象等其他数据类型
- 上面的bean属性都要写set、get方法,如果有n个属性则非常麻烦
-
lombok、spring-boot-configuration-processor的使用
lombok:
- 作用可以通过注解给domain类自动生成get、set、构造方法
-
常见注解有:
@Getter:自动生成get方法 @Setter:自动生成set方法 @Data: 自动生成get、set方法 @AllArgsConstructor:自动生成所有参数的构造 @NoArgsConstructor :自动生成无参构造
- 上面虽然自动生成了get、set方法,但是在写代码时候并没有get、set方法的自动提示,则需要安装IDEA插件
- perferences->plugins->搜索lombok,点击安装即可
- 此时在输入person.get时会有提示
- 为了在开发期间能够有Lombok所生成代码的提示,最好安装Lombok插件,Lombok官网:https://projectlombok.org
- 注意:Lombok仅仅在编译期间使用即可,所以scope设置为provided即可
spring-boot-configuration-processor:
- 作用:配置文件属性名提示,在配置文件中写Model的类时有自动提示功能
- 需要代码重新编译后,才会生成提示
-
在父项目22_spparent的pom.xml中,添加2个依赖
<!-- 在编译期间帮助生成Getter、Setter等代码 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <!-- 配置文件属性名提示:在配置文件中写Model的类时有自动提示功能 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> </dependency>
- 举例使用
-
Student类
//放入容器 @Component //告知这个类在配置文件中对应的字段是什么,而且不需要在写@Value注释 @ConfigurationProperties("student") //自动生成set、get方法 @Data //@Getter //@Setter public class Student { private String name; private List<String> hobbies; private Set<Integer> numbers; private String[] jobs; private Map<String, String> homes; private Dog dog; private List<Book> books; @Data public static class Dog { private Integer age; private String name; } @Data public static class Book { private Double price; private String name; } }
-
application.yml
student: name: ZH #也可以写成: 足球, 篮球 hobbies: [足球, 篮球] numbers: [25, 9, 10] jobs: - 厨师 - 程序员 # 也可以写成: {gz: 珠江新城, sh: 陆家嘴} homes: - gz: 珠江新城 - sh: 陆家嘴 dog: age: 5 name: larry books: - price: 10.5 # 可以直接引用配置文件中的数据 name: ${student.name}_书1 - price: 20.5 name: ${student.name}_书2
-
TestController
@RestController public class TestController { @Autowired private Student student; @GetMapping("/test") public String test() { System.out.println(student); return "test!!!"; } }
-
@EnableConfigurationProperties注解的使用
- 上面例子中Student类必须添加
@Component
,即放入到容器中才能使用,也可以有其他方式:- 删除Student类中的
@Component
,TestController添加注释@EnableConfigurationProperties(Student.class)
@RestController //取代Student类添加@Component注释 //作用是:将配置文件的内容绑定(注入)到Student这个类中 @EnableConfigurationProperties(Student.class) public class TestController { @Autowired private Student student; @GetMapping("/test") public String test() { System.out.println(student); return "test!!!"; } }
- 删除Student类中的
- 学习到这里,再倒回去看ServletWebServerFactoryAutoConfiguration类可以理解得更加深刻
构造方法绑定(Constructor binding)
- 一个domain类有带参的构造方法,如何才能绑定创建该对象的时候自动调用该构造方法呢?
-
Cat类
//不能使用@Component @ConfigurationProperties("cat") //绑定构造方法 @ConstructorBinding @Data public class Cat { private Integer id; private String name; //构造方法 public Cat(Integer id, String name) { this.id = id; this.name = name; System.out.println("Cat--------------"); } }
-
TestController
@RestController //@EnableConfigurationProperties({Student.class, Cat.class}) @EnableConfigurationProperties(Cat.class) public class TestController { @Autowired private Cat cat; @GetMapping("/test") public String test() { System.out.println(cat); return "test!!!"; } }
- 重新部署项目,可以看到日志调用了Cat的构造方法
- 注意: 构造方法绑定只能用
@EnableConfigurationProperties(Cat.class)
,不能使用@Component
@ConfigurationProperties与@Bean
@Bean
的作用是将一个方法对象放入到容器中@ConfigurationProperties
是将配置文件的数据注入到一个对象的成员- 可以联合使用
-
Person类
//@Component、@ConfigurationProperties都不需要添加 @Data public class Person { private Integer id; private Integer age; }
-
TestController
@RestController public class TestController { @Autowired private Person person; //将对象放入到容器 @Bean //将配置文件数据注入到对象成员 @ConfigurationProperties("person") public Person person() { return new Person(); } @GetMapping("/test") public String test() { System.out.println(cat); return "test!!!"; } }
-
宽松绑定(Relaxed Binding)
- 配置文件中的属性名格式比较宽松
- acme.my-project.person.first-name
- Kebab格式 (烤肉串格式),推荐
- 就是每个属性用中划线隔开
- 驼峰标识: acme.myProject.person.firstName
- 下划线隔开:acme.my_project.person.first_name
- 全部大写用下划线隔开:ACME_MYPROJECT_PERSON_FIRSTNAME
- 使用系统环境变量时建议使用
- acme.my-project.person.first-name
- 上面说的就是在配置文件中如何写一个类的属性名称,按照上面的格式才会被识别并自动注入
拆分配置文件
方式一:可以通过---
将配置文件拆分成多个文档
- 特点:所有内容在一个配置文件中
- 举例:
- 新建02_yml子模块
- 启动入口Application略
-
resources中application.yml配置文件内容如下:
#通过spring.profiles.active指定需要加载哪个文档 spring: profiles: active: development #设置端口号 server: port: 8888 #开发文档 --- #设置文档的名称 spring: profiles: development jdbc: url: jdbc:mysql://localhost:3306/test username: root1 password: root1 #生产文档 --- #设置文档的名称 spring: profiles: production jdbc: url: jdbc:mysql://200.0.0.10:3306/shop username: root2 password: root2
-
新建domain类JdbcProperties
//com.zh.domain.JdbcProperties @ConfigurationProperties("jdbc") @Component @Data public class JdbcProperties { private String url; private String username; private String password; }
-
TestController
@RestController public class TestController { @Autowired private JdbcProperties jdbcProperties; @GetMapping("/test") public String test() { return jdbcProperties.toString(); } }
方式二:文件名application-*的后半部分默认就是文档名
- 将配置文件拆分成n个配置文件,每个配置文件的名称叫做application-xxxx,那么每个配置文件的文档名称就是xxxx
-
比如将上面的配置文件拆分成4个yml
//application-port.yml server: port: 8888 //application-dev.yml jdbc: url: jdbc:mysql://localhost:3306/test username: root1 password: root1 //application-prd.yml jdbc: url: jdbc:mysql://200.0.0.10:3306/shop username: root2 password: root2 //application-path.yml server: servlet: context-path: /yml
-
则入口配置文件application.yml如下:
#通过spring.profiles.active指定需要加载哪些文档 spring: profiles: active: - dev - port - path # active: dev, port, path # active: [dev, port, path]
- 浏览器输入:
http://localhost:8888/yml/test/
- 浏览器输入:
- 入口配置文件application.yml也可以什么都不写,直接在VM选项或者运行参数中配置
- 运行参数配置:
--spring.profiles.active=dev,port,path
- VM选项设置:
-Dspring.profiles.active=dev,port,path
- 而且这两种配置的优先级高于配置文件中直接设置
- 比如在VM选项配置
-Dserver.port=8800
,则会覆盖掉上面配置文件中设置的8888- 点击Eidt Configurations ->Spring Boot->Application(当前项目的启动入口类)->VM options 输入:
-Dserver.port=8800
,点击应用即可 - 则此时浏览器输入:
http://localhost:8800/yml/test/
进行访问
- 点击Eidt Configurations ->Spring Boot->Application(当前项目的启动入口类)->VM options 输入:
- 运行参数配置:
- 在VM选项或者运行参数中设置变量,在控制器中接收
- 在运行参数中输入如下:
--spring.profiles.active=dev,port,path --name=zh666
-
则TestController如下
@RestController public class TestController { @Value("${name}") private String name; @Autowired private JdbcProperties jdbcProperties; @GetMapping("/test") public String test() { return jdbcProperties.toString() + "_" + name; } }
- 浏览器输入:
http://localhost:8888/yml/test/
- 打印如下:
JdbcProperties(url=jdbc:mysql://localhost:3306/test, username=root1, password=root1)_zh666
- 在运行参数中输入如下:
- VM选项与运行参数原理
- 在VM选项或者运行参数中设置的参数,本质就是直接写入、覆盖掉application.yml中的数据
- 因此可以起到设置配置文件内容的作用
设置Banner
- 官网文档参考:https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-banner
- Banner生成:http://patorjk.com/software/taag
- 输入内容,可以自动生成漂亮的banner
- 然后复制到banner.txt文件中
- 在SpringBoot项目运行时,会有一个个性的图标SpringBoot样式,这个就是通过Banner做的
- 在项目的resources下添加一个banner.txt
- 在里面输入要展示的内容