HelloWorld Maven配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <mirrors > <mirror > <id > nexus-aliyun</id > <mirrorOf > central</mirrorOf > <name > Nexus aliyun</name > <url > http://maven.aliyun.com/nexus/content/groups/public</url > </mirror > </mirrors > <profiles > <profile > <id > jdk-1.8</id > <activation > <activeByDefault > true</activeByDefault > <jdk > 1.8</jdk > </activation > <properties > <maven.compiler.source > 1.8</maven.compiler.source > <maven.compiler.target > 1.8</maven.compiler.target > <maven.compiler.compilerVersion > 1.8</maven.compiler.compilerVersion > </properties > </profile > </profiles >
HelloWorld项目 需求:浏览发送/hello请求,响应 “Hello,Spring Boot ”
创建maven工程 引入依赖 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.3.4.RELEASE</version > </parent > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > </dependencies >
创建主程序 1 2 3 4 5 6 7 8 9 10 import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class MainApplication { public static void main (String[] args) { SpringApplication.run(MainApplication.class, args); } }
编写业务 1 2 3 4 5 6 7 8 9 10 import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController public class HelloController { @RequestMapping("/hello") public String handle01 () { return "Hello, Spring Boot!" ; } }
运行&测试
运行MainApplication
类
浏览器输入http://localhost:8888/hello
,将会输出Hello, Spring Boot 2!
。
设置配置 maven工程的resource文件夹中创建application.properties文件。
更多配置信息
打包部署 在pom.xml添加
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的Maven插件上点击运行 clean 、package,把helloworld工程项目的打包成jar包,
打包好的jar包被生成在helloworld工程项目的target文件夹内。
用cmd运行java -jar boot-01-helloworld-1.0-SNAPSHOT.jar
,既可以运行helloworld工程项目。
将jar包直接在目标服务器执行即可。
依赖管理特性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 依赖管理<parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.3.4.RELEASE</version > </parent > 上面项目的父项目如下:<parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-dependencies</artifactId > <version > 2.3.4.RELEASE</version > </parent > 它几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
开发导入starter场景启动器
见到很多 spring-boot-starter-* : *就某种场景
只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
更多SpringBoot所有支持的场景
见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
1 2 3 4 5 6 7 所有场景启动器最底层的依赖<dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter</artifactId > <version > 2.3.4.RELEASE</version > <scope > compile</scope > </dependency >
无需关注版本号,自动版本仲裁
引入依赖默认都可以不写版本
引入非版本仲裁的jar,要写版本号。
可以修改默认版本号
查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
在当前项目里面重写配置,如下面的代码。
1 2 3 <properties > <mysql.version > 5.1.43</mysql.version > </properties >
IDEA快捷键:
ctrl + shift + alt + U
:以图的方式显示项目中依赖之间的关系。
alt + ins
:相当于Eclipse的 Ctrl + N,创建新类,新包等。
自动配置特性
1 2 3 4 5 6 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-tomcat</artifactId > <version > 2.3.4.RELEASE</version > <scope > compile</scope > </dependency >
自动配好SpringMVC
引入SpringMVC全套组件
自动配好SpringMVC常用组件(功能)
自动配好Web常见功能,如:字符编码问题
SpringBoot帮我们配置好了所有web开发的常见场景
1 2 3 4 5 6 7 8 9 10 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); } }
默认的包结构
主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
无需以前的包扫描配置
想要改变扫描路径
@SpringBootApplication(scanBasePackages=“com.lun”)
@ComponentScan 指定扫描路径
1 2 3 4 5 @SpringBootApplication 等同于@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan("com.lun")
各种配置拥有默认值
默认配置最终都是映射到某个类上,如:MultipartProperties
配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
按需加载所有自动配置项
非常多的starter
引入了哪些场景这个场景的自动配置才会开启
SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
@Configuration详解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Configuration(proxyBeanMethods = false) public class MyConfig { @Bean public User user01 () { User zhangsan = new User ("zhangsan" , 18 ); zhangsan.setPet(tomcatPet()); return zhangsan; } @Bean("tom") public Pet tomcatPet () { return new Pet ("tomcat" ); } }
@Configuration测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan("com.atguigu.boot") public class MainApplication { 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); } Pet tom01 = run.getBean("tom" , Pet.class); Pet tom02 = run.getBean("tom" , Pet.class); System.out.println("组件:" +(tom01 == tom02)); MyConfig bean = run.getBean(MyConfig.class); System.out.println(bean); User user = bean.user01(); User user1 = bean.user01(); System.out.println(user == user1); User user01 = run.getBean("user01" , User.class); Pet tom = run.getBean("tom" , Pet.class); System.out.println("用户的宠物:" +(user01.getPet() == tom)); } }
最佳实战
配置 类组件之间无依赖关系 用Lite模式加速容器启动过程,减少判断
配置 类组件之间有依赖关系 ,方法会被调用得到之前单实例组件,用Full模式(默认)
IDEA快捷键:
Alt + Ins
:生成getter,setter、构造器等代码。
Ctrl + Alt + B
:查看类的具体实现代码。
@Import导入组件 @Bean、@Component、@Controller、@Service、@Repository,它们是Spring的基本标签,在Spring Boot中并未改变它们原来的功能。
@ComponentScan
@Import({User.class, DBHelper.class})给容器中自动创建出这两个类型的组件 、默认组件的名字就是全类名
1 2 3 @Import({User.class, DBHelper.class}) @Configuration(proxyBeanMethods = false) public class MyConfig {}
测试类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); String[] beanNamesForType = run.getBeanNamesForType(User.class);for (String s : beanNamesForType) { System.out.println(s); }DBHelper bean1 = run.getBean(DBHelper.class); System.out.println(bean1);
@Conditional条件装配 条件装配:满足Conditional指定的条件,则进行组件注入
用@ConditionalOnMissingBean举例说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 @Configuration(proxyBeanMethods = false) @ConditionalOnMissingBean(name = "tom") public class MyConfig { @Bean public User user01 () { User zhangsan = new User ("zhangsan" , 18 ); zhangsan.setPet(tomcatPet()); return zhangsan; } @Bean("tom22") public Pet tomcatPet () { return new Pet ("tomcat" ); } }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); } boolean tom = run.containsBean("tom" ); System.out.println("容器中Tom组件:" +tom); boolean user01 = run.containsBean("user01" ); System.out.println("容器中user01组件:" +user01); boolean tom22 = run.containsBean("tom22" ); System.out.println("容器中tom22组件:" +tom22); }
@ImportResource导入Spring配置文件 比如,公司使用bean.xml文件生成配置bean,然而你为了省事,想继续复用bean.xml,@ImportResource粉墨登场。
bean.xml:
1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" encoding="UTF-8" ?> <beans ... "> <bean id ="haha" class ="com.lun.boot.bean.User" > <property name ="name" value ="zhangsan" > </property > <property name ="age" value ="18" > </property > </bean > <bean id ="hehe" class ="com.lun.boot.bean.Pet" > <property name ="name" value ="tomcat" > </property > </bean > </beans >
使用方法:
1 2 @ImportResource("classpath:beans.xml") public class MyConfig {}
测试类:
1 2 3 4 5 6 7 8 9 public static void main (String[] args) { ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); boolean haha = run.containsBean("haha" ); boolean hehe = run.containsBean("hehe" ); System.out.println("haha:" +haha); System.out.println("hehe:" +hehe); }
@ConfigurationProperties配置绑定 如何使用Java读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用
传统方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class getProperties { public static void main (String[] args) throws FileNotFoundException, IOException { Properties pps = new Properties (); pps.load(new FileInputStream ("a.properties" )); Enumeration enum1 = pps.propertyNames(); while (enum1.hasMoreElements()) { String strKey = (String) enum1.nextElement(); String strValue = pps.getProperty(strKey); System.out.println(strKey + "=" + strValue); } } }
Spring Boot一种配置配置绑定:
@ConfigurationProperties + @Component
假设有配置文件application.properties
1 2 mycar.brand =BYD mycar.price =100000
只有在容器中的组件,才会拥有SpringBoot提供的强大功能
1 2 3 @Component @ConfigurationProperties(prefix = "mycar") public class Car {}
Spring Boot另一种配置配置绑定:
@EnableConfigurationProperties + @ConfigurationProperties
开启Car配置绑定功能
把这个Car这个组件自动注册到容器中
1 2 3 4 @EnableConfigurationProperties(Car.class) public class MyConfig {}@ConfigurationProperties(prefix = "mycar") public class Car {}
自动包规则原理 Spring Boot应用的启动类:
1 2 3 4 5 6 @SpringBootApplication public class MainApplication { public static void main (String[] args) { SpringApplication.run(MainApplication.class, args); } }
分析下@SpringBootApplication
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @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
,@EnableAutoConfiguration
,@ComponentScan
。
@SpringBootConfiguration 1 2 3 4 5 6 7 8 9 10 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration public @interface SpringBootConfiguration { @AliasFor( annotation = Configuration.class ) boolean proxyBeanMethods () default true ; }
@Configuration
代表当前是一个配置类。
@ComponentScan 指定扫描哪些Spring注解。
@ComponentScan
@EnableAutoConfiguration 1 2 3 4 5 6 7 8 9 10 11 12 13 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration" ; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
重点分析@AutoConfigurationPackage
,@Import(AutoConfigurationImportSelector.class)
。
@AutoConfigurationPackage 标签名直译为:自动配置包,指定了默认的包规则。
1 2 3 4 5 6 7 8 9 10 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; }
利用Registrar给容器中导入一系列组件
将指定的一个包下的所有组件导入进MainApplication所在包下。
初始加载自动配置类 @Import(AutoConfigurationImportSelector.class)
利用getAutoConfigurationEntry(annotationMetadata);
给容器中批量导入一些组件
调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)
获取到所有需要导入到容器中的配置类
利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);
得到所有的组件
从
1 META -INF /spring.factories
位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories
位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar
包里面也有META-INF/spring.factories
1 2 3 4 5 6 org.springframework.boot.autoconfigure.EnableAutoConfiguration =\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
虽然我们127个场景的所有自动配置启动的时候默认全部加载,但是xxxxAutoConfiguration
按照条件装配规则(@Conditional
),最终会按需配置。
如AopAutoConfiguration
类:
1 2 3 4 5 6 7 8 9 10 11 12 13 @Configuration( proxyBeanMethods = false ) @ConditionalOnProperty( prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true ) public class AopAutoConfiguration { public AopAutoConfiguration () { } }
自动配置流程 以DispatcherServletAutoConfiguration
的内部类DispatcherServletConfiguration
为例子:
1 2 3 4 5 6 7 8 9 @Bean @ConditionalOnBean(MultipartResolver.class) @ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) public MultipartResolver multipartResolver (MultipartResolver resolver) { return resolver; }
SpringBoot默认会在底层配好所有的组件,但是如果用户自己配置了以用户的优先 。
总结 :
SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。(xxxxProperties里面读取,xxxProperties和配置文件进行了绑定)
生效的配置类就会给容器中装配很多组件
只要容器中有这些组件,相当于这些功能就有了
定制化配置
用户直接自己@Bean替换底层的组件
用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 —-> application.properties
SpringBoot应用如何编写
引入场景依赖
查看自动配置了哪些(选做)
自己分析,引入场景对应的自动配置一般都生效了
配置文件中debug=true开启自动配置报告。
Negative(不生效)
Positive(生效)
是否需要修改
参照文档修改配置项
官方文档
自己分析。xxxxProperties绑定了配置文件的哪些。
自定义加入或者替换组件
自定义器 XXXXXCustomizer;
…
Lombok简化开发 Lombok用标签方式代替构造器、getter/setter、toString()等鸡肋代码。
spring boot已经管理Lombok。引入依赖:
1 2 3 4 <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > </dependency >
IDEA中File->Settings->Plugins,搜索安装Lombok插件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @NoArgsConstructor @Data @ToString @EqualsAndHashCode public class User { private String name; private Integer age; private Pet pet; public User (String name,Integer age) { this .name = name; this .age = age; } }
简化日志开发
1 2 3 4 5 6 7 8 9 @Slf4j @RestController public class HelloController { @RequestMapping("/hello") public String handle01 (@RequestParam("name") String name) { log.info("请求进来了...." ); return "Hello, Spring Boot 2!" +"你好:" +name; } }
Spring Boot includes an additional set of tools that can make the application development experience a little more pleasant. The spring-boot-devtools
module can be included in any project to provide additional development-time features.——link
Applications that use spring-boot-devtools
automatically restart whenever files on the classpath change. This can be a useful feature when working in an IDE, as it gives a very fast feedback loop for code changes. By default, any entry on the classpath that points to a directory is monitored for changes. Note that certain resources, such as static assets and view templates, do not need to restart the application .——link
Triggering a restart
As DevTools monitors classpath resources, the only way to trigger a restart is to update the classpath. The way in which you cause the classpath to be updated depends on the IDE that you are using:
In Eclipse, saving a modified file causes the classpath to be updated and triggers a restart.
In IntelliJ IDEA, building the project (Build -> Build Project
)(shortcut: Ctrl+F9) has the same effect.
添加依赖:
1 2 3 4 5 6 7 <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-devtools</artifactId > <optional > true</optional > </dependency > </dependencies >
在IDEA中,项目或者页面修改以后:Ctrl+F9。
Spring Initailizr Spring Initailizr 是创建Spring Boot工程向导。
在IDEA中,菜单栏New -> Project -> Spring Initailizr。
yaml的用法 同以前的properties用法
YAML 是 “YAML Ain’t Markup Language”(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)。
非常适合用来做以数据为中心的配置文件 。
基本语法
key: value;kv之间有空格
大小写敏感
使用缩进表示层级关系
缩进不允许使用tab,只允许空格
缩进的空格数不重要,只要相同层级的元素左对齐即可
‘#’表示注释
字符串无需加引号,如果要加,单引号’’、双引号””表示字符串内容会被 转义、不转义
数据类型
字面量:单个的、不可再分的值。date、boolean、string、number、null
对象:键值对的集合。map、hash、set、object
1 2 3 4 5 6 7 8 9 10 11 k: {k1:v1 ,k2:v2 ,k3:v3 }k: k1: v1 k2: v2 k3: v3 12345678910
数组:一组按次序排列的值。array、list、queue
1 2 3 4 5 6 7 8 9 10 11 k: [v1 ,v2 ,v3 ]k: - v1 - v2 - v3 12345678910
实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Data public class Person { private String userName; private Boolean boss; private Date birth; private Integer age; private Pet pet; private String[] interests; private List<String> animal; private Map<String, Object> score; private Set<Double> salarys; private Map<String, List<Pet>> allPets; }@Data public class Pet { private String name; private Double weight; }
用yaml表示以上对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 person: userName: zhangsan boss: false birth: 2019 /12/12 20 :12:33 age: 18 pet: name: tomcat weight: 23.4 interests: [篮球 ,游泳 ] animal: - jerry - mario score: english: first: 30 second: 40 third: 50 math: [131 ,140 ,148 ] chinese: {first: 128 ,second: 136 } salarys: [3999 ,4999.98 ,5999.99 ] allPets: sick: - {name: tom } - {name: jerry ,weight: 47 } health: [{name: mario ,weight: 47 }]
自定义类绑定的配置提示 自定义的类和配置文件绑定一般没有提示。若要提示,添加如下依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-configuration-processor</artifactId > <optional > true</optional > </dependency > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > <configuration > <excludes > <exclude > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-configuration-processor</artifactId > </exclude > </excludes > </configuration > </plugin > </plugins > </build >