优点:创建独立的Spring应用
内嵌web服务器
自动starter依赖,简化构建配置
自动配置Spring以及第三方功能
提供生产级别的监控,健康检查和外部化配置
无代码生成,无需编写XML
缺点:版本迭代太快,内部原理复杂,不容易精通
微服务:微服务是一种架构风格
一个应用拆分为一组小型任务
每个服务运行在自己的进程内,也就是可以独立部署和升级
服务之间使用轻量级HTTP交互
服务围绕业务功能拆分
可以由全自动部署机制独立部署
去中心化,服务自治,服务可以使用不同的语言,不同的存储技术
分步式:远程调用,服务发现,负载均衡,服务容错,服务监控,链路追踪,日志管理,任务调度
(可以用SpringBoot+Spring Cloud解决)
云原生:服务自愈,弹性伸缩,服务隔离,自动化部署,灰度发布,流量治理
(使用Docker,星际级容器编排KUbernetes)
父项目做依赖管理和版本仲裁:
org.springframework.boot spring-boot-starter-parent2.3.4.RELEASE org.springframework.boot spring-boot-dependencies2.3.4.RELEASE
可以看到版本号都在这里规定好了,几乎声明了所有的常用的依赖的版本号,这就是自动版本仲裁机制。如果引入了非版本仲裁的jar包,还是要自己设置版本号的。
如果想要自己声明版本号:
1.查看spring-boot-dependencies中里面规定版本用的key,比如mysql的就是mysql.version
2.然后在当前项目里重写配置。例子如下:
5.1.43 mysql mysql-connector-java
场景启动器:
1.我们之后会见到很多的spring-boot-starter-* : *表示某种场景
2.只要引入starter,这个场景的所有常规需要的依赖我们都能自动导入
3.springboot支持所有的场景
4.见到的*-spring-boot-starter : 这些是第三方给我们提供的简化开发的场景启动器
5.所有的场景启动器最底层的依赖都是:
spring-boot-starter
自动配置好tomcat:
引入Tomcat依赖,配置Tocat
自动配置好SpringMvc:
引入SpringMVC全套组件,自动配置好了SpringMVC的常用组件(功能)
自动配置好web常见功能,如字符编码问题:
SpringBoot帮我们配置好了所有web开发的常见场景
默认包结构:
主程序所在包及其子包下面的左右组件都会被默认扫描进来
无需以前的包扫描
如果想改变扫描路径:@SpringBootApplication(scanBasePackages = "com.atguigu")
各种配置都有默认值:
默认配置最终都是映射到某个类上,如MultipartProperties
配置文件的值最终会绑定在每个类上,这个类会在容器中创建对象
按需加载所有自动配置项:
有非常多的starter
引入了哪些场景这些场景的自动配置才会开启
SpringBoot所有的自动配置功能都在spring-boot-autoconfigure包里面
配置下maven的本地仓库:
来康康pom文件:
4.0.0 org.example shangguigu_SpringBoot21.0-SNAPSHOT 14 14 org.springframework.boot spring-boot-starter-parent2.3.4.RELEASE org.springframework.boot spring-boot-starter-weborg.springframework.boot spring-boot-maven-plugin
先得有个springboot的启动类:
package com.atguigu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class mainApplicatin {
public static void main(String[] args) {
SpringApplication.run(mainApplicatin.class,args);
}
}
然后再写个Controller层的代码:
package com.atguigu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@ResponseBody
@Controller//或者也可以直接把上面的两个注解合并成@RestController
public class HelloController {
@RequestMapping("/hello")
public String show(){
return "hello SpringBoot";
}
}
可以在配置文件application.properties中改下配置,比如端口号
看下结构目录:
测试:ok测试成功
简化部署,不需要在目标服务器安装tomcat服务器:
三.容器功能 1.组件添加 @Bean...
1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的,如例1
2、配置类本身也是组件,如例2
3、proxyBeanMethods:代理bean的方法
Full(proxyBeanMethods = true)【每个@Bean方法被调用多少次返回的组件都是单实例的】
Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个
组件是否在容器中有。如例3
4、组件依赖必须使用Full模式默认(true)。其他默认是否Lite模式(false)。如例4
5、用@Service @Controller @Repository @Component 进行组件添加
6、@Import导入组件,默认组件名字是全类名,这个注解要放到别的组件上。如例5
7、@Conditional条件装配。只有满足条件的时候才会被注入进来。如例6
//用户的实体类
package com.atguigu.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
String username;
int age;
Pet pet;
public User(String username, int age) {
this.username = username;
this.age = age;
}
}
//宠物实体类
package com.atguigu.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Pet {
String name;
int age;
}
//配置类
package com.atguigu.config;
import com.atguigu.bean.Pet;
import com.atguigu.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = true)
public class MyConfig {
@Bean//给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
public User user(){
User xiao = new User("萧萧", 200);
//User组件依赖了Pet组件
xiao.setPet(pet());
return xiao;
}
@Bean
public Pet pet(){
return new Pet("萧萧的狗",200);
}
}
//测试类
package com.atguigu;
import ch.qos.logback.core.db.DBHelper;
import com.atguigu.bean.Pet;
import com.atguigu.bean.User;
import com.atguigu.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
@Import({DBHelper.class})
@SpringBootApplication(scanBasePackages = "com.atguigu")
public class mainApplicatin {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(mainApplicatin.class, args);
//例1.检测组件的单实例,这个是从容器里面拿,所以即使proxyBeanMethods=false,这里拿到的也是相同的
User user1 = (User)run.getBean("user");
User user2 = (User)run.getBean("user");
System.out.println(user1==user2);
//例2.证明配置类也是组件
MyConfig myConfig = run.getBean(MyConfig.class);
System.out.println(myConfig);
//例3.验证proxyBeanMethods的属性值true和false的区别,false是轻量级
User user3 = myConfig.user();
User user4 = myConfig.user();
System.out.println(user3==user4);//如果是true,则这里是一样的;如果是false,这里就不一样
//例4.组件依赖
User user5 = run.getBean("user", User.class);
Pet pet2 = run.getBean("pet", Pet.class);
System.out.println(user5.getPet()==pet2);//如果是true,则这里是一样的,说明用户的宠物就是容器中的宠物;如果是false,这里就不一样
//例5.@Import导入组件验证
DBHelper dbHelper = run.getBean(DBHelper.class);
System.out.println(dbHelper);
}
}
//宠物和人的实体类用上面的
//配置类
package com.atguigu.config;
import com.atguigu.bean.Pet;
import com.atguigu.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig {
@Bean("pet1")
public Pet pet(){//注意这个要放在user()方法的前面,先在容器里注册
return new Pet("萧萧的狗",200);
}
@ConditionalOnBean(name = "pet1")
@Bean("user1")
public User user(){
User xiao = new User("萧萧", 200);
return xiao;
}
}
//测试类
package com.atguigu;
import ch.qos.logback.core.db.DBHelper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
@Import({DBHelper.class})
@SpringBootApplication(scanBasePackages = "com.atguigu")
public class mainApplicatin {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(mainApplicatin.class, args);
//例6,测试@ConditionalOnBean注解
boolean user6 = run.containsBean("user1");
System.out.println(user6);
boolean pet3 = run.containsBean("pet1");
System.out.println(pet3);
}
}
2.原生配置文件注入@ImportResource
package com.atguigu;
import ch.qos.logback.core.db.DBHelper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
@Import({DBHelper.class})
@SpringBootApplication(scanBasePackages = "com.atguigu")
@ImportResource("classpath:beans.xml")
public class mainApplicatin {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(mainApplicatin.class, args);
boolean user7 = run.containsBean("haha");
System.out.println(user7);
boolean pet4 = run.containsBean("haihaihai");
System.out.println(pet4);
}
}
3.配置绑定@ConfigurationProperties
1.第一种直接使用@ConfigurationProperties
一定要在组件上写
//实体类
package com.atguigu.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "people")//一定要在组件上写
public class User {
String username;//注意这里的属性名和配置文件中的名字是一样的
int age;
}
//Controller层的测试类
import com.atguigu.bean.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Autowired
User user;
@RequestMapping("/p")
public User show2(){
return user;
}
}
2.@EnableConfigurationProperties(User.class)+@ConfigurationProperties(prefix = "people")
前一个注解能自动将实体类注册进容器中,并且开启他的绑定功能
//测试Controller是不变的
//实体类(去掉了@Component)
package com.atguigu.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "people")//一定要在组件上写
public class User {
String username;//注意这里的属性名和配置文件中的名字是一样的
int age;
}
//主类
package com.atguigu;
import com.atguigu.bean.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication(scanBasePackages = "com.atguigu")
@EnableConfigurationProperties(User.class)
public class mainApplicatin {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(mainApplicatin.class, args);
}
}
四.自动配置原理入门
1.引导加载自动配置类
2.自动配置流程
我们以springframework-boot-aop 不生效举例
再找个生效的案例
总之就是
1.SpringBoot会加载所有的配置类:xxxxAutoConfiguration
2.每个自动配置类都按照条件进行生效,一般都会默认绑定配置文件中的值xxxxProperties里
面拿,而这个xxxxProperties是和我们的application.properties进行绑定
3.生效的配置类就会给容器添加很多的组件
4.只要容器中有这些组件,相当于这些功能就有了
5.只要用户自己配置的,就以用户配置的优先
定制化组件:
1.用户直接自己@Bean替换掉底层的组件
2.用户自己去看这个组件获取的是配置文件的哪些值,我们直接去改配置文件
xxxxAutoConfiguration->创建组件->xxxxProperties里面拿值->application.properties
3.最佳实践-应用咋写 1.引入场景依赖
Developing with Spring Boot
2.查看配置了哪些东西
自己爬源码
配置文件中添加debug=true,然后运行程序,就能打印自动配置报告
3.是否需要修改?
参照文档修改配置,自己分析咋配置Common Application Properties
自定义加入或者替换组件
自定义器xxxxCustomizer
yaml: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
行内写法: k: {k1:v1,k2:v2,k3:v3}
#或
k:
k1: v1
k2: v2
k3: v3
数组:一次按次序排列的值,array、list、queue
行内写法:k: [v1,v2,v3]
#或
k:
- v1
- v2
- v3
实例:
@Data
public class Person {
private String userName;
private Boolean boss;
private Date birth;
private Integer age;
private Pet pet;
private String[] interests;
private List animal;
private Map score;
private Set salarys;
private Map> allPets;
}
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}] #对象的非行内写法+数组行内写法+对象的行内写法
书写提示:
org.springframework.boot
spring-boot-configuration-processor
true
org.springframework.boot
spring-boot-maven-plugin
org.springframework.boot
spring-boot-configuration-processor
2.资源访问
(1)静态资源访问
1.静态资源目录:/static 、 /public、 /resources 、 /META-INF/resources,将静态资源放到
这些目录下就能直接访问到。例如:http://localhost:8080/2.jpg
2.原理:静态映射是默认是/**,但是在进行请求是要先看Controller能不能解决问题,如果不
能那就去上面的静态目录中找静态资源,如果连静态资源都没有就404
3.修改静态资源的访问前缀,或者静态资源的默认目录
(2)支持欢迎页
1. 静态资源路径下 index.html的会被当做欢迎界面,访问根路径就能看到
此时可以配置静态资源的路径
但不能配置静态资源的访问前缀,否则欢迎页效果会失效,报404
2.controller能处理/index
就是设置浏览器菜单栏的小图标,只要把favicon.ico放到静态资源目录下就好。
同样也是不能配置静态资源的访问前缀,否则会失效。



