SpringBoot知识概括
Spring Boot简介
Spring Boot 简介:
- 简化Spring应用开发的一个框架;
- 整个Spring技术栈的一个大整合;
- J2EE开发的一站式解决方案;
微服务:
- 微服务:架构风格(服务微化)
- 一个应用应该是一组小型服务;可以通过HTTP的方式进行互通;
- 对比:
①单体应用:ALL IN ONE
②微服务:每一个功能元素最终都是一个可独立替换和独立升级的软件单元;
Spring Boot入门:
- 一个功能:浏览器发送hello请求,服务器接受请求并处理,响应Hello World字符串;
- 步骤:
①创建一个maven工程;(jar)
②导入spring boot相关的依赖
③编写一个主程序;启动Spring Boot应用
④编写相关的Controller、Service
⑤运行主程序测试
⑥简化部署:将这个应用打成jar包,直接使用java -jar的命令进行执行。
----------------------------------pom.xml jar包配置----------------------------------
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
----------------------------------springboot主程序----------------------------------
/**
- @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
*/
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
// Spring应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
-------------------------Controller层-------------------------------------------
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "Hello World!";
}
}
----------------------------pom.xml 插件配置----------------------------------------
/**
- 这个插件,可以将应用打包成一个可执行的jar包
*/
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
springboot研究:
POM文件中的plugin:
①Spring Boot的Maven插件(Spring Boot Maven plugin)能够以Maven的方式为应用提供Spring Boot的支持,即为Spring Boot应用提供了执行Maven操作的可能。POM文件中的父项目:
①spring-boot-dependencies
来真正管理Spring Boot应用里面的所有依赖版本:Spring Boot的版本仲裁中心。
②以后我们导入依赖默认是不需要写版本;(没有在dependencies里面管理的依赖自然需要声明版本号)
----------------------------------pom.xml parent依赖----------------------------------
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
-------------------pom.xml parent依赖的父项目是----------------------------
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
POM文件中的启动器:
①Spring Boot将所有的功能场景都抽取出来,做成一个个的starters(启动器)。
②只需要在项目里面引入这些starter相关场景的所有依赖都会导入进来。要用什么功能就导入什么场景的启动器
③其中spring-boot-starter-web依赖spring-boot-starter
,spring-boot-starter是Spring Boot的核心启动器,包含了自动配置、日志和YAML。
<1>当不使用web依赖时则会导入这个核心启动器依赖。
---spring-boot-starter:spring-boot场景启动器,帮我们导入了web模块正常运行所依赖的组件。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
------Spring Boot的核心启动器依赖------
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.5.RELEASE</version>
<scope>compile</scope>
</dependency>
主程序类、主入口类:
①@SpringBootApplication:
Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用。
②@SpringBootConfiguration:
Spring Boot的配置类,标注在某个类上,表示这是一个Spring Boot的配置类。
③@Configuration:
配置类上来标注这个注解。
<1>配置类等于配置文件
,配置类也是容器中的一个组件@Component。
④@EnableAutoConfiguration:
开启自动配置功能,以前我们需要配置的东西,Spring Boot帮我们自动配置。@EnableAutoConfiguration告诉SpringBoot开启自动配置功能,这样自动配置才能生效;
⑤@AutoConfigurationPackage:
自动配置包
⑥@Import:
给容器中导入一个组件
<1>@Import(AutoConfigurationPackages.Registrar.class):
Spring的底层注解@Import给容器中导入的组件为AutoConfigurationPackages.Registrar.class。
1、将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器;
<2>@Import(EnableAutoConfigurationImportSelector.class):
给容器中导入组件。
1、EnableAutoConfigurationImportSelector:将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中。
----------------------------------主程序类----------------------------------
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
// Spring应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
-------------------------@SpringBootApplication注解----------------------------------
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
-------------------------@SpringBootConfiguration注解----------------------------------
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
-------------------------@Configuration注解----------------------------------
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
}
-------------------------@EnableAutoConfiguration注解----------------------------------
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
-------------------------@AutoConfigurationPackage 注解----------------------------------
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}
- 总结:
①会给容器中导入非常多的自动配置类(xxxAutoConfiguration)
:就是给容器中导入这个场景需要的所有组件,并配置好这些组件。
<1>有了自动配置类,免去了我们手动编写配置注入功能组件等的工作。
②SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader);
<1>SpringBoot在启动的时候从类路径下的META-INF/spring.factories
中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作,以前我们需要自己配置的东西,自动配置类都帮我们。
③J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfigure-1.5.9.RELEASE.jar。
快速创建Spring Boot项目:
- IDEA:使用 Spring Initializer快速创建项目
①IDE都支持使用Spring的项目创建向导快速创建一个Spring Boot项目。
②选择我们需要的模块,向导会联网创建Spring Boot项目。
③默认生成的Spring Boot项目。
一、主程序已经生成好了,我们只需要我们自己的逻辑
二、resources文件夹中目录结构:
<1>static:保存所有的静态资源,如js,css,images。
<2>templates:保存所有的模板页面。(Spring Boot默认jar包使用嵌入式的Tomcat,默认不支持JSP页面)
但是可以使用模板引擎(freemarker、thymeleaf)。
<3>application.properties:Spring Boot应用的配置文件,可以修改一些默认设置。
- STS使用 Spring Starter Project快速创建项目
配置文件
配置文件:
- SpringBoot使用一个全局的配置文件,配置文件名是固定的:
①application.properties
②application.yml
- 配置文件的作用:修改SpringBoot自动配置的默认值,SpringBoot在底层都给我们自动配置好。
YAML(YAML Ain't Markup Language)
两个解释:
①YAML A Markup Language:是一个标记语言
②YAML isn’t Markup Language:不是一个标记语言;- 标记语言:以前的配置文件;大多都使用的是 "xxxx.xml"文件,现在使用YAML,YAML,
以数据为中心
,比json、xml等更适合做配置文件。
①配置例子
-----yaml------
server:
port: 8081
-----xml------
<server>
<port>8081</port>
</server>
YAML语法:
- 基本语法:
k:(空格)v:表示一对键值对(空格必须有)
。
①以空格的缩进来控制层级关系,只要是左对齐的一列数据,都是同一个层级的。
②属性和值也是大小写敏感。
server:
port: 8081
path: /hello
- 值的写法:
一、字面量:普通的值(数字,字符串,布尔)
k: v:字面直接来写。
<1>字符串默认不用加上单引号或者双引号。
"":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi":输出;zhangsan 换行 lisi
'':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi
总结:转义是将具体意思往反方向转换,例如转义字符本身表示换行,转义的话就是\n,不转义就是换行。
二、对象、Map(属性和值)(键值对):
k: v:在下一行来写对象的属性和值的关系,注意缩进。
对象还是k: v的方式
friends:
lastName: zhangsan
age: 20
行内写法:
friends: {lastName: zhangsan,age: 18}
三、数组(List、Set):
用- 值表示数组中的一个元素:
pets:
- cat
- dog
- pig
行内写法:
pets: [cat,dog,pig]
配置文件值注入:
- 配置文件:
person:
lastName: hello
age: 18
boss: false
birth: 2017/12/12
maps: {
k1: v1,k2: 12}
lists:
- lisi
- zhaoliu
dog:
name: 小狗
age: 12
- javaBean:
①解释:将配置文件中配置的每一个属性的值映射到这个组件中
②@ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定。
<1>prefix = “person”:配置文件中哪个下面的所有属性进行一一映射
③注意:只有这个组件是容器中的组件,才能用容器提供的@ConfigurationProperties功能。
④配置文件注入值数据校验使用Validated注解在类上面,使用@Email等等注解在字段上面。
⑤使用@ConfigurationProperties和@Bean注解在配置类的Bean定义方法上:将方法返回的对象定义为一个Bean,并使用配置文件中相应的属性初始化该Bean的属性。
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
@Email
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
- 导入配置文件处理器,以后编写配置就有提示了。
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
@Value获取值和@ConfigurationProperties获取值比较:
- 配置文件yml还是properties他们都能获取到值;
- 如果我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
- 如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
@PropertySource、@ImportResource、@Bean:
- @PropertySource:加载指定的配置文件。
①通过@PropertySource注解将properties配置文件中的值存储到Spring的 Environment中,Environment接口提供方法去读取配置文件中的值,参数是properties文件中定义的key值。
②通过@value({SPEL})里编写spel表达式从环境变量、配置文件获取值
@PropertySource(value = {"classpath:person.properties"})
@Component
public class Person {
@Value("${person.last-name}")
private String lastName;
@Value("#{11*2}")
private Integer age;
@Value("true")
private Boolean boss;
@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效。
①Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别。
②想让Spring的配置文件生效加载进来,使用@ImportResource标注在一个配置类上。
//导入Spring的配置文件让其生效
@ImportResource(locations = {"classpath:beans.xml"})
//Spring的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloService" class="com.atguigu.springboot.service.HelloService"></bean>
</beans>
SpringBoot推荐给容器中添加组件的方式:推荐使用全注解的方式
①配置类@Configuration
②使用@Bean
给容器中添加组件
/**
* @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件
*/
@Configuration
public class MyAppConfig {
//将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
@Bean
public HelloService helloService02(){
System.out.println("配置类@Bean给容器中添加组件了...");
return new HelloService();
}
}
配置文件占位符:
- 随机数
- 占位符获取之前配置的值,
如果没有可以是用:指定默认值
${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}
person.last-name=张三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15
Profile:
多Profile文件:
①我们在主配置文件编写的时候,文件名可以是application-{profile}.properties/yml
②默认使用application.properties的配置;
③使用profile还有个明显的用处——可以抽取application.yml中的配置信息到其他文件
。如当我们的项目越来越大时,项目配置信息太多,application.yml配置文件会比较大,这时我们可以通过定义profile,将一些配置信息从application.yml中抽取到一个单独的文件中,如建立:
<1>application-devFtp.yml 只存放开发环境ftp相关的配置信息
<2>application-devRedis.yml 只存放开发环境redis相关的配置信息
<3>application-testFtp.yml 只存放测试环境ftp相关的配置信息
<4>application-testRedis.yml 只存放测试环境redis相关的配置信息
④然后在application.yml中切换开发环境,配置spring.profiles.active=dev, devFtp,devRedis
来引入dev、devFtp、devRedis的配置即可。
⑤切换测试环境,配置spring.profiles.active=test, testFtp,testRedis 来引入test、testFtp、testRedis的配置即可。
⑥默认配置:如果没有指定profiles,则默认配置生效。
yml还支持多文档块方式:
①注意:文档块以---分隔
server:
port: 8081
spring:
profiles:
active: prod
---
server:
port: 8083
spring:
profiles: dev
---
server:
port: 8084
spring:
profiles: prod #指定属于哪个环境
- 激活指定profile
①在配置文件中指定 spring.profiles.active=dev
②命令行:
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
<1>可以直接在测试的时候,配置传入命令行参数
③虚拟机参数:
-Dspring.profiles.active=dev - 总结:
①appliaction-dev.yml,appliaction-test.yml,appliaction-prd.yml等等环境这些配置文件在每个module中都需要,除了工具module除外。
②appliaction.yml一般放在web启动类的module中,再通过指定spring.profiles.active来整合多个文件。
③每个module的appliaction.yml最终会整合在一起。
④例如在appliaction.yml中指定spring.profiles.active为dev(本web模块的dev环境文件)、devFtp(Ftp模块的dev环境文件)、devRedis(Redis模块的dev环境文件)。
⑤链接:多模块配置文件问题
⑥使用maven的时候一个可运行的springboot项目中只能有一个application.properties。其他模块配置文件一定要以application-XX的形式命名,不然后续配置无法识别。若想以其他文件名或其他文件类型的话需要配置@PropertySource注解。
⑦多模块思路:写测试代码时要考虑测试代码是否是通用的,是的话写在web模块。
配置文件加载位置:
- springboot启动会扫描以下位置的application.properties或者application.yml文件作为Spring
boot的默认配置文件
①jar包同级目录下的/config目录–file:./config/
②jar包同级目录–file:./
③classpath里的/config目录–classpath:/config/
④classpath 同级目录–classpath:/
- 优先级由高到底,
高优先级的配置会覆盖低优先级的配置
,SpringBoot会从这四个位置全部加载主配置文件,互补配置
,因此最终底层会互补成一个配置文件
。 我们还可以通过spring.config.location来改变默认的配置文件位置
①项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置。
<1>java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
外部配置加载顺序:
-
SpringBoot也可以从以下位置加载配置; 优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置。
-
规则为:
①由jar包外向jar包内进行寻找
②优先加载带profile
③再来加载不带profile -
具体:
①命令行参数:所有的配置都可以在命令行上进行指定
<1>java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
<2>多个配置用空格分开; --配置项=值
②来自java:comp/env的JNDI属性
③Java系统属性(System.getProperties())
④操作系统环境变量
⑤RandomValuePropertySource配置的random.*属性值
⑥jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
⑦jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
⑧jar包外部的application.properties或application.yml(不带spring.profile)配置文件
⑨jar包内部的application.properties或application.yml(不带spring.profile)配置文件
⑩@Configuration注解类上的@PropertySource
⑪通过SpringApplication.setDefaultProperties指定的默认属性 -
所有支持的配置加载来源:参考官方文档
自动配置原理:
- SpringBoot启动的时候加载主配置类,开启了自动配置功能
@EnableAutoConfiguration
@EnableAutoConfiguration 作用:
①利用EnableAutoConfigurationImportSelector给容器中导入一些组件。
②可以查看selectImports()方法的内容:
一、扫描
<1>@Import(AutoConfigurationPackages.Registrar.class):
将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器;
<2>扫描所有jar包类路径下的META-INF/spring.factories文件,
把扫描到的这些文件的内容包装成properties对象
二、获取候选的配置
<1>List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)
<2>从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中
SpringFactoriesLoader.loadFactoryNames()
spring.factories 文件:
①每一个这样的xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中,用他们来做自动配置。
②每一个自动配置类进行自动配置功能。
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
- 以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释:
①根据当前不同的条件判断,决定这个配置类是否生效?
<1>一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
②所有在配置文件中能配置的属性都是在xxxxProperties类中封装者中,配置文件能配置什么就可以参照某个功能对应的这个属性类。
//表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件
@Configuration
//启动指定类的ConfigurationProperties功能;将配置文件中对应的值和
//HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中
@EnableConfigurationProperties(HttpEncodingProperties.class)
//Spring底层@Conditional注解(Spring注解版),根据不同的条件,
//如果满足指定的条件,整个配置类里面的配置就会生效;
//判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnWebApplication
//判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
@ConditionalOnClass(CharacterEncodingFilter.class)
//判断配置文件中是否存在某个配置spring.http.encoding.enabled;如果不存在,判断也是成立的
@ConditionalOnProperty(prefix = "spring.http.encoding",
value = "enabled", matchIfMissing = true)
//即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
public class HttpEncodingAutoConfiguration {
//他已经和SpringBoot的配置文件映射了
private final HttpEncodingProperties properties;
//只有一个有参构造器的情况下,参数的值就会从容器中拿
public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
this.properties = properties;
}
@Bean //给容器中添加一个组件,这个组件的某些值需要从properties中获取
@ConditionalOnMissingBean(CharacterEncodingFilter.class) //判断容器没有这个组件?
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
return filter;
}
//从配置文件中获取指定的值和bean的属性进行绑定
@ConfigurationProperties(prefix = "spring.http.encoding")
public class HttpEncodingProperties {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
...
}
- 精髓:
①SpringBoot启动会加载大量的自动配置类。
②我们看我们需要的功能有没有SpringBoot默认写好的自动配置类。
③我们再来看这个自动配置类中到底配置了哪些组件(只要我们要用的组件有,我们就不需要再来配置了)
④给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值。
⑤注意:
<1>xxxxAutoConfigurartion:自动配置类,给容器中添加组件。
<2>xxxxProperties:封装配置文件中相关属性。
@Conditional派生注解(Spring注解版原生的@Conditional作用):
- 作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效。
@Conditional扩展注解 | 作用(判断是否满足当前指定条件) |
---|---|
@ConditionalOnJava | 系统的java版本是否符合要求 |
@ConditionalOnBean | 容器中存在指定Bean |
@ConditionalOnMissingBean | 容器中不存在指定Bean |
@ConditionalOnExpression | 满足SpEL表达式指定 |
@ConditionalOnClass | 系统中有指定的类 |
@ConditionalOnMissingClass | 系统中没有指定的类 |
@ConditionalOnSingleCandidate | 容器中只有一个指定的Bean,或者这个Bean是首选Bean |
@ConditionalOnProperty | 系统中指定的属性是否有指定的值 |
@ConditionalOnResource | 类路径下是否存在指定资源文件 |
@ConditionalOnWebApplication | 当前是web环境 |
@ConditionalOnNotWebApplication | 当前不是web环境 |
@ConditionalOnJndi | JNDI存在指定项 |
- 自动配置类必须在一定的条件下才能生效,
我们怎么知道哪些自动配置类生效?
①我们可以通过启用debug=true属性,来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效。
=========================
AUTO-CONFIGURATION REPORT
=========================
Positive matches:(自动配置类启用的)
-----------------
DispatcherServletAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)
Negative matches:(没有启动,没有匹配成功的自动配置类)
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)
AopAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition)
日志
日志框架:
- 开发一个大型系统:
①System.out.println(“”);将关键数据打印在控制台;去掉?写在一个文件?
②框架来记录系统的一些运行时信息;日志框架 ; zhanglogging.jar;
③高大上的几个功能?异步模式?自动归档?xxxx? zhanglogging-good.jar?
④将以前框架卸下来?换上新的框架,重新修改之前相关的API;zhanglogging-prefect.jar;
⑤JDBC—数据库驱动; - 办法:
①写了一个统一的接口层;日志门面(日志的一个抽象层);logging-abstract.jar;
②给项目中导入具体的日志实现就行了;我们之前的日志框架都是实现的抽象层;
市面上的日志框架;
- JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j…
①左边选一个门面(抽象层)、右边来选一个实现。
日志门面 (日志的抽象层) | 日志实现 |
---|---|
Log4j JUL(java.util.logging) Log4j2 Logback |
- SpringBoot:底层是Spring框架,Spring框架默认是用JCL。
SpringBoot选用:
①日志门面: SLF4J
②日志实现:Logback
如何在系统中使用SLF4j:
-
以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法。
-
给系统里面导入slf4j的jar和 logback的实现jar
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
- 每一个日志的实现框架都有自己的配置文件。使用slf4j以后,
配置文件还是做成日志实现框架自己本身的配置文件
。
①图示:
遗留问题:
- (slf4j+logback):Spring(commons-logging)、Hibernate(jboss-logging)、MyBatis、xxxx
- 统一日志记录,
如何让系统中所有的日志都统一到slf4j:
①将系统中其他日志框架先排除出去。
②用中间包来替换原有的日志框架。
③我们导入slf4j其他的实现。
SpringBoot日志关系:`
SpringBoot依赖spring-boot-starter,spring-boot-starter依赖spring-boot-starter-logging,并使用它来做日志功能。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
- 底层依赖关系:
- 总结:
①SpringBoot底层也是使用slf4j+logback的方式进行日志记录
②SpringBoot也把其他的日志都替换成了slf4j;
③中间替换包
,例如jul-to-slf4j。
④SpringBoot能自动适配所有的日志,而且底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要把这个框架依赖的默认日志框架排除掉即可。
<1>Spring框架用的是commons-logging,如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
springBoot日志使用:
- SpringBoot默认帮我们配置好了日志。
//记录器
Logger logger = LoggerFactory.getLogger(getClass());
@Test
public void contextLoads() {
//System.out.println();
//日志的级别;
//由低到高 trace<debug<info<warn<error
//可以调整输出的日志级别;日志就只会在这个级别以以后的高级别生效
logger.trace("这是trace日志...");
logger.debug("这是debug日志...");
//SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;root级别
logger.info("这是info日志...");
logger.warn("这是warn日志...");
logger.error("这是error日志...");
}
日志输出格式:
%d表示日期时间,
%thread表示线程名,
%-5level:级别从左显示5个字符宽度
%logger{50} 表示logger名字最长50个字符,否则按照句点分割。
%msg:日志消息,
%n是换行符
总结:%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
- SpringBoot修改日志的默认配置:
# 自定义logger
logging.level.com.atguigu=trace
# 不指定路径在当前项目下生成springboot.log日志
# 可以指定完整的路径;
#logging.file=G:/springboot.log
# 在当前磁盘的根路径下创建spring文件夹和里面的log文件夹;使用 spring.log 作为默认文件
logging.path=/spring/log
# 在控制台输出的日志的格式
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
# 指定文件中日志输出的格式
logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} ==== %msg%n
logging.file | logging.path | Example | Description |
---|---|---|---|
(none) | (none) | 只在控制台输出 | |
指定文件名 | (none) | my.log | 输出日志到my.log文件 |
(none) | 指定目录 | /var/log | 输出到指定目录的 spring.log 文件中 |
指定配置:给类路径下放上每个日志框架自己的配置文件即可,SpringBoot就不使用他默认配置的了。
①logback.xml:直接就被日志框架识别了。
②logback-spring.xml:日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot的高级Profile功能。
<1>如果使用logback.xml作为日志配置文件,还要使用profile功能,会有以下错误:no applicable action for [springProfile]
Logging System | Customization |
---|---|
Logback | logback-spring.xml , logback-spring.groovy , logback.xml or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
<springProfile name="staging">
<!-- configuration to be enabled when the "staging" profile is active -->
可以指定某段配置只在某个环境下生效
</springProfile>
例如:
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<springProfile name="dev">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%n</pattern>
</springProfile>
<springProfile name="!dev">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%n</pattern>
</springProfile>
</layout>
</appender>
切换日志框架:
- 可以按照slf4j的日志适配图,进行相关的切换。
- 例如:slf4j+log4j的方式。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
//排除底层的log4j替换到slf4j框架以及logback实现框架
<exclusions>
<exclusion>
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
<exclusion>
<artifactId>log4j-over-slf4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
//加入log4j-slf4j绑定jar包及log4j实现jar包
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
- 例如:slf4j+log4j2的方式。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
//直接去掉starter-logging配置器
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
//使用starter-log4j2配置器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
Web开发
Web开发简介:
- 使用SpringBoot
- 创建SpringBoot应用,选中我们需要的模块
- SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来
- 自己编写业务代码
springboot的jar包目录结构分析:
SpringBoot提供的bootstrap的类是放到包的最外面,比如上面的org.springframework.boot.loader。
应用程序的代码则是需要放到BOOT-INF/classes目录下面;然后应用程序依赖的其他的jar包文件需要放到BOOT-INF/lib目录下。
- 当这个jar作为standardalone的程序运行时(没有放到container),SpringBoot会在生成的META-INF/MANIFEST.MF里面将Main-Class设置成org.springframework.boot.loader.JarLauncher,JarLauncher类会创建一个spring自己的ClassLoader:LaunchedURLClassLoader, 这个classloader
会就能通过URL来加载上面BOOT-INF/lib里面所依赖的包,并且通过反射Manifest里面的Start-Class里面定义的类,然后invoke这个类里面的main方法。
example.jar
|
+-META-INF
| +-MANIFEST.MF
+-org
| +-springframework
| +-boot
| +-loader
| +-<spring boot loader classes>
+-BOOT-INF
+-classes
| +-mycompany
| +-project
| +-YourClasses.class
+-lib
+-dependency1.jar
+-dependency2.jar
静态资源
SpringBoot对静态资源的映射规则:
所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找资源。
①webjars:以jar包的方式引入静态资源;
②localhost:8080/webjars/jquery/3.3.1/jquery.js
"/**" 访问当前项目的任何资源,都去(静态资源的文件夹)找映射
①localhost:8080/abc === 去静态资源文件夹里面找abc欢迎页; 静态资源文件夹下的所有index.html页面;被"/**"映射
①localhost:8080/ 找index页面所有的 **/favicon.ico 都是在静态资源文件下找;
------------------------------静态资源配置类------------------------
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties implements ResourceLoaderAware {
//可以设置和静态资源有关的参数,缓存时间等
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Integer cachePeriod = this.resourceProperties.getCachePeriod();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(
registry.addResourceHandler("/webjars/**")
.addResourceLocations(
"classpath:/META-INF/resources/webjars/")
.setCachePeriod(cachePeriod));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
//静态资源文件夹映射
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(
registry.addResourceHandler(staticPathPattern)
.addResourceLocations(
this.resourceProperties.getStaticLocations())
.setCachePeriod(cachePeriod));
}
}
//配置欢迎页映射
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(
ResourceProperties resourceProperties) {
return new WelcomePageHandlerMapping(resourceProperties.getWelcomePage(),
this.mvcProperties.getStaticPathPattern());
}
//配置喜欢的图标
@Configuration
@ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)
public static class FaviconConfiguration {
private final ResourceProperties resourceProperties;
public FaviconConfiguration(ResourceProperties resourceProperties) {
this.resourceProperties = resourceProperties;
}
@Bean
public SimpleUrlHandlerMapping faviconHandlerMapping() {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
//所有 **/favicon.ico
mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",
faviconRequestHandler()));
return mapping;
}
@Bean
public ResourceHttpRequestHandler faviconRequestHandler() {
ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
requestHandler
.setLocations(this.resourceProperties.getFaviconLocations());
return requestHandler;
}
}
------------------------------jquery-webjar------------------------
<!--引入jquery-webjar-->在访问的时候只需要写webjars下面资源的名称即可
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
------------------------------静态资源映射------------------------
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
"/":当前项目的根路径
模版引擎
模板引擎:
- JSP、Velocity、Freemarker、Thymeleaf
- SpringBoot推荐的Thymeleaf,语法更简单,功能更强大。
thymeleaf的使用:
- 引入thymeleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
2.1.6
</dependency>
切换thymeleaf版本
<properties>
<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
<!-- 布局功能的支持程序 thymeleaf3主程序 layout2以上版本 -->
<!-- thymeleaf2 layout1-->
<thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
</properties>
- Thymeleaf自动配置类
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING = Charset.forName("UTF-8");
private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html");
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
- 使用方法:只要我们把HTML页面放在classpath:/templates/,thymeleaf就能自动渲染。
- 具体使用:
①导入thymeleaf的名称空间
②使用thymeleaf语法
----------------------名称空间-----------------
<html lang="en" xmlns:th="http://www.thymeleaf.org">
----------------------具体语法-----------------
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>成功!</h1>
<!--th:text 将div里面的文本内容设置为 -->
<div th:text="${hello}">这是显示欢迎信息</div>
</body>
</html>
thymeleaf语法规则:
th:text
:改变当前元素里面的文本内容。th
:任意html属性,来替换原生属性的值。
- 表达式:
Simple expressions:(表达式语法)
Variable Expressions: ${...}:获取变量值;OGNL;
1)、获取对象的属性、调用方法
2)、使用内置的基本对象:
#ctx : the context object.
#vars: the context variables.
#locale : the context locale.
#request : (only in Web Contexts) the HttpServletRequest object.
#response : (only in Web Contexts) the HttpServletResponse object.
#session : (only in Web Contexts) the HttpSession object.
#servletContext : (only in Web Contexts) the ServletContext object.
${session.foo}
3)、内置的一些工具对象:
#execInfo : information about the template being processed.
#messages : methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{…} syntax.
#uris : methods for escaping parts of URLs/URIs
#conversions : methods for executing the configured conversion service (if any).
#dates : methods for java.util.Date objects: formatting, component extraction, etc.
#calendars : analogous to #dates , but for java.util.Calendar objects.
#numbers : methods for formatting numeric objects.
#strings : methods for String objects: contains, startsWith, prepending/appending, etc.
#objects : methods for objects in general.
#bools : methods for boolean evaluation.
#arrays : methods for arrays.
#lists : methods for lists.
#sets : methods for sets.
#maps : methods for maps.
#aggregates : methods for creating aggregates on arrays or collections.
#ids : methods for dealing with id attributes that might be repeated (for example, as a result of an iteration).
Selection Variable Expressions: *{...}:选择表达式:和${}在功能上是一样;
补充:配合 th:object="${session.user}:
<div th:object="${session.user}">
<p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
<p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
<p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div>
Message Expressions: #{...}:获取国际化内容
Link URL Expressions: @{...}:定义URL;
@{/order/process(execId=${execId},execType='FAST')}
Fragment Expressions: ~{...}:片段引用表达式
<div th:insert="~{commons :: main}">...</div>
Literals(字面量)
Text literals: 'one text' , 'Another one!' ,…
Number literals: 0 , 34 , 3.0 , 12.3 ,…
Boolean literals: true , false
Null literal: null
Literal tokens: one , sometext , main ,…
Text operations:(文本操作)
String concatenation: +
Literal substitutions: |The name is ${name}|
Arithmetic operations:(数学运算)
Binary operators: + , - , * , / , %
Minus sign (unary operator): -
Boolean operations:(布尔运算)
Binary operators: and , or
Boolean negation (unary operator): ! , not
Comparisons and equality:(比较运算)
Comparators: > , < , >= , <= ( gt , lt , ge , le )
Equality operators: == , != ( eq , ne )
Conditional operators:条件运算(三元运算符)
If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)
Special tokens:
No-Operation: _
SpringBoot应用配置常用相关视图解析器:
SpringBoot使用JSP:
SpringBoot在自动装配的时候默认就已经将JSP的视图解析器InternalResourceViewResolver
装配。所以我们只需要进行配置使用即可。
-----------------------外置tomcat模式------------
第一步:创建自定义webapp目录
第二步:将此文件夹配置成项目的WEB模块
第三步:导入JSP相关依赖
<!-- 部署tomcat,排除冲突-->
<!-- 也可以在spring-boot-starter-web中使用exclusion排除这个依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- servlet依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<