1、Springboot简介
Springboot可以帮我们简化spring的搭建,并且快速创建一个spring的应用程序。该框架使用了特定的方法进行配置,从而使开发人员不再需要定义样板化的配置。
2、Springboot特征
SpringBoot所具备的特征有:
(1)可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;
(2)内嵌Tomcat或Jetty等Servlet容器;
(3)提供自动配置的“starter”项目对象模型(POMS)以简化Maven配置;
(4)尽可能自动配置Spring容器;
(5)提供准备好的特性,如指标、健康检查和外部化配置;
3、创建Springboot工程
要求:
- JDK必须是1.8以上
- spring的jar包必须是5.0以上
- maven必须是3.3以上
配置Springboot项目的名称,Java版本等基本信息
Springboot版本号以及该项目要进入的依赖
在这里 要注意的是Spring boot版本太高,最好使用低一点的版本,不过这里不能修改,可以在pom.xml文件中修改版本号,建议使用稳定版本。
项目结构
注意:默认springboot扫描的包为启动类所在包以及子包。
启动Springboot项目
我们不用再配置tomcat,Springboot中内置了tomcat,我们从运行的结果可以看到tomcat的启动端口号8080
pom.xml文件中相关介绍
parent: 继承,如果maven项目想成为springboot工程必须继承SpringBoot父依赖
<?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: 继承
如果maven项目想成为springboot工程必须继承SpringBoot父依赖
-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version> <!--定义依赖导入的版本,方便版本管理,尽量不要使用最新的版本-->
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.gjx</groupId>
<artifactId>Springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Springboot</name>
<description>Springboot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--web的启动依赖 把spring中常见的jar都集成到该依赖中,集成了springmvc的启动配置类-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Springboot的配置文件
两种格式的配置文件
第一种:properties属性文件
# 配置端口号
server.port=8080
# 配置默认路径
server.servlet.context-path=/dumpling1
第二种:yml文件
# 配置端口号以及默认访问路径
server:
port: 8082
# 配置默认路径
servlet:
context-path: "/dumpling"
两种配置文件都可以使用,不过要保证配置文件名是application
如果两个配置文件都存在,配置了不同的端口号,properties属性文件的优先级高,使用properties属性文件中配置的端口号,如果两个文件中的内容不完全一样,两个配置文件会合并到一起。
4、读取配置文件中的内容
我们之前使用OSS文件上传时,密钥和bucket名称等内容都是写在代码中的,如果后期需要修改密钥和bucket值,我们必须要修改源代码。在Springboot项目中,我们可以把这些内容写在配置文件中,然后通过代码读取配置文件中的内容。
读取配置文件中的内容
第一种:通过@ConfigurationProperties注解,加在类上
配置文件中的内容
# 自定义配置
people.name=dumpling
people.age=18
people.hobby[0]=sing
people.hobby[1]=swimming
实体类
@Data
@Component //该对象的创建与销毁交与spring容器管理
@ConfigurationProperties(prefix = "people") //读取配置文件中的内容
public class People {
private String name;
private Integer age;
private String[] hobby;
}
控制层
//spring容器注入People对象
@Autowired
People people;
@GetMapping("/people")
public People getpeople(){
System.out.println(people.getAge());
return people;
}
第二种:通过@Value注解 只能加在类属性上,而且只能读取基本数据类型和字符串类型
配置文件中的内容
people:
name: dumpling
age: 18
hobby:
- dance
- game
- book
map:
address: 翻斗花园
clazz: 123
实体类
@Data
@Component //该对象的创建与销毁交与spring容器管理
@ConfigurationProperties(prefix = "people") //读取配置文件中的内容
public class People {
private String name;
private Integer age;
private String[] hobby;
private Map<String,String> map;
}
控制层
如果@Value()中的内容不是基本数据类型和字符串类型会报以下错误
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'people.map' in value "${people.map}"
//使用@Value读取配置文件中的内容
@Value("${people.name}")
String name;
//报错Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'people.map' in value "${people.map}"
@Value("${people.map}")
Map<String,String> map;
@GetMapping("/people")
public People getpeople(){
System.out.println(people.getAge());
System.out.println("Value-String:"+name);
//System.out.println("Value-map:"+map);
return people;
}
5、profiles文件介绍
我们在实际开发中,环境有以下几种环境
开发环境 测试环境 线上环境 不同的环境有不同的配置内容
我们子啊实际工作中,针对不同的环境,配置不同的配置文件,然后在总的配置文件中激活相应的配置文件
开发环境的配置文件:application-dev.properties
测试环境的配置文件:application-test.properties
线上环境的配置文件:application-prod.properties
总的配置文件中激活不同环境的配置环境:spring.profiles.active=dev
6、Springboot注册web三大组件
web的三大组件:Servlet,Filter,以及Linstener监听器
我们在后面的使用过程中有可能要集成第三方框架,而第三方框架的底层可能就是依赖于过滤器或servlet。
(1)注册servlet
我们在SSM框架中注册servlet时,是注册到tomcat容器是编写的web.xml文件
<servlet>
<servlet-name></servlet-name>
<servlet-class>Servlet类</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name></servlet-name>
</url-parttern>/</url-parttern>
</servlet-mapping>
现在在springboot项目中,没有web.xml文件,那我们就需要创建一个配置类:
@Configuration //相当于web.xml文件
public class Config {
@Bean //返回的类交与spring容器管理
public ServletRegistrationBean<Servlet> servletRegistrationBean(){
ServletRegistrationBean<Servlet> registrationBean = new ServletRegistrationBean<>();
//相当于servlet-name标签
registrationBean.setName("myServlet");
//相当于servlet-class标签
registrationBean.setServlet(new MyServlet());
//相当于url-pattern标签
registrationBean.addUrlMappings("/myServlet");
return registrationBean;
}
}
这里的 registrationBean.setServlet(new MyServlet()); servlet对象可能是未来第三方框架提供的,这里的MyServlet对象是测试创建的类。
public class MyServlet extends HttpServlet {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("我是自己定义的servlet~~~~~~~~~~~");
}
}
(2)注册filter
同上,在配置类中加入FilterRegistrationBean对象
@Configuration //相当于web.xml文件
public class Config {
@Bean
public FilterRegistrationBean<Filter> filterRegistrationBean(){
FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setName("myFilter");
registrationBean.setFilter(new MyFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}
这里使用的MyFilter()对象如下:
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("经过了过滤器");
filterChain.doFilter(servletRequest, servletResponse);
}
}
7、Springboot自动装配原理
什么是自动装配?
无需手动加载某些配置,而是由Springboot自动加载进来,例如自己加载DispatcherServlet
我们之前在SSM框架中设置了包扫描,那在springboot中为什么扫描的是启动类所在的包以及子包呢?
(1)自动装配
我们在启动类上可以看到一个@SpringBootApplication注解,这个注解是一个复合注解。
@SpringBootApplication注解
@EnableAutoConfigration开启自动配置注解
AutoConfigurationImportSelector自动装配导入选择器类
AutoConfigurationImportSelector中的selectImport方法是自动装配的核心实现,它主要是读取META-INF/spring.factories文件,经过去重、过滤,返回需要装配的配置类集合;
getAttributes方法:获取@EnableAutoConfiguration中的exclude、excludeName等
getCandidateConfigurations方法:获取所有自动装配的配置类,也就是读取spring.factories文件,后面会再次说明
removeDuplicates方法:去除重复的配置项
getExclusions方法:根据@EnableAutoConfiguration中的exclude、excludeName移除不需要的配置类
fireAutoConfigurationImportEvents方法:广播事件
最后根据多次过滤、判重返回配置类合集
打断点观察所有配置类
观察自动装配的配置类
总结:springboot是如何进行自动装配的?
Spring Boot通过@EnableAutoConfiguration开启自动装配,通过SpringFactoriesloader最终加载META-INF/spring.factories中的自动配置类实现自动装配,自 动配置类其实就是通过@Conditional按需加载的配置类,想要其生效必须引入spring-boot-starter-xxx包实现起步依赖
(2)加载包扫描
我们在启动类上可以看到一个@SpringBootApplication注解,这个注解是一个复合注解,加上这个注解就指定了扫描该类所在的包以及子包。
我们来看一下这个复合注解都复合了哪些注解,由从哪里获取了要扫描的包的名称。
SpringBootApplication注解
EnableAutoConfiguration注解
AutoConfigurationPackage注解
Registrar类
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
}
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
}
}
我们在这个类中的registerBeanDefinitions()方法中看到了getPackageNames()方法,
我们可以在这一行代码打一个断点,然后再进入这个方法在返回值的地方打一个断点,观察这里的包名叫什么?
从这里可以发现扫描的包为启动类所在的包