SpringBoot
简介
定义:提供一种简单、快速开发spring项目的方式,而不是对spring的功能性增强
解决问题: xml配置繁琐、依赖包版本和兼容问题
提供功能: 1.自动配置。spring内置了许多流行框架的内置程序,通过注解的使用与否来对应开启哪些程序生效
2.内置许多jar包版本管理,使用传递依赖特性作为起步依赖。
3.快速启动,内置了多种web应用服务器,默认使用tomcat
4.统一监控。actuator监控服务的运行状态
SpringBoot 入门
-
创建maven工程,设置父工程
不写父工程,那么依赖中必须写版本 <!--springboot工程需要继承的父工程--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> </parent>
-
导入起步依赖
如果不导入此报 yml文件不会是正确样式
<!--web开发的起步依赖(集成了spring+springmvc)--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
-
定义controller控制层
-
编写引导类
-
一般来说,结尾都是以application结尾
-
springboot项目的入口
-
使用SpringBootApplication注解定义引导类
定义main方法,来运行项目
执行SpringApplictiaon.run(controller.class,args);
@SpringBootApplication //定义引导类 public class HelloApplication { public static void main(String[] args) { SpringApplication.run(HelloApplication.class,args); } }
-
-
启动测试
注意事项
1.不需要指定打包方式,自身默认为jar包,因为使用的main为入口
2.使用idea快速配置时,需要联网
插件分享
安装插件
可以查询出springBoot的包结构关系和版本
方便排查jar包版本冲突问题
1.Maven Dependency Helper
2.Maven Helper
快速构建
方式一:官网提供快速构建项目的可视化界面: start.spring.io
方式二:在idea中直接构建
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yrro3ZJ5-1602550399072)(D:\Java总结文档\图解\SpringBoot\idea快速构建.png)]
起步依赖
一、spring-boot-starter-parent 父工程依赖
在父工程中一共还有两个上级父类,最上层中依然是定义的pom打包方式
提供了大量的技术依赖包且在开发阶段就已经对各类基础做了优化测试
二、spring-boot-starter-web 导包依赖
在顶层父类中还定义了很多依赖管理包,所以在配置依赖的时候不需要再配置版本。
SprinigBoot配置
官方推荐使用yml的方式进行配置
springBoot项目配置的理论四大文件
1.pom.xml
2.web.xml(servlet3.0已经去除了web.xml的配置)【已去除】
3.容器中bean的JavaConfig配置 (spring纯注解)
4.属性配置(如:jdbc.properties)【推荐使用yml】
配置修改项
//修改端口
server:
port:8080
//给项目设置统一访问路径
spring:
application:
name:hello
属性文件配置顺序
SprinigBoot是基于约定的,如果要自己修改默认配置
**目前只能使用application.properties 、application.yam、application.yaml 三种命名方式!**
比如:
1.修改默认端口8080 ,修改为8081,就可以使用这种配置方案
2.自定义key value
注意:
如果同一级目录中三种配置文件都存在
优先级依次是application.properties 、application.yml、application.yaml,默认是application.yml
只对有冲突的配置生效
properties:
server.port=8081
name=123 //自定义name属性 不会被程序识别,但是可以自己在程序中调用
===========================
yml:
//以下是整体
server:
port: 8081 //此处有一个空格,没有就会报错 分隔符是 冒号+空格
YAML
定义:不是一种标记语言,是一种直观的,能被电脑直接识别的数据序列化格式,并且可以很容易的被阅读和与脚本语言交互
是以数据为核心,比传统xml更简洁
基本语法
三种配置文件的对比
数据格式
注意 : 统一文件中key不可重复
1.对象(map) 键值对集合
person:
name: zhangsan //注意空格
age: 23 //注意空格
//行内写法,类似于json,不推荐使用。
person: {name: zhangsan,age: 23} //注意空格
2.数组:一组
address:
- beijing //注意空格
- shanghai //注意空格
address:[beijing,shanghai]
3.纯量(常量)
msg1: 'hello \n world' //注意空格,单引号忽略转义字符,原样输出
msg2: "hello \n world" //注意空格,双引号,不忽略
4.参数引用
name:lisi //定义引用
person:
name:${name} //使用引用
数据获取
作用:将配置文件的数据读取到代码中
注意:数据沿用上面的数据
@Value
//获取基本类型
@Value("${name}") //使用上面的name引用
private String name1;
@Value("${person.name}") //使用上面的person引用
private String name1;
@RequestMapping("${name}") //使用上面的name引用
private String name1;
//获取数组
@Value("${address[0]}") //使用上面的数组引用
private String name1;
@Value("${address[1]}") //使用上面的数组引用
private String name1;
//获取常量
@Value("${msg1}") //使用上面的name引用
private String name1;
Environment
注意:如果值比较少还是建议使用value更方便
主要作用:通过该类可以在程序启动时获取系统的环境变量
//需要使用时,在对应的类中自动注入
@AutoWired
private Environment env; //自动注入,初始化时就会在容器中存在
env.getProperty("person.name");
env.getProperty("address[0]");
@ConfigurationProperties
作用:可以将对象的数据直接封装进配置文件
位置:POJO类上方,要求该类被spring识别,所以要加Component
注意:
包扫描是根据main的入口对应的包来进行扫描的。所以入口方法必须定义到根包下!!
指定要存储的对象 @ConfigurationProperties(prefix=“person”)
//注意:1.如果配置文件中 外部变量与内部有重名
// 不会自动识别person中的name,而是选择外部的代替
//解决方案: 在注解中使用属性prefix来指定用哪一个配置
//@ConfigurationProperties(prefix="person")
// 2.数组的使用则需某个类型的[] 如:String[] 来接收
person:
name: zhangsan //注意空格
age: 23 //注意空格
address:
- beijing //注意空格
- shanghai
name:lisi //外部与内部name重名,使用这个
//必须记住的常用注解
profile
作用:动态切换profile来对不同环境进行切换
可以配置多properties、yml
一、配置方式
默认加载application.yml
在application.properties配置profile文件来激活(常用)
激活后,在项目启动时就会去自动查找对应文件
spring.profiles.active=pro
1.定义多个环境配置文件
application-pro.proerties
application-test.proerties
application-dev.proerties
可以在pom文件中profiles标签中定义,使用maven高级配置,解耦
2.在application.yml配置profile文件
//使用三个 --- 来区分
---
sever:
port: 8081
spring:
profiles: dev
---
sever:
port: 8082
spring:
profiles: test
---
sever:
port: 8083
spring:
profiles: pro
二、profile激活方式
1.配置文件 (同上)
spring.profiles.active=pro
-
虚拟机配置
在edit–> configuration中-- >VM options进行配置
-Dspring.profiles.active=名字(如:上面的 pro)
-
命令行
java -jar xxx.jar --spring.profiles.actiev=名字
内部配置加载顺序
SpringBoot启动时的加载application配置文件顺序:(有config比其他的方式高)
file../config/: 当前项目下的/config目录下 //磁盘下的profile文件夹下
file../: 当前项目根目录下 //磁盘下
classpath:/config/: classpath的config目录 //resources下的profile文件夹下
classpath:/ classpath根目录 //默认用的此种方式 在resources下放置配置文件
//==========================================
可以在application中配置整个项目的访问路径
server.servlet.context-path=/路径名
外部配置加载顺序
作用:与外部配置互补。外部配置比内部配置优先生效
使用场景:若项目发布后,要修改某功能,那么直接在外部配置中覆盖内部配置的某一功能
优先级整理
1.配置文件类型的优先级
poperties>yml>yaml的优先级生效
2.配置文件位置的优先级
config目录的配置文件优先于classpath下的配置文件,config文件夹下的配置优先于根下的配置文件
3.bootstrap.yml优先于application.yml
搜索
在不知道对应的类有哪些属性的时候,可以使用搜索功能(双击shift)
搜索xxxProperties,可以找到对应的类,进入则可以查看对应的属性
SpringBoot整合
整合Junit
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
注意: 1.常规配置junit
2. 如果测试类的包是对应引导类的包的子包 那么可以不加 class=启动类.class
@RunWith(SpringRunner.class)//指定测试运行的容器
@SpringBootTest(classes = SbdemoApplication.class) //底层读取对应的xml文件告知程序
class SbdemoApplicationTests {
@Autowired
private WzTest wz;
@Test
void contextLoads() {
wz.showTest();
}
}
整合Mybatis
搭建工程时勾选 SQL–> MySQL Driver 和 Mybatis Framwork
(会单独生成一个mybatis的起步依赖,因为boot没有与mybatis进行整合,所以mybatis自己写了一个)
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!--运行时生效-->
<scope>runtime</scope>
</dependency>
yml文件中写配置信息
//指定数据源JDBC
spring:
datasource:
url: jdbc:mysql://192.168.93.133:3307/springboot #设置标准时区
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver #使用最新驱动器
================================================================
================================================================
//如果使用xml方式,要加上扫描功能
//指定扫描
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml # mapper映射文件路径
type-aliases-package: com.example.mbdemo.domain.User
@Mapper注解:在纯注解中使用,目的是将该类定义为mapper映射文件
整合Redis
注意:
勾选noSQL – spring data redis 来自动导包
RedisTemplate自动在程序运行的时候进行配置,默认是以本机ip 6379端口号
RedisTemplate //key value 是原生jdk序列化方式(看不懂的字符)
StringTemplate //key value 是字符串序列化方式
自动注入
@Autowired
RedisTemplate //工作中基本上是这个类来使用redis
redisTemplate.boundValueOps("key").set(value) //设置
Object name = redisTemplate.boundValueOps("key") //取值
配置
可以搜索 RedisProperties类 ,里面有所有的配置名字
spring:
redis:
host: IP
port:端口号
redis: 会提示弹框,选择其他参数进行配置(如:重试时间等,等待时长)
docker中实现入门案例
# 一、创建dockerfile目录,写镜像代码
1 FROM centos:7
2 # 添加压缩包
3 ADD ./jdk-8u202-linux-x64.tar.gz /root/jdk/ #同级目录下,绝对路径报错找不到路径! 此处的/root/jdk/是定义的解压路径
4
5 #设置JDK的环境变量
6 ENV JAVA_HOME=/root/jdk/jdk1.8.0_202 #此处的jdk1.8.0_202为版本解压后的文件名
7 ENV CLASSPATH=.:$JAVA_HOME/lib
8 ENV PATH=$JAVA_HOME/bin:$PATH
9 # 添加jar包到镜像文件中去
10 ADD ./dt-0.0.1-SNAPSHOT.jar /root/jdk/ #添加该jar包到解压路径中方便被下述语句识别
11 # 在镜像文件中使用jar包
12 CMD java -jar /root/jdk/dt-0.0.1-SNAPSHOT.jar #绝对路径
#二、生成镜像文件
docker build -f dockerfile文件名 -t 镜像名:版本号 . (如果没有则默认latest。有一个.)
#三、将入门案例打包上传到dockefile对应目录中
至此,dockerfile文件、入门案例jar包、jdk的linux压缩包在同层目录中(目录自创)
#四、开启镜像
docker run -it --name=容器名 -p 映射端口:8080 镜像文件名:版本(如果没有则默认latest)
#五、通过Linux的Ip和映射端口访问即可
注意事项:dockerfile只能以这种格式写且所有文件都要用./来查找,否则很容易出现找不到文件的情况。绝对路径不生效
springboot四大功能❤️
1.起步依赖
2.自动配置
3.starter
4.内置tomcat
springboot底层实现原理
自动配置
1.condition
是一个状态接口
作用:配合@Condition注解来判断某类是否可用
步骤:
1.在想要限制的@Bean类、方法上方添加@Condition(条件类.class)注解
2.创建condition实现类 重写match方法,根据Booelan返回值,来判断该类是否可以在IOC中被获取(方法参数:上下文,注解元数据)
context上下文对象: 获取环境,IOC容器,ClassLoader对象等
# 注意 :springboot提供了大量注解
条件类
package com.condition.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class UserCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//1.需求: 导入Jedis坐标后创建Bean
//思路:判断redis.clients.jedis.Jedis.class文件是否存在
boolean flag = true;
try {
Class<?> cls = Class.forName("redis.clients.jedis.Jedis");
} catch (ClassNotFoundException e) {
flag = false;
}
return flag;
}
}
核心映射类
package com.condition.condition;
import com.condition.condition.user.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
//使用condition意义:根据依赖是否存在,来判断是否可以获取该类
@Configuration //定义为核心配置类
//@Conditional(UserCondition.class)
public class UserConfig {
//使用condition来确定是否可以在容器中获取该类
@Bean
@Conditional(UserCondition.class)
public User show(){
return new User();
}
//使用注解,判断在配置文件中是否存在该键值对,如果有该类才能创建
@Bean
@ConditionalOnProperty(name = "itcast",havingValue = "itheima")
public User user2(){
return new User();
}
}
自定义condition注解
//自定义注解类
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ClassCondition.class)
public @interface ConditionOnClass {
String[] value();
}
package com.itheima.springbootcondition.condtion;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import java.util.Map;
public class ClassCondition implements Condition {
/**
*
* @param context 上下文对象。用于获取环境,IOC容器,ClassLoader对象
* @param metadata 注解元对象。 可以用于获取注解定义的属性值
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//获取注解属性值 value
//获取前端传入的参数
Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
//获取参数值数组
String[] value = (String[]) map.get("value");
//定义flag
boolean flag = true;
try {
for (String className : value) {
Class<?> cls = Class.forName(className); //遍历 如果没有这个类进入catch
}
} catch (ClassNotFoundException e) {
flag = false;
}
return flag;
}
}
核心类
@Configuration
public class UserConfig {
@Bean
@ConditionOnClass("com.alibaba.fastjson.JSON") //使用自定义的注解,传入参数
public User user(){
return new User();
}
}
面试题❤️
# springboot底层实现原理是什么?
通过@EnableAutoConfiguiration注解加载Springboot内置的自动初始化类,
在这些类中基于Spring4.0提供的condition接口进行实现,来判断是否有对应导包。
如: RedisTemplate类使用condition接口来查看是否存在有对应的依赖包
2.切换内置web服务器
1.提供多种内置服务器,默认使用tomcat
2.更换前要使用exclusion标签移除tomcat
3.导入对应的服务器依赖包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--排除tomcat依赖-->
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--引入jetty的依赖-->
<dependency>
<artifactId>spring-boot-starter-jetty</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>
3.Enable*注解
作用:对其他模块或者包的功能进行使用,在使用时能够精准的被程序所定位到
由于启动类只找上级包,所以提供三种方式扫描包
1.@Component("包名")注解 # 直接扫描某包下的所有进IOC容器
2.@Import("类")注解 # 直接导入某类进IOC容器
3.@Enable*** 自定义注解 # 该方式实际上是对import的封装使用
#==============以上方式都可以直接定义在入口启动类中================
自定义enable注解功能
//1.创建enable注解接口类,注意: 要使用@interface来标识
//2.除了元注解,还使用import注解导入其他配置类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(UserConfig.class) //使用import导入要使用的类。
public @interface EnableUser {
}
4.@Import使用
作用:把其他模块的配置类存入自己模块的IOC中
import提供四种不同的使用方式:
1.导入pojo.class
2.导入配置类 #工作中大量使用
#以下两种方式是批量导入,在框架中相对常见
3.导入ImportSelector
4.导入
扩展:
SpringApplication的返回值对象提供多种方法
其中一个方法可以获取容器中对应实体Bean在容器中的名字和值
Map<String,xxx> map context.getBeanOfType(xxx.class) #获取容器中所有可以获取这个类的key名和value值
/**
* @ComponentScan 扫描范围:当前引导类所在包及其子包
*
* com.itheima.springbootenable
* com.itheima.config
* //1.使用@ComponentScan扫描com.itheima.config包
* //2.可以使用@Import注解,加载类。这些类都会被Spring创建,并放入IOC容器
* //3.可以对Import注解进行封装。
*/
/**
* Import4中用法:
* 1. 导入Bean
* 2. 导入配置类
* 3. 导入ImportSelector的实现类。
* 4. 导入ImportBeanDefinitionRegistrar实现类
*/
四种方式:
//@Import(User.class)
//@Import(UserConfig.class) 这是一个核心配置类(该类可以不加@Configuration注解) 可以直接导入这个配置类中的所有bean进入ioc容器
//@Import(MyImportSelector.class) springboot的@SpringBootApplication核心注解中,使用这种方式导入其他类进入容器
//@Import({MyImportBeanDefinitionRegistrar.class})
@SpringBootApplication
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
Jedis jedis = context.getBean(Jedis.class);
System.out.println(jedis);
jedis.set("name","itcast");
String name = jedis.get("name");
System.out.println(name);
}
}
ImportBeanDefinitionRegistrar
package com.itheima.config;
import com.itheima.domain.User;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
//实现
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
registry.registerBeanDefinition("user", beanDefinition); //在ioc容器中注册一个bean 名字是"user" 类型是User
}
}
ImportSelector(springboot使用)
package com.itheima.config;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
//存入多个全路径名在IOC中以识别他们
// springboot的@SpringBootApplication核心注解中,使用这种方式导入其他类进入容器
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.itheima.domain.User", "com.itheima.domain.Role"};
}
}
5.EnableAutoConfiguration注解
# 该注解是在@SpringBootApplication核心注解中所定义的
# 主要作用是为了在启动的时候读取到所有bean进入容器。
# 读取的时候会找到对应的Auto类,对应类上方有condition注解定义判断是否真正需要实例化该类。
//首先会执行该方法
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);//此句为本方法核心代码
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
//由上层核心代码到达此方法
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);//关键代码
configurations = this.removeDuplicates(configurations);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
//由上层关键代码最终读取并扫描META-INF/spring.factories文件。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
6.自定义starter
举例一个stater
spring-boot-starter-web。
任何经典的 Web 应用程序都会使用所有这些依赖项。Spring Boot Starter Web 预先打包了这些依赖项。
作为一个开发者,我不需要再担心这些依赖项和它们的兼容版本。
如:jackson、logging、MVC、tomcat 等等
还有很多,比如
spring-boot-starter-test - 单元测试和集成测试
spring-boot-starter-security - 使用 SpringSecurity 进行身份验证和授权
使用场景:公司中同小组成员协同开发时,供他人使用,导入对方starter依赖就可以直接获取对应实体类
此处以redis作为示例
步骤:
1.创建工程1,导入依赖
2.自定义配置类和对应Properties类
3.resoureces下定义META-INF/factories文件
4.创建工程2,定义规范类,存放自定义配置类依赖
5.创建工程3,导入工程2依赖,测试。
注意:
1.已经导入该依赖之后,就不要再使用@Bean再次定义,可能会使starter失效。
2.要使用 @ConditionalOnMissingBean(name = "xxx") 来定义AutoConfiguration是否生效,确保bean不会冲突
redis依赖
<!--引入jedis依赖-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
XXXProperties类
package com.sbhigher.sbhigher;
import org.springframework.boot.context.properties.ConfigurationProperties;
//定义redis的存放bean实例化
//因为这是一个properties,所以需要由配置文件来定义成员变量
@ConfigurationProperties(prefix = "redis")
public class RedisProperties {
//定义连接
private String url="localhost";
//定义端口
private Integer port=6379;
public RedisProperties() {
}
public RedisProperties(String url, Integer port) {
this.url = url;
this.port = port;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
}
自动配置类
package com.sbhigher.sbhigher;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;
//当项目启动时,查找到META-INF/factories文件,通过复写该文件找到该类,再定义该类是否可以被存入IOC中
@Configuration //把该类当作核心配置类
//将来这个类可能不会被扫描到,所以使用该注解启动查找该类,因为spring会将这个类存入ioc中
@EnableConfigurationProperties(RedisProperties.class)
//由于springboot在启动时,要让这个类被成功读入ioc,所以要在META-INF下的factories文件中定义这个类的配置
public class RedisAutoConfiguration {
@Bean //把这个返回值存入bean中
@ConditionalOnMissingBean(name = "jedis") //容器中不存在Jedis才能被实例化
public Jedis getJedis(RedisProperties redisProperties){
System.out.println("自定义redis:RedisAutoConfiguration已创建....");
return new Jedis(redisProperties.getUrl(),redisProperties.getPort());
}
}
factories文件
# 必须以EnableAutoConfiguration作为key,对应的实体启动类作为value
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.sbhigher.sbhigher.RedisAutoConfiguration
启动流程分析❤️
# @SpringBootApplication是一个复合注解或派生注解,在@SpringBootApplication中有一个注解@EnableAutoConfiguration,翻译成人话就是开启自动配置。
# 而这个注解也是一个派生注解,其中的关键功能由@Import提供,它导入AutoConfigurationImportSelector类执行相关逻辑
依次调用方法:selectImports-->getAutoConfigurationEntry-->getCandidateConfigurations(具体‘自动配置-5已有介绍’)
# 最终扫描所有具有META-INF/spring.factories的文件。这个spring.factories文件也是一组一组的key=value的形式,其中一个key是EnableAutoConfiguration类的全类名,而它的value是一个个xxxxAutoConfiguration的类名的列表,这些类名以逗号分隔
# 这个@EnableAutoConfiguration注解通过@SpringBootApplication被间接的使用在启动类上。
# 在执行SpringApplication.run(...)的时候内部就会执行selectImports()方法,找到所有JavaConfig自动配置类的全限定名对应的class,然后将所有满足condition注解条件的自动配置类加载到Spring容器中。
# 每一个XxxxAutoConfiguration自动配置类都是在某些条件之下才会生效的,这些条件的限制在Spring Boot中以注解的形式体现,常见的条件注解有如下几项:
@ConditionalOnBean:当容器里有指定的bean的条件下。
@ConditionalOnMissingBean:当容器里不存在指定bean的条件下。
@ConditionalOnClass:当类路径下有指定类的条件下。
@ConditionalOnMissingClass:当类路径下不存在指定类的条件下。
@ConditionalOnProperty:指定的属性是否有指定的值
比如:1.@ConditionalOnProperties(prefix=”xxx.xxx”, value=”enable”, matchIfMissing=true),
代表当xxx.xxx为enable时条件的布尔值为true,如果没有设置的情况下也为true。
2. @ConditionalOnProperties(name=”xxx”, value=”enable”)
代表在yml配置文件中是否存在name,value对应的值,不存在为false
具体狂神博文
https://mp.weixin.qq.com/s?__biz=Mzg2NTAzMTExNg==&mid=2247483743&idx=1&sn=431a5acfb0e5d6898d59c6a4cb6389e7&scene=19#wechat_redirect
整个项目运行流程
监听机制❤️
SpringBoot 的监听机制,其实是对Java提供的事件监听机制的封装。
Java中的事件监听机制定义了以下几个角色:
① 事件:Event,继承java.util.EventObject类的对象 # 所有监听类都要继承该类
② 事件源:Source ,任意对象Object
③ 监听器:Listener,实现java.util.EventListener 接口 的对象
对java事件监听机制的封装
# 总共四个,追其源码可以发现都是继承了java.util.EventObject类
#使用需要在/resources/META-INFO/spring.factories中进行配置 ApplicationContextInitializer全路径名=实现类全路径名
1.ApplicationContextInitializer # 配置好后 是在项目还没有正式运行ioc容器前执行(spring图标生成后)
#除了要在/resources/META-INFO/spring.factories中进行配置,还要在实现类中复写有参构造器
2.SpringApplicationRunListener # 配置好后就可以对整个生命周期的相关方法进行重写的使用
#当项目启动后自动执行其run方法
3.CommandLineRunner
4.ApplicationRunner(springboot) # 使用时,对应的类要使用@Component 存入ioc中
两个长的要在META-INF中的配置文件中配置
接口全路径名=自定义全路径名
区别:仅参数
contextinilizer 初始化完成后 (属于spring)
springApplicationRunListner 整个项目生命周期(属于springboot)
Actuator监控
SpringBoot自带监控功能Actuator
作用:可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、配置属性 、日志信息等。
依赖坐标
不建议使用勾选下载依赖的方式,应自己定义springboot工程
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
访问路径,动态获取
默认以actuator作为访问路径
/info
#显示配置文件中以info开头的基本信息
info.name=“wz” info.age=22
/health
#默认关闭,监控项目中软件的使用信息
使用management.endpoint.health.show-details=always开启
# 将所有的监控endpoint暴露出来
management.endpoints.web.exposure.include=*
SpringBootAdmin
是对Actuator监控的封装升级。springboot admin图形化监控
步骤:
导包,父工程,客户端/服务端
yml中配置访问端口(可选) 默认8080
server.port=9000 (properties) <!--注意:此处的端口是监控端口,其他端口发送到这儿来-->
开启服务功能注解
@EnableAdminServer <!-- 客户端不需要加 -->
服务端
// 开启admin服务功能
@EnableAdminServer
@SpringBootApplication
public class SpringbootAdminServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootAdminServerApplication.class, args);
}
}
//服务端导包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> //springboot依赖
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId> //admin-server依赖
</dependency>
客户端
导包
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
<!--在yml文件中指定adminserver地址,访问端口依然是自己的,不是这个9000!-->
spring.boot.admin.client.url=http://localhost:9000 <!--此处是在指定把监控信息发送到哪儿去。-->
<!--查看所有信息-->
management.endpoint.health.show-details=always
<!--打开所有功能-->
management.endpoints.web.exposure.include=*
<!--yml格式-->
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: '*'
spring:
boot:
admin:
client:
url: http://localhost:9000 # 指定服务端的端口号
版本依赖
使用import导入,在要使用的地方使用。由于这也是一个父工程,但是工程中有parent了,所以使用import
包含server和client 如果有父工程,在父工程中使用
<!-- 版本控制 -->
<properties>
<java.version>1.8</java.version>
<spring-boot-admin.version>2.1.5</spring-boot-admin.version>
</properties>
<!-- 依赖导入 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-dependencies</artifactId>
<version>${spring-boot-admin.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
docker上部署入门admin
1
2 version: '3.0'
3 services:
4 tomcatclit:
5 restart: always
6 image: tomcat
7 container_name: clienttomcat
8 volumes:
9 - /root/tomcatClient:/usr/local/tomcat/webapps # war包文件是放在此挂载文件中,运行时识别解压后自动加载
10 ports:
11 - 8080:8080
12 tomcatserv:
13 restart: always
14 image: tomcat
15 container_name: servertomcat
16 volumes:
17 - /root/tomcatServer:/usr/local/tomcat/webapps
18 ports:
19 - 9000:8080
properties配置文件
# 执行admin.server地址 在docker上运行时使用
# 指定服务端的端口号
spring.boot.admin.client.url=http://192.168.93.133:9000
#在docker上执行还需要指定自己的端口号和ip
spring.boot.admin.client.instance.service-base-url=http://192.168.93.133:8080
management.endpoint.health.show-details=always
management.endpoints.web.exposure.include=*
yml
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: '*'
spring:
boot:
admin:
client:
instance:
service-base-url: http://192.168.15.135:8080 #在docker上执行还需要指定自己的端口号和ip
url: http://192.168.15.135:9000 # 指定服务端的端口号
Springboot部署jar/war包❤️
部署前提:这是一个web工程
默认为jar包(官方推荐使用)
1.打包为一个jar包
2.到对应的地方使用java -jar 编译
3.由于是web工程,且自带tomcat,所以编译后就可以直接访问
#=========================================================================
打war包方式(优先使用)
场景:生产使用。
因为jar包
1.自带的tomcat是有漏洞的
2.对tomcat做优化不灵活
1.修改pom打包方式为war
2.启动类继承war包类
3.编写方法编译war包
package com.itheima.springbootdeploy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
//继承SpringBootServletInitializer
@SpringBootApplication
public class SpringbootDeployApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SpringbootDeployApplication.class, args);
}
//重写方法,修改编译为war包
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SpringbootDeployApplication.class);
}
}
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: '*'
spring:
boot:
admin:
client:
instance:
service-base-url: http://192.168.15.135:8080 #在docker上执行还需要指定自己的端口号和ip
url: http://192.168.15.135:9000 # 指定服务端的端口号
Springboot部署jar/war包❤️
部署前提:这是一个web工程
默认为jar包(官方推荐使用)
1.打包为一个jar包
2.到对应的地方使用java -jar 编译
3.由于是web工程,且自带tomcat,所以编译后就可以直接访问
#=========================================================================
打war包方式(优先使用)
场景:生产使用。
因为jar包
1.自带的tomcat是有漏洞的
2.对tomcat做优化不灵活
1.修改pom打包方式为war
2.启动类继承war包类
3.编写方法编译war包
package com.itheima.springbootdeploy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
//继承SpringBootServletInitializer
@SpringBootApplication
public class SpringbootDeployApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SpringbootDeployApplication.class, args);
}
//重写方法,修改编译为war包
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SpringbootDeployApplication.class);
}
}