目录
@SpringBootApplication包含三大主要的注解
SpringBoot
含义:是框架的框架,简化了常规框架的配置方式,只需要很少的代码便可实现大量的功能
作用:SpringBoot基于spring开发,能快速创建出生产级别的Spring,让以后用Spring开发变得简单
理解:
关于SpringBoot有一句很出名的话就是约定大于配置,采用springboot可以大大简化开发模式,它集成了大量常用的第三方库配置,所有你想集成的常用框架他都有对应的组件支持,例如:Redis、MongoDB、Dubbo、kafka、ES等。springboot应用中这些第三方库几乎可以零配置的开箱即用,大部分的springboot应用都只需要非常少量的配置代码,开发者能够专注于业务逻辑。另外springboot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性问题得到了很好的解决。
注意:
- SpringBoot底层是Spring框架
- SpringBoot是整合Spring技术栈的一站式框架
- SpringBoot是简化Spring技术栈的快速开发脚手架
SpringBoot优点
- 创建独立Spring应用(不用写spring配置文件)
- 内嵌web服务器
- 自动starter依赖,简化构建配置
- 自动配置Spring以及第三方功能
- 提供生产级别的监控、健康检查及外部化配置
- 无代码生成、无需编写XML,开箱即用
快速搭建springboot应用程序
创建一个maven项目
导入依赖
<!--引入父maven项目,集成父maven项目的所有配置信息-->
<!--parent标签里面提供了spring集成所有其他第三方框架的所有依赖-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
</parent>
<dependencies>
<!--web工程依赖集——使用springmvc构建web应用程序,使用tomcat为默认嵌入容器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.3</version>
</dependency>
<!--springboot测试文件依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!--部署springboot的插件-->
<!--用于运行命令时指定main方法启动类在哪里-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
@RestController
@RequestMapping("/test")
public class HelloController {
@RequestMapping("/hello")
public String asyHi(){
return "hello world";
}
}
在所有类的外层创建启动类
//标记成springboot的启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
将启动端口号改为8088,为项目加虚拟路径为app
#resources目录下(编译后会编译到classes文件中)
#application.properties(文件名必须固定为application)文件内
server.port=8088
#为项目加虚拟路径
server.servlet.context-path=/app
#初始化懒加载,所有的bean在spring容器初始化的时候将不会去创建这些bean,而是在我们使用的时候才会创建
spring.main.lazy-initialization=true
使用maven命令打包后在对应包所在文件中使用java -jar 完整包名 --server.port=8087命令开启服务
注意:这里用直接配置的端口号覆盖了原来的配置端口,这样运行的信息会通过main函数的args参数传递下去 ,进而实现端口配置
测试类
//在主启动类所在同名包路径的同包或子包中
//提前已经将User类交给spring容器管理了
@SpringBootTest
public class TestSpringBoot {
@Autowired
private User user;
//注意@Test注解用import org.junit.jupiter.api.Test;
@Test
public void test1(){
System.out.println(user.getName());
}
}
pom内的parent标签
作用:引入父maven项目,使该项目继承了父maven项目的所有配置信息
点开[spring-boot-starter-parent]依赖,然后发现其内部也有父maven项目——[spring-boot-dependencies],点进该父maven项目发现第三方库所有的版本号都在这里维护了;所以它就用该种方式帮我们管理了第三方库之间的版本冲突问题,以及我们会用到的所有依赖信息也都在这里引入进来了;以后我们导入已有的依赖就可以不用写版本号了
@SpringBootApplication
被该注解修饰的类,为springboot的启动类(入口);因为springboot的所有自动配置都是从该注解开始的
@SpringBootApplication包含三大主要的注解
- @ComponentScan(包路径):包扫描注解
- @EnableAutoConfiguration:实现自动配置的注解
- @SpringBootConfiguration:实现spring配置文件的功能,标识该类实现容器功能
@ComponentScan注解
规则:Spring底层解析配置类的时候会扫描当前包的路径,默认是主启动类所在的包路径,以后写代码必须在主启动类所在包路径的同包或子包中编程
@EnableAutoConfiguration注解
规则:该注解用来加载SpringBoot-start-xxx的启动项,当主启动类的执行时,则会开始加载启动项中的配置,实现自动化配置
注意:这里的开箱即用中SpringBoot-start-xxx的启动项为箱,@EnableAutoConfiguration自动化配置为即用
@SpringBootTest注解
作用:当运行测试类中@Test注解标识的方法时springboot程序启动,springboot程序启动,内部spring容器启动,基于ioc管理对象,DI注入对象;进而可以在任意测试类中注入想要的对象
注意:
- 使用@Test注解的包必须为import org.junit.jupiter.api.Test才能实现一键启动
- 测试类用@SpringBootTest注解标识,并且测试类的包路径在主启动类所在同名包路径的同包或子包中才能实现一键启动
自定义SpringApplication
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
//关闭springboot的启动横幅
app.setBannerMode(Banner.Mode.OFF);
//一键启动springboot
app.run(args);
}
}
在springApplication内获得bean
注解配置spring容器
//告诉springboot这是一个配置类,这里的proxyBeanMethods值默认为true(代理bean的方法,为true后那么获得到的bean返回的对象就全一样)
@Configuration(proxyBeanMethods = true)
//组件扫描(将该包下被标识的的组件交给该容器来保存)
@ComponentScan("cn.tedu.springboot.service")
//向容器中导入指定类型的组件——默认组件的名字为全类名
@Import({People.class, Student.class})
public class MyConfig {
@Bean//给容器添加组件,组件id默认为方法名,组件为方法的返回值,组件名也可以改变@Bean("app")——组件名为app
public String fly(){
return "hello world";
}
}
从容器中获取组件
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
//返回ioc容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class);
//获取容器里的组件
String fly = run.getBean("fly", String.class);
System.out.println(fly);
//获取容器组件(配置类本身也是组件)
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);//cn.tedu.springboot.config.MyConfig$$EnhancerBySpringCGLIB$$7bfb7bcb@3fc4a116
//获取Import组件
People people = run.getBean(People.class);
System.out.println(people);
}
}
条件装配
含义:满足Conditional条件的时候就会向容器中注入容器中注入相关组件
注解:@Conditional
子注解
经典注解@ConditionalOnBean使用案例
@Configuration(proxyBeanMethods = true)
//从resouses目录下的beans.xml导入资源
@ImportResource("classpath:beans.xml")
public class MyConfig {
//当容器中有people这个组件时再注册该组件(也可以直接通过类名注入——value属性)
//该注解也可以标注在类上
@ConditionalOnBean(name = "people")
public String fly(){
return "hello world";
}
@Bean("people")
public People getPeople(){
return new People();
}
}
配置文件的使用
SpringBoot使用一个全局配置文件也称核心配置文件(application文件),配置文件在约定的情况下名字是固定的
配置文件的作用:修改springboot自动配置的默认值;springboot在底层都给我们配置好
- application.properties
- application.yaml
properties文件语法
- 数据结构类型:key=value(特别注意不要有空格)
- 程序读取该文件时默认采用ISO-8859-1编码
- 所有的的key都必须完整,不能缩进
- 注释用#
server.port=8088
server.servlet.context-path=/app
yaml文件语法
- 写法为key:value(注意冒号和value之间有空格)
- 层级代码结构,应注意缩进
- 文件读取时默认采用UTF-8编码
- 注释用#
server:
port: 8088
servlet:
context-path: /app
配置文件的加载顺序
spring-boot-starter-parent内
<includes>
<include>**/application*.yml</include>
<include>**/application*.yaml</include>
<include>**/application*.properties</include>
</includes>
注意:配置文件加载顺序是针对共有的配置,如果两种文件有相同的配置则会以优先级高的文件配置为准,若优先级低的配置文件有优先级高的配置文件所没有的属性,则该属性也可用
其他约定配置文件加载顺序
- 直接子目录/config(命令行直接配置子目录)
- 项目根目录/config
- 项目根目录
- classpath根目录的config
- classpath根目录
设置默认配置文件读取
#app.properties文件内
server.port=8888
注意:约定的配置优先级最高(application)
普通方式
@SpringBootApplication
public class SpWebApplication {
public static void main(String[] args) throws Exception {
SpringApplication application = new SpringApplication(SpWebApplication.class);
Properties properties = new Properties();
//通过当前类加载器获得app.properties文件内容
InputStream stream = SpWebApplication.class.getClassLoader().getResourceAsStream("app.properties");
properties.load(stream);
//设置默认配置文件
application.setDefaultProperties(properties);
application.run(args);
}
}
注解方式
@SpringBootApplication
@PropertySource("classpath:/app.properties")
public class SpWebApplication {
public static void main(String[] args) throws Exception {
SpringApplication application = new SpringApplication(SpWebApplication.class);
application.run(args);
}
}
动态为属性赋值
properties文件为属性动态赋值
#mysql.properties文件内
mysql.username=名字
mysql.password=123
@RestController
@PropertySource(value = "classpath:/mysql.properties",encoding = "UTF-8")
public class TestController {
@Value("${mysql.username:lili}")
private String username;
@Value("${mysql.password}")
private String password;
@RequestMapping("/test")
public String getMsg(){
return username+password;
}
}
访问路径:localhost:8080/test
注意:
- @PropertySource注解用于将该文件交给spring容器管理,它主要用来读取properties文件
- @PropertySource注解若不设置编码,则默认为iso-8859-1编码,其内的value值应为文件路径
- @Value作用是给属性动态赋值,若属性被赋予了默认值,则默认值被value注解内的值覆盖
- @Value("${mysql.username:lili}")内的lili为没有读到mysql.username的值时给定username的默认值
- @ConfigurationProperties(prefix = "mysql")注解加载类上面,作用是将mysql为前缀的pro文件属性与类中的属性进行映射,属性相同则不用写value注解(上面2个属性均能映射)
- @Value内支持sel表达式
yml文件为属性动态赋值
前言:只要是application的配置文件(yml、properties)都是springboot的核心配置文件,springboot已经对其进行管理,就不需要再交给spring来管理了
#application.yaml文件内
mysql:
username: 名字
password: 234
@RestController
public class TestController {
@Value("${mysql.username}")
private String username;
@Value("${mysql.password}")
private String password;
@RequestMapping("/test")
public String getMsg(){
return username+password;
}
}
访问路径:localhost:8080/test
注意:yaml文件读取时默认采用utf-8形式编码
yml文件内特殊属性动态赋值
#application.yaml内
server:
port: 8888
mysql:
#数组写法
hobbies: [足球,篮球] #数组写法1
pets: #数组写法2
- cat
- dog
#map写法
girlFriend:
18: 范凉凉
20: 地里冷吧
boyFriend: {18: 张三, 20: 李四}
#随机值写法
number: ${random.int[1,100]} #随机值范围1-100岁
类比properties文件
#application.properties文件内
server.port=8888
#数组写法
mysql.hobbies=唱歌,跳舞
#map集合写法
mysql.girlFriend.18=范凉凉
mysql.girlFriend.20=迪丽冷吧
#随机数写法
mysql.number=${random.int[1,100]}
@Data
@RestController
@ConfigurationProperties(prefix = "mysql")
public class TestController {
private List<String> hobbies;
private List<String> pets;
private Map<Integer,String> girlFriend;
private Map<Integer,String> boyFriend;
private Integer number;
@RequestMapping("/test")
public String getMsg(){
return "爱好为:"+hobbies+"\n宠物为"+pets;
}
@RequestMapping("/friend")
public String getFriend(){
return "朋友为:"+girlFriend+boyFriend;
}
@RequestMapping("/random")
public String getNumber(){
return "随机值为"+number;
}
}
注意:
- 使用时要为具体实体类属性加set方法
- @ConfigurationProperties注解常用于bean属性的yml配置文件的绑定
- yml文件内可以设置随机值
- yml文件不支持sel表达式,但是支持属性引用以及对随机数的引用
- 特殊属性的动态赋值尽量不用@Value注解
springboot环境分割
前言:
- 可以用在yml文件内也可以用在properties文件内
- @Profile("环境名称")注解用在spring容器中的bean上,当触发某种环境,那么被标记为该环境的bean将会生效,其他环境的bean将不会生效
单文件形式
#application.yaml文件内
spring:
profiles:
active: dev
---
server:
port: 8888
spring:
config:
activate:
on-profile: dev
---
server:
port: 6666
spring:
config:
activate:
on-profile: test
注意:
- 每个环境之间用---来分割
- active对应哪个环境下的on-profile那么就使用哪个环境的配置
- dev(开发环境)、prod(生产环境)、test(测试环境)
分文件形式
#application.yaml文件内
spring:
profiles:
active: dev
#application-dev.yaml文件内
server:
port: 8888
#application-test.yaml文件内
server:
port: 6666
注意:
- active对应所要用的环境名称
- 文件起名:application-环境名称.yaml
- 环境名称的名字可以随意写,但约定优于配置
热部署
前言:为了进一步提高开发效率,springboot为我们提供了全局项目热部署,日后在开发过程中修改了部分代码及相关配置文件后,不需要每次重启修改生效,在项目中开启了spring全局热部署之后只需要修改之后等待几秒钟即可使修改生效
引入热部署依赖
<!--devtools热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
idea中配置
- idea中File | Settings | Build, Execution, Deployment | Compiler开启自动编译
- ctrl+shift+alt+/,选择Registry,勾上Compile autoMake allow when app running
springboot日志的使用
日志门面:不实现日志功能,只是用来整合日志的(日志抽象层)
理解:市面上的日志框架非常混乱,一个项目内多个模块可能用不同的日志框架,所以引出日志门面
使用:左边选一个门面,右边选一个实现
注意:
- springboot底层spring,spring默认用jcl门面,而springboot选用了slf4j门面和logback日志实现
- 以后开发的时候,日志记录方法的调用,不应该直接调用日志的实现类,而是调用日志抽象层里面的方法
springboot默认日志配置
@SpringBootTest
class Springboot3ApplicationTests {
//日志记录器
Logger logger = LoggerFactory.getLogger(getClass());
@Test
void contextLoads() {
String s=":";
String msg="message";
logger.trace("trace{}{}",s,msg);
logger.debug("debug{}{}",s,msg);
logger.info("info{}{}",s,msg);
logger.warn("warn{}{}",s,msg);
logger.error("error{}{}",s,msg);
}
}
日志级别:trace<debug<info<warn<error
注意:
- 日志打印规则——只打印比日志级别高的日志信息
- logger方法里面字符串内的{}为占位符(可以写多个);分别按顺序依次表示后面的数据
- springboot默认日志级别为info级别
日志的级别
#application.properties文件内
#将cn.tedu包下的文件日志级别调为trace级别
logging.level.cn.tedu=trace
#将打印的日志文件输出到具体位置
# 直接输出当前项目下的springboot.log文件中,如果不想在当前项目下生成日志文件,那么指定绝对路径
logging.file.name=springboot.log
#application.properties文件内
#将cn.tedu包下的文件日志级别调为trace级别
logging.level.cn.tedu=trace
#指定日志生成在文件的哪个目录,默认日志文件名为spring.log
#根目录下的spring/log目录里
logging.file.path=/spring/log
日志的输出格式
#application.properties文件内
#将cn.tedu包下的文件日志级别调为trace级别
logging.level.cn.tedu=trace
logging.file.name=springboot.log
#在控制台输出的日志格式
logging.pattern.console=[%thread] %msg %n
#在文件中日志输出的格式
logging.pattern.file=%d{yyyy-MM-dd} [%thread] %msg %n
静态资源访问
前言:只要静态资源放在类路径下:static or public or resources or META-INF/resources这些目录中,那么接下来浏览器就可以直接访问(当前项目根路径/+静态资源名)
原理:静态资源映射/**
请求进来,先去找controller,看能不能处理,不能处理的所有请求就会交给静态资源处理器,然后静态资源就会按照以上文件内的名字进行查找,若静态资源能找到,那么就会访问,若不能找到,那么就会404
静态资源访问前缀
#application.yml文件内
spring:
mvc:
#为静态资源加访问前缀,默认为/**
static-path-pattern: /res/** #表示res下的所有请求都是静态资源请求
注意:以上说明访问res下的东西才会映射到static or public or resources or META-INF/resources这些目录中,去查找对应的文件
改变放入静态资源文件的目录
#application.yml文件内
spring:
mvc:
#为静态资源加访问前缀,默认为/**
static-path-pattern: /res/** #表示res下的所有请求都是静态资源请求
#修改将静态资源放入/app内可以直接访问
web:
resources:
static-locations: [classpath:/app] #传递的是一个数组
设置静态资源映射
//说明其为一个配置类
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
//设置静态资源映射
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
//将路径中有backend的请求映射到classpath下的backend路径后面
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
}
静态欢迎页
- 静态资源路径下的index.html(可以配置静态资源路径,但不可配置静态资源访问前缀)
- controller方法返回的index
网站图标
将图标改为favicon.ico放入到springboot的静态目录中,那么以后访问该网页就自动有这个图标(可以配置静态资源路径,但不可配置静态资源访问前缀)
注意:这个图标在同一次会话中共享