SpringBoot学习笔记
文章目录
Spring Boot初级
1、Spring缺点
1.配置繁琐 需要大量的xml配置文件。
2.依赖繁琐
2、SpringBoot功能
1.自动配置
2.起步依赖 对于其他库的依赖传递。
2.辅助功能 如tomcat,安全功能 外部配置等。
SpringBoot并不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式。
3、SringBoot 快速入门小结
1.SpringBoot在创建项目时,使用jar的打包方式。
2.SpringBoot的引导类,是项目入口,运行main方法就可以启动项目。
3.使用SpringBoot和Spring构建的项目,业务代码编写方式完全一样。
@SpringBootApplication 内置注解
@Target({ElementType.TYPE,ElementType.METHOD}) //表示这个注解可以加到那个范围上 类和方法上
@Retention(RetentionPolicy.RUNTIME) //表示注解的生效时机 运行时
@Documented //生成javadoc的文档
@Inherited //表示该注解会被子类继承 注意,仅针对类,成员属性、方法并不受此注释的影响。
@SpringBootConfiguration //读取配置文件,配置文件的路径是当前根目录(src/main/resources/application.yml等)
@EnableAutoConfiguration //开启自动配置,扫描当前的所有依赖的jar包,发现新的依赖出现将会将会根据依赖完成各种自动配置(扫描start_web,自动配置内置tomcat默认路径、端口;依赖了rabbitmq,自动配置rabbitTemble)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) //扫描范围默认情况下是启动类坐在的同名包及其子孙包, 属于Spring框架(@Component,@Service,@Controller,@Repository,@Entity)
public @interface SpringBootApplication {
//暂时忽略
}
4、SpringBoot起步依赖原理分析
1.spring-boot-starter-boot
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
2.spring-boot-starter-web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
小结:
在spring-boot-starter中定义了各种技术的版本信息,组合了一套最优搭配的技术版本。
在各种starter中,定义了完成该功能需要的坐标合集,其中大部分版本信息来自于父工程。
我们的工程继承parent,引入starter后,通过依赖传递,就可以简单方便获得需要的jar包,并且不会存在版本冲突等问题。
5、Springboot配置
1.配置文件三种格式:
- application.properties
- application.yml
- application.yaml
加载顺序 properties 》yml 》 yaml
高优先级有的 低优先级的不会生效,只有高优先级没有的低优先级有的才会生效.
#参数引用
name: abc
person3:
name: ${name} #引用上边定义的name
#对象
person:
name: zhangsan
age: 20
#对象的行内写法
person2: {name: lisi,age: 20}
#数组
address:
- beijing
- shanghai
#数组的行内写法
address2: [beijing,shanghai]
#纯量
msg1: 'hello \n world' #''不会识别转义字符,会原样输出
msg2: "hello \n world" #""会识别转义字符
2.读取配置内容:
- @Value 获取单个的值。
- Environment 对象方式注入 用getProperties()方式获取。
- @ConfigurtionProperties 需要创建一个对象 用对象和配置属性绑定 ,根据配置前缀后的对应属性进行注入。
6、使用Profile来完成不同环境下动态配置切换功能
1.多profile文件方式:提供多个配置文件,每个代表一种环境。
- application-dev.properties 开发环境
- application-pro.properties 生产环境
- application-test.properties 测试环境
选择properties文件的环境:
spring.profiles.active=pro
2、多文档方式 在yml中使用“ — ”分割不同配置
#多文档方式 在yml中使用 --- 分割不同配置
---
#生产环境
server:
port: 8081
spring:
profiles: pro
---
#开发环境
server:
port: 8082
spring:
profiles: dev
---
#测试环境
server:
port: 8083
spring:
profiles: test
---
#选择启用的环境
spring:
profiles:
active: dev
3.profile激活方式
配置文件:在配置文件中配置:Spring.profiles.active = dev
虚拟机参数: 在VM option指定: -Dspring.profiles.active=dev
命令行参数: java -jar xxx.jar --spring.profiles.active=dev
4.内部配置加载顺序
file../config/: 当前项目下的/config目录下
file../ :当前项目的根目录
classpath/config:classpath的/config目录
classpath/:classpath的根目录
加载顺序为上文的排列顺序,高优先级配置的属性才会生效
5.外部配置加载顺序
(1). 在命令行填写:java-jar .\项目jar包.jar --server.port=8082
(2). 创建配置文件启动时引入:java -jar .\项目jar包.jar --spring.config.location=d://application.properties
(3). 在项目target目录里添加配置文件跟jar包同级 application.properties文件启动时自动识别
(4). 在项目target目录里创建config文件添加配置文件 application.properties文件启动时会自动识别(比(3)的启动顺序要高)
通过官网查看外部属性加载顺序
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
7、Springboot整合其他框架
1. SpringBoot整合Junit
1.搭建SpringBoot工程
2.引入starter-test起步依赖
3.编写测试类
4.添加测试相关注解
@RunWith(SpringRunner.class)
@SpringBootTest(classes=启动类.class)
5.编写测试方法
在测试方法上添加@Test注解
- 添加依赖:
<!--添加测试依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
- 测试代码:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = 项目启动类.class)
public class SpringBootApplicationTest {
@Test
public String demo(){
System.out.println("测试类");
}
}
2. SpringBoot整合Redis
1.搭建SpringBoot工程
2.引入redis起步依赖
3.配置redis相关属性
4.注入RedisTemplate模版
5.编写测试方法,测试
- 添加依赖:
<!--添加Redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置文件:
spring:
redis:
host: 127.0.0.1 #redis主机ip
port: 6379 #redis端口号
- 测试代码:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = 项目启动类.class)
public class SpringBootApplicationTest {
//注入RedisTemplate
@Autowired
private RedisTemplate redisTemplate;
//测试Redis
@Test
public void redisTest(){
//存入键值对
redisTemplate.boundValueOps("name").set("张三");
//获取键值对
Object name = redisTemplate.boundValueOps("name").get();
System.out.println(name);
}
}
3. Springboot整合Mybatis
1.搭建SpringBoot工程
2.引入Mybatis起步依赖,添加mysql驱动
3.编写DataSource和MyBatis相关配置
4.定义表和实体类
5.编写dao和mapper文件/纯注解开发
6.测试
- 添加依赖:
<!--整合mybatis-->
<!--添加mysql连接依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!-- <scope>runtime</scope>-->
</dependency>
<!--添加mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
- 配置文件:
#配置数据源信息
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/examfile?serverTimezone=UTC
username: root
password: root
#mybatis
mybatis:
# config-location: #指定mybatis的核心配置文件
mapper-locations: classpath:mapper/*Mapper.xml #mapper映射文件路径
type-aliases-package: com.haotian.domain #包扫描
- 测试代码:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = 项目启动类.class)
public class SpringBootApplicationTest {
@Autowired
private UserMapper userMapper;
//测试Mybatis
@Test
public void mybatisTest(){
List<User> users = userMapper.findAll();
for (User user:users ){
System.out.println(user);
}
}
}
SpringBoot高级
1、Spirng 原理分析
目标:
- Condition是在Spinrg4.0增加的条件判断功能,通过这个功能可以实现选择性的创建Bean操作。
- SpringBoot是如何知道要创建那个Bean的?比如SpringBoot是如何要创建RedisTemplate的?
分析:
- 添加依赖:
<!--添加Redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置文件:
spring:
redis:
host: 127.0.0.1 #redis主机ip
port: 6379 #redis端口号
- 测试代码:
@SpringBootApplication
public class SpringBootDemoApplication {
public static void main(String[] args) {
//启动SpringBoot的应用,返回Spring的IOC容器
ConfigurableApplicationContext context = SpringApplication.run(SpringBootDemoApplication.class, args);
//获取Bean,redisTemplate
Object redisTemplate = context.getBean("redisTemplate");
System.out.println(redisTemplate);
}
}
案例:需求
-
在Spring的IOC容器中有一个User的Bean,现要求:
1.导入Jedis坐标后加载该Bean,没导入,则不加载。
2.将类的判断定义为动态的。判断那个字节码文件存在可以动态指定。 -
实现代码:
//判断是否有对应的字节码文件
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ClassCondition.class)
public @interface ConditionalOnClass {
String[] value();
}
@Configuration
public class UserConfig {
@Bean
//@Conditional(ClassCondition.class)
//@ConditionalOnClass("redis.clients.jedis.Jedis")
@ConditionalOnClass("com.alibaba.fastjson.JSON")
public User user(){
return new User();
}
//获取配置文件中定义的对象
@Bean
@ConditionalOnProperty(name = "name",havingValue = "zhangsan")
public User userTwo(){
return new User();
}
}
//重新实现condition接口
public class ClassCondition implements Condition {
/**
* @param context 上下文对象。用于获取环境,IOC容器,ClassLoader对象
* @param metadata 注解元对象。可以用于获取注解定义的属性值
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//1.需求:导入jedis坐标后创建Bean
//思路:判断redis.clients.jedis.Jedis.class文件是否存在
//2.需求: 导入通过注解属性值value指定坐标后创建Bean
//获取注解属性值 value
Map<String, Object> map = metadata.getAnnotationAttributes(ConditionalOnClass.class.getName());
String[] value = (String[]) map.get("value");
boolean flag = true;
try {
//循环打印集合中的数据
for (String className : value){
//寻找对应的class字节码文件
Class<?> cls = Class.forName(className);
System.out.println(cls);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
flag = false;
}
return flag;
}
}
Condition - 小结:
- 自定义条件:
1.定义条件类:自定义类实现Contition接口,重写matches方法,在matches方法中进行逻辑判断,返回boolean值。matches方法两个参数:
context:上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等。
metadata:元数据对象,用于获取注解属性。
2.判断条件:在初始化Bean时,使用@Conditional(条件类.class)注解
SpringBoot提供的常用条件注解:
@ConditionalOnProperty :判断配置文件中是否有对应属性和值才初始化Bean
@ConditionalOnClass :判断环境中是否有对应字节码文件才初始化Bean
@ConditionalOnMissingBean : 判断环境中没有对应Bean才初始化Bean
2、SpringBoot自动配置
1. 内置web服务器
目标:
- 切换内置web服务器:
SpringBoot的web环境中默认使用tomcat作为内置服务器,其实SpringBoot提供了4中内置服务器供我们选择,我们可以很方便切换。
分析:
- SpringBoot内嵌四种服务器:
JettyWebServerFactoryCustomizer
NettyWebServerFactoryCustomizer
TomcatWebServerFactoryCustomizer
UndertowWebServerFactoryCustomizer
小结:
切换方式为:在pom下修改服务器 默认是tomcat服务器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--排除tomcat依赖-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--引入jetty依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
2. @Enable注解
简介:
SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态启动某些功能的。而其底层原理是使用@Import注解导入一些配置类,实现Bean的动态加载。
- 测试代码:
/**
* @ConponentScan 扫描范围:当前引导类所在包跟子包
* 1.使用ComponentScan扫描需要导入的(com.haotian.config)包
* 2.可以使用@Import注解,加载类,这些类都会被Spring创建,放入IOC容器
* 3.可以对@Import进行封装
*/
@SpringBootApplication
public class SpringBootDemoApplication {
public static void main(String[] args) {
//启动SpringBoot的应用,返回Spring的IOC容器
ConfigurableApplicationContext context = SpringApplication.run(SpringBootDemoApplication.class, args);
//获取Bean
Object user = context.getBean("user");
System.out.println(user);
}
}
3. @Import注解
简介:
@Enable*底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中。而@Import提供4种用法。
1.导入Bean
2.导入配置类
3.导入ImportSelector实现类,一般用于加载配置文件中的类
4.导入ImportBeanDefinitionRegistrar实现类
- 测试代码:
//@Import(User.class)
//@Import(UserConfig.class)
//@Import(MyImportSelector.class)
//@Import(MyImportBeanDefinitionRegistrar.class)
@SpringBootApplication
public class SpringBootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringBootEnableApplication.class, args);
/* Object user = context.getBean(User.class);
System.out.println(user);*/
User bean = context.getBean(User.class);
System.out.println(bean);
//获取导入类的名称
Map<String, User> beansOfType = context.getBeansOfType(User.class);
System.out.println(beansOfType);
Role role = context.getBean(Role.class);
System.out.println(role);
}
- 导入配置类
//如果使用@Import方式导入 可以不加@Configuration
//@Configuration
public class UserConfig {
@Bean
public User user(){
return new User();
}
@Bean
public Role role(){
return new Role();
}
}
- 导入ImportSelector实现类,一般用于加载配置文件中的类
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.haotian.domain.Role","com.haotian.domain.User"};
}
}
- 导入ImportBeanDefinitionRegistrar实现类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
registry.registerBeanDefinition("user",beanDefinition);
}
}
4. @EnableAutoConfiguration注解
简介:
- @EnableAutoConfiguration注解内部使用@Import(AutoConfigurationImportSelector.class)来加载配置文件
- 配置文件位置:META-INF/spring.factories,该配置文件中定义了大量的配置类,当SpringBoot应用启动时,会自动加载这些配置类,初始化Bean。
- 并不是所有的Bean都会被初始化,在配置类中使用Condition来满足条件的Bean。
案例:
需求:
自定义redis-starter。要求当导入redis坐标时,SpringBoot自动创建Jedis的Bean。
实现步骤:
(1). 创建redis-spring-boot-autoconfigure模块
(2). 创建redis-spring-boot-starter模块,依赖redis-spring-boot-autoconfigure的模块
(3). 在redis-spring-boot-autoconfigure模块中初始化Jedis的Bean。并定义META-INF/spring.factories文件
(4). 在测试模块中引入自定义的redis-starter依赖,测试获取Jedis的Bean,操作redis。
小结:
- 添加依赖
<!--引入Jedis依赖-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
- 编写代码
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
@ConditionalOnClass(Jedis.class)
public class RedisAutoConfiguration {
//提供Jedis的Bean
@Bean
@ConditionalOnMissingBean(name = "jedis")
public Jedis jedis(RedisProperties redisProperties){
System.out.println("RedisAutoConfiguration...");
return new Jedis(redisProperties.getHost(),redisProperties.getPort());
}
}
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "redis")
public class RedisProperties {
private String host = "localhost";
private int port = 6379;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
- META-INF/spring.factories配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.haotian.redis.config.RedisAutoConfiguration
3、SpringBoot监听机制
简介:
- SpringBoot的监听机制,其实是对Java提供的事件监听机制的封装。
- Java中的事件监听机制定义了一下几个角色:
(1).事件:Event,继承java.util.EventObject类的对象
(2).事件源:Source,任意对象Object
(3).监听器:Listener,实现java.util.EvenetListener接口的对象
分析:
- SpringBoot在项目启动时,会对几个监听器进行回调,我们可以实现这些写监听器接口,在项目启动时完成一些操作。
ApplicationContextInitalizer
用于项目启动之前去加载配置文件
SpringApplicationRunListener
启动初始化的过程中
CommandLineRunner
项目启动后加载
ApplicationRunner
项目启动后加载
springboot流程分析图
4、SpringBoot监控
1.SpringBoot自带监控功能Actuator
简介:
- SpringBoot自带监控功能Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、配置属性、日志信息等
分析:
- 1.导入依赖坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 2.配置文件
#开启健康检查的完整信息
management.endpoint.health.show-details=always
#将所有的监控endpoint暴露出来
management.endpoints.web.exposure.include=*
- 3.访问http://localhost:8080/aruator
2. SpringBoot监控-Spring boot admin
简介:
- Spring Boot Admin 是一个开源社区项目,用于管理和监控SpringBoot应用程序
- Spring Boot Admin有两个角色,客户端(Client)和服务端(Server)
- 应用程序作为Spring Boot Admin Clinet向为Spring Boot Admin Server注册
- Spring Boot Admin Server的UI界面将Spring Boot Admin Client的Actuator Endpoint上的一些监控信息
分析:
- admin-server 配置:
1.创建admin-server模块
2.导入依赖坐标admin-starter-server
3.在引导类上启用监控功能@EnableAdminServer
- admin-server 添加依赖
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
- admin-servert 配置文件
server.port=9090
- admin-servert 启动类添加注解
@EnableAdminServer
@SpringBootApplication
public class SpringBootServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootServerApplication.class, args);
}
}
-
admin-client 配置:
1.创建admin-client模块
2.导入依赖坐标admin-starter-client
3.配置相关信息:server地址等
4.启动server和client服务,访问server -
admin-client 添加依赖
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
- admin-client 配置文件
#执行admin.server地址
spring.boot.admin.client.url=http://localhost:9090
#开启健康检查的完整信息
management.endpoint.health.show-details=always
#将所有的监控endpoint暴露出来
management.endpoints.web.exposure.include=*
- admin-client 启动
@SpringBootApplication
public class SpringBootClientApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootClientApplication .class, args);
}
}
idea控制栏也有监控信息
运行控制台Console旁边的 Endpoints选项
5、SpringBoot项目部署
SpringBoot项目开发完毕之后,支持两种方式部署到服务器
1. jar包(官方推荐)
java -jar .\xxx.jar
2. war包
springboot项目修改为war包
1.在pom文件中加入打包方式
<packaging>war</packaging>
2.在启动类上继承 SpringBootServeletInitializer
快捷键:alt + insert
复写configure();
修改return builder.sources(当前启动类.class);
3.把war放入tomcat中的webapps中启动tomcat
完成