1.什么是Spring Boot?(以下来自百度百科)
Spring Boot是由Pivotal团队提供的全新框架,Spring Boot基于Spring4.0设计,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。另外SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性等问题得到了很好的解决。
SpringBoot所具备的特征有:
(1)可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;
(2)内嵌Tomcat或Jetty等Servlet容器;
(3)提供自动配置的“starter”项目对象模型(POMS)以简化Maven配置;
(4)尽可能自动配置Spring容器;
(5)提供准备好的特性,如指标、健康检查和外部化配置;
(6)绝对没有代码生成,不需要XML配置。
2.什么是springboot starter?
它将常用依赖分组进行整合,将其依赖合并到一个依赖中,这样就可以添加到项目的maven或gradle中,即起步依赖
解决问题:
(1)依赖管理的坐标信息比较繁琐
(2)容易产生依赖版本冲突
3.什么是JavaConfig?
SpringBoot采用 JavaConfig的方式对Spring进行配置,并且提供了大量的注解,极大的提高了工作效率。
生成bean对象到IOC容器中,通过以下方式进行构建,IOC容器是Map数据结构,key就是方法名user,value就是返回值new User()对象,如下
@configuration
public class SpringBootConfiguration{
@Bean
public User user(){
return new User();
}
4.自动配置
(1)SpringBoot的自动配置特性利用了Spring对条件化配置的支持,合理地推测应用所需的bean并自动化配置他们,即springboot在启动的过程中,会自动的将一些配置类的bean进行创建,并且添加到IOC容器中,再通过注解@Resource或@Autowrite即可拿来使用。
(2)解决spring配置繁琐问题。
spring工程
需要在配置文件applicationContext.xml进行bean创建和配置
<bean id="redisTemplate" class="redisTemplate全路径">
......
springboot过程
引入对应RedisTeamplate依赖
springboot根据依赖的引入情况,会自动的完成的一些配置bean对象的创建,同时添加到IOC容器中
通过注解@Resource或@Autowrite即可拿来使用
5.内置servlet容器
部署变得简单,SpringBoot内置了三种Servlet容器,Tomcat,Jetty,undertow。我们只需要一个Java的运行环境就可以跑SpringBoot的项目了,SpringBoot的项目可以打成一个jar包。
6.案例实现
(1)使用Spring Initializr方式构建Spring Boot项目
(2)完成GAV坐标
(3)选择springboot版本,选择初始依赖
(4)创建好的Spring Boot项目结构如图
(5)创建controller
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "hello springBoot";
}
}
(6)启动springbootapplication
(7)访问localhost:8080/hello,即可访问接口资源
解决乱码问题
方法1:@RequestMapping(produces = “application/json; charset=utf-8”)
方法2:在application中配置
#设置响应为utf-8
spring.http.encoding.force-response=true
7.热部署
在开发项目过程中,当修改了某些代码后需要本地验证时,需要重启本地服务进行验证,启动这个项目,如果项目庞大的话还是需要较长时间的,spring开发团队为我们带来了一个插件:spring-boot-devtools,很好的解决了本地验证缓慢的问题。
(1)添加spring-boot-devtools热部署依赖启动器
<!-- 引入热部署依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
(2) IDEA工具热部署设置
选择IDEA工具界面的【File】->【Settings】选项,打开Compiler面板设置页面
在项目任意页面中使用组合快捷键“Ctrl+Shift+Alt+/”打开Maintenance选项框,选中并打开Registry页面
页面原始输出的内容是“hello Spring Boot”。
为了测试配置的热部署是否有效,接下来,在不关闭当前项目的情况下,将HelloController 类中的请求处理方法hello()的返回值修改为“你好,Spring Boot”并保存,查看控制台信息会发现项目能够自动构建和编译,说明项目热部署生效
7.1热部署原理
该原理其实很好说明,就是我们在编辑器上启动项目,然后改动相关的代码,然后编辑器自动触发编译替换掉历史的.class文件后,项目检测到有文件变更后会重启srpring-boot项目。
这里提到了,该插件重启快速的原因:这里对类加载采用了两种类加载器,对于第三方jar包采用base-classloader来加载,对于开发人员自己开发的代码则使用restartClassLoader来进行加载,这使得比停掉服务重启要快的多,因为使用插件只是重启开发人员编写的代码部分。
@Component
public class Devtools implements InitializingBean {
private static final Logger log = LoggerFactory.getLogger(Devtools.class);
@Override
public void afterPropertiesSet() throws Exception {
log.info("guava-jar classLoader: " + DispatcherServlet.class.getClassLoader().toString());
log.info("Devtools ClassLoader: " + this.getClass().getClassLoader().toString());
}
}
引入插件前(未引入插件依赖),只发现一个类加载器base-classloader:
修改接口返回信息,刷新页面,接口返回没有变化
引入插件后(引入插件依赖),同时发现两个类加载器base-classloader和RestartClassLoader:
修改接口返回信息,刷新页面,不用重新重启服务,接口返回自动发生变化
并且发现第三方的jar包的类加载器确实是使用的系统的类加载器,而我们自己写的代码的类加载器为RestartClassLoader,并且每次重启,类加载器的实例都会改变。
7.2排除资源
某些资源在更改后不一定需要触发重新启动。例如,Thymeleaf模板可以就地编辑。默认情况下,改变资源/META-INF/maven,/META-INF/resources,/resources,/static,/public,或/templates不触发重新启动,但确会触发现场重装。如果要自定义这些排除项,则可以使用该spring.devtools.restart.exclude属性。例如,仅排除/static,/public您将设置以下属性:
spring.devtools.restart.exclude=static/**,public/**
8.全局配置文件
全局配置文件能够对一些默认配置值进行修改及自定义配置。
Spring Boot使用一个application.properties或者application.yaml的文件作为全局配置文件
加载优先级:
- 先去项目根目录找config文件夹下找配置文件件
- 再去根目录下找配置文件
- 去resources下找cofnig文件夹下找配置文件
- 去resources下找配置文件
1.SpringBoot会加载全部主配置文件,互补配置。
2.配置文件,都还是项目里面,最终都会被打进jar包里面的。
3.如果同一个目录下,有application.yml也有application.properties,默认先读application.properties。
4.如果同一个配置属性,在多个配置文件都配置了,默认使用第1个读取到的,后面读取的不覆盖前面读取到的。
5.创建SpringBoot项目时,一般的配置文件放置在“项目的resources目录下”。
如果我们的配置文件名字不叫application.properties或者application.yml,可以通过以下参数来指定配置文件的名字,myproject是配置文件名
$ java -jar myproject.jar --spring.config.name=myproject
我们同时也可以指定其他位置的配置文件来生效指定配置文件和默认加载的这些配置文件共同起作用形成互补配置。
java -jar run-0.0.1-SNAPSHOT.jar --spring.config.location=D:/application.properties
Spring Boot 2.4 改进了处理 application.properties 和 application.yml 配置文件的方式,如果是2.4.0之前版本,优先级properties>yaml
但是如果是2.4.0的版本,优先级yaml>properties
如果想继续使用 Spring Boot 2.3 的配置逻辑,也可以通过在 application.properties 或者 application.yml 配置文件中添加以下参数:
spring.config.use-legacy-processing = true
8.1全局配置案例
1.导入依赖
<!--@ConfigurationProperties注解进行配置文件属性值注入时自动提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
2.编写实体对象
@Component//生产当前类实例对象存到IOC容器中
@ConfigurationProperties(prefix = "person")//实现批量注入(set方法)
public class Person {
private int id;
private String name;
private List hobby;
private String[] family;
private Map map;
private Pet pet;
//......省略set和get方法
}
public class Pet {
private int id;
private String name;
//......省略set和get方法
}
2.全局属性配置
(1).properties配置文件方式
server.port=8080
person.id=1
person.name=marry
person.family=丹麦
person.hobby=爱好1,爱好2,爱好3
person.map.k1=v1
person.map.k2=v2
person.pet.id=001
person.pet.name=cat
(2).yml配置文件方式
server:
port: 9090
person:
id: 0001
family: [person1,person2]
name: lala
hobby: // 方式一
play,
read,
sleep
//hobby: [play,read,sleep] // 方式二
map: {k1: v1,k2: v2} //方式一
//map: //方式二
//k1: v1
//k2: v2
pet: {id: 111,name: dog}
3.测试
@RunWith(SpringRunner.class)
@SpringBootTest
class SpringbootApplicationTests {
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
9.属性注入
使用Spring Boot全局配置文件设置属性时:如果配置属性是Spring Boot已有属性,例如服务端口server.port,那么Spring Boot内部会自动扫描并读取这些配置文件中的属性值并覆盖默认属性。
如果配置的属性是用户自定义属性,例如刚刚自定义的Person实体类属性,还必须在程序中注入这些配置属性方可生效。
9.1属性注入常用注解
(1)@Configuration:声明一个类作为配置类
(2)@Bean:声明在方法上,将方法的返回值加入Bean容器
(3)@Value:属性注入
(4)@ConfigurationProperties(prefix = “jdbc”):批量属性注入
(5)@PropertySource(“classpath:/jdbc.properties”)指定外部属性文件。在类上添加
9.2属性注入常用方式
1.引入依赖
<dependency>
<groupId>com.github.drtrang</groupId>
<artifactId>druid-spring-boot2-starter</artifactId>
<version>1.1.10</version>
</dependency>
2.application.properties添加信息
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/springboot
jdbc.username=root
jdbc.password=root
3.方式一:@Value属性值注入
//1.@Value属性值注入
@Configuration
public class JdbcConfiguration {
@Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
public String getDriverClassName() {
return driverClassName;
}
@Bean
public DataSource dataSource(){
DruidDataSource druidDataSource=new DruidDataSource();
druidDataSource.setDriverClassName(driverClassName);
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
return druidDataSource;
}
@Override
public String toString() {
return "JdbcConfiguration{" +
"driverClassName='" + driverClassName + '\'' +
", url='" + url + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
4.方式二:@ConfigurationProperties批量注入
//2.@ConfigurationProperties批量注入
// @Component可替换@Configuration和@EnableConfigurationProperties(JdbcConfiguration.class)
@Configuration
@EnableConfigurationProperties(JdbcConfiguration.class)//使下方注解生效
@ConfigurationProperties(prefix = "jdbc")//这里需要定义出在application文件中定义属性值得前缀信息
public class JdbcConfiguration {
private String driverClassName;
private String url;
private String username;
private String password;
@Bean
public DataSource dataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driverClassName);
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
return druidDataSource;
}
@Override
public String toString() {
return "JdbcConfiguration{" +
"driverClassName='" + driverClassName + '\'' +
", url='" + url + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public void setUrl(String url) {
this.url = url;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}
测试类
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
@Autowired
private JdbcConfiguration jdbcConfiguration;
@Autowired
private DataSource dataSource;
@Test
public void test1() {
System.out.println(jdbcConfiguration);
System.out.println(dataSource);
}
9.2第三方配置注入
除了@ConfigurationProperties用于注释类之外,您还可以在公共@Bean方法上使用它。当要将属性绑定到控件之外的第三方组件时,这样做特别有用。
创建一个其他组件类
@Data
public class AnotherComponent {
private boolean enabled;
private InetAddress remoteAddress;
}
创建MyService
@Configuration
public class MyService {
@ConfigurationProperties("another")
@Bean
public AnotherComponent anotherComponent(){
return new AnotherComponent();
}
}
配置文件
another.enabled=true
another.remoteAddress=192.168.10.11
测试类
@Autowired
private AnotherComponent anotherComponent;
@Test
public void myServiceTest() {
System.out.println(anotherComponent);
}
9.3松散绑定
Spring Boot使用一些宽松的规则将环境属性绑定到@ConfigurationProperties的bean,因此环境属性名和bean属性名之间不需要完全匹配
1.定义绑定对象
@Data
@Component
@ConfigurationProperties("acme.my-person.person")
public class OwnerProperties {
private String firstName;
}
2.配置文件定义属性
acme:
my-person:
person:
first-name: 泰森
10.SpringBoot日志框架
常见的日志框架有很多,比如:JCL、SLF4J、Jboss-logging、jUL、log4j、log4j2、logback等等,我们该如何选择呢?
通常情况下,日志是由一个抽象层+实现层的组合来搭建的。
日志-抽象层
JCL(Jakarta Commons Logging)、SLF4J(Simple LoggingFacade for Java)、jboss-logging
日志-实现层
jul(java.util.logging)、log4j、logback、log4j2
Spring 框架选择使用了 JCL 作为默认日志输出。而 Spring Boot 默认选择了 SLF4J+LogBack
10.1使用案例
Logger logger = LoggerFactory.getLogger(this.getClass());
@Test
public void testLog() {
logger.trace("Trace 日志...");
logger.debug("Debug 日志...");
logger.info("Info 日志...");
logger.warn("Warn 日志...");
logger.error("Error 日志...");
}
已知日志级别从小到大为 trace < debug < info < warn < error . 运行得到输出如下。由此可见 Spring Boot 默认日志级别为 INFO.
从上面的日志结合 Logback 日志格式可以知道 Spring Boot 默认日志格式是
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
# %d{yyyy-MM-dd HH:mm:ss.SSS} 时间
# %thread 线程名称
# %-5level 日志级别从左显示5个字符宽度
# %logger{50} 类名
# %msg%n 日志信息加换行
10.2自定义日志输出
# 日志配置
# 指定具体包的日志级别
logging.level.com.lagou=debug
# 控制台和日志文件输出格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %
logger{50} - %msg%n
# 日志输出路径,默认文件
spring.loglogging.file.path=spring.log#logging.file.name=log.log
关于日志的输出路径,可以使用 logging.file 或者 logging.path 进行定义
10.3替换日志框架
因为 Log4j 日志框架已经年久失修,原作者都觉得写的不好,所以下面演示替换日志框架为 Log4j2 的方式。根据官网我们 Log4j2 与 logging 需要二选一,因此修改 pom如下
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>