1.springboot简介
springboot是一个简化spring的一个开发应用框架,是整一个sping技术栈的一个集合。J2EE开发的一站式解决方案。
文档可以去官方网站查看。
spring官方网站:https://spring.io/projects/spring-boot
springboot官方文档:https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/htmlsingle/#boot-features-external-config
2.Spring Boot HelloWorld
浏览器访问hello,服务器相应请求并返回Hello World字符。
1.导入相关的依赖
<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>
2.编写主程序,启动springboot应用
/**
* @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
*/
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
// Spring应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
3.编写controller
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "Hello World!";
}
}
springboot是一个非常简化的的部署应用框架。只需要再pom文件中导入打包插件
<!‐‐ 这个插件,可以将应用打包成一个可执行的jar包;‐‐>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐maven‐plugin</artifactId>
</plugin>
</plugins>
</build>
4.springboot hello word的内部实现
4.1 pom文件
每一个springboot应用程序都会有这个spring‐boot‐starter‐parent资源。它的父级资源是管理整个springboot资源版本依赖,起到一个版本仲裁的作用。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
他的父项目是下面这个资源依赖:真正管理Spring Boot应用里面的所有依赖版本;
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath>../../spring‐boot‐dependencies</relativePath>
</parent>
启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐web</artifactId>
</dependency>
spring-boot-starter:spring-boot场景启动器;帮我们导入了web模块正常运行所依赖的组件;
Spring Boot将所有的功能场景都抽取出来,做成一个个的starters(启动器),只需要在项目里面引入这些starter
相关场景的所有依赖都会导入进来。要用什么功能就导入什么场景的启动器
4.2 springboot主启动类
/**
* @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
*/
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
// Spring应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
@SpringBootApplication:是配置某一个类,说明这个类是这个应用的主配置类。运行该类里面的main方法
@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:Spring Boot的配置类;
标注在某个类上,表示这是一个Spring Boot的配置类;
@Configuration:配置类上来标注这个注解;
配置类 ----- 配置文件;配置类也是容器中的一个组件;@Component@EnableAutoConfiguration:开启自动配置功能;
使用spring的时候,是需要配置很多的配置文件,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉SpringBoot开启自
动配置功能;这样自动配置才能生效;
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
@AutoConfigurationPackage:自动配置包
@Import(AutoConfigurationPackages.Registrar.class):
Spring的底层注解@Import,给容器中导入一个组件;导入的组件由 AutoConfigurationPackages.Registrar.class;
将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器;
@Import(EnableAutoConfigurationImportSelector.class);有了自动配置类的操作,就可以省去手动配置的麻烦
EnableAutoConfigurationImportSelector:导入哪些组件的选择器;将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中;会给容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件,并配置好这些组件;
J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfigure-1.5.9.RELEASE.jar;
3.springboot 配置文件
springboot的全局配置文件有两种
- application.properties
- application.yml
1. YAML语法:
1、基本语法
k:(空格)v:表示一对键值对(空格必须有);以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的server: port: 8081 path: /hello
属性和值也是大小写敏感;
4.将配置文件中的值注入到类中
- 使用@ConfigurationProperties才能将配置文件中的有的属性映射到spring容器中
- 在JavaBean中必须配置@Component 注解将类注入到spring的容器中
配置文件
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将本类中的所有属性和配置文件中相关的配置进行绑定; * prefix = "person":配置文件中哪个下面的所有属性进行一一映射 * * 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能; * */ @Component @ConfigurationProperties(prefix = "person") public class Person { private String lastName; private Integer age; private Boolean boss; private Date birth; private Map<String,Object> maps; private List<Object> lists; private Dog dog;
可以导入配置文件对应javabean的属性提示的功能。这样的话就可以在配置文件中获取提示信息
<!‐‐导入配置文件处理器,配置文件进行绑定就会有提示‐‐> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring‐boot‐configuration‐processor</artifactId> <optional>true</optional> </dependency>
@Value获取值和@ConfigurationProperties获取值比较 @ConfigurationProperties @Value 功能 批量注入配置文件中的属性 一个个指定 松散绑定(松散语法) 支持 不支持 SpEL 不支持 支持 JSR303数据校验 支持 不支持 复杂数据类型封装 支持 不支持 总结:
如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
5.配置文件注入值数据校验
这个数据校验是对上面总结表格的实际数据
@Component @ConfigurationProperties(prefix = "person") @Validated public class Person { /** * <bean class="Person"> * <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/# {SpEL}"></property> * <bean/> */ //lastName必须是邮箱格式 @Email //@Value("${person.last‐name}") private String lastName; //@Value("#{11*2}") private Integer age; //@Value("true") private Boolean boss; private Date birth; private Map<String,Object> maps; private List<Object> lists; private Dog dog;
6.@PropertySource&@ImportResource&@Bean
6.1@PropertySource:加载指定的配置文件;
是获取资源文件夹中的不是全局配置的配置文件
/** * 将配置文件中配置的每一个属性的值,映射到这个组件中 * @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定; * prefix = "person":配置文件中哪个下面的所有属性进行一一映射 * * 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能; * @ConfigurationProperties(prefix = "person")默认从全局配置文件中获取值; * */ @PropertySource(value = {"classpath:person.properties"}) @Component @ConfigurationProperties(prefix = "person") public class Person { private String lastName; private Integer age; private Boolean boss;
6.2 @ImportResource
主要的作用是将额外配置的xml文件注入到容器
导入Spring的配置文件,让配置文件里面的内容生效;Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上
@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>
6.3 使用@Configuration 全注解的来实现加载资源文件(springboot推荐使用全注解的方式)
需要一个组件的时候,就可以使用这个方法来进行对某一个类注入到容器中
/**
* @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件
*
* 在配置文件中用<bean><bean/>标签添加组件
*
*/
@Configuration
public class MyAppConfig {
//将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
@Bean
public HelloService helloService02(){
System.out.println("配置类@Bean给容器中添加组件了...");
return new HelloService();
}
}
7.Profile
profile 是springboot提供一个多环境切换的方式 。开发环境、测试环境、生产环境。可以改变的是对数据库连接、端口号的控制。
7.1、多Profile文件
我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml,默认使用application.properties的配置;
7.2、yml支持多文档块方式
作用是跟前面定义的多个配置文件的方式是一样的,这样的优点在于不用写很多的配置文件,就可以实现对多环境的切换。
server:
port: 8081
spring:
profiles:
active: prod
‐‐‐
server:
port: 8083
spring:
profiles: dev
‐‐‐
server:
port: 8084
spring:
profiles: prod #指定属于哪个环境
7.3、激活指定profile
激活指定profile的4种方法,目的切换不同的环境,控制端口和其他一些的资源
- 命令行:java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
- 在配置文件中指定: spring.profiles.active=dev
- 在测试的直接传入参数:spring.profiles.active=dev
- 虚拟机参数:-Dspring.profiles.active=dev
8.springboot配置文件加载位置
springboot在启动的过程中会加载以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文
件-file:../config config文件夹
-file:./
–classpath:/config/ 类路径下的config文件夹
–classpath:/ 类路径下
优先级是从高到低,高优先级的会覆盖低优先级的配置文件。springboot会从这个4个路劲加载配置文件,形成互补的方式
项目打好包后 也可以使用命令的方式来确定配置文件的位置:
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
项目打包运行后,所有的运行参数配置都可以是在命令行中输入,多个配置用空格分开; --配置项=值
比如改变访问路径:
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
(体现了英文好的妙处,可惜本人英文不好。。所以要努力学习呀!!!)
9.自动配置原理
写了很多的配置文件,但是其中的奥秘还是不了解,所以凡是都要知根知底的使用起来才有底气~~~~,这就要看一看springboot的自动配置原理。
9.1自动配置原理
- springboot在启动的时候,会加载主配置类,开启了自动配置功能,@EnableAutoConfiguration
- @EnableAutoConfiguration的作用
- 利用EnableAutoConfigurationImportSelector给容器中导入一些组件
- 可以查看selectImports()方法的内容;
- List configurations = getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置
- (SpringFactoriesLoader.loadFactoryNames() 扫描所有jar包类路径下 META‐INF/spring.factories把扫描到的这些文 件的内容包装成properties对象从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们 添加在容器中)
就是将 类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;
3. 就是这里每一个自动配置类进行自动配置功能,将配置文件中的配置信息装载在类中(这个前面说到的获取配置文件数据到实体类的方方法是一样的);
9.2 以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;
@Configuration //表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件 @EnableConfigurationProperties(HttpEncodingProperties.class) //启动指定类的 ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;并把 HttpEncodingProperties加入到ioc容器中 @ConditionalOnWebApplication //Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果 满足指定的条件,整个配置类里面的配置就会生效; 判断当前应用是否是web应用,如果是,当前配置类生效 @ConditionalOnClass(CharacterEncodingFilter.class) //判断当前项目有没有这个类 CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器; @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) //判断配置文件中是否存在某个配置 spring.http.encoding.enabled;如果不存在,判断也是成立的 //即使我们配置文件中不配置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; }
spring.http.encoding 这个数据就可以在配置文件中写的前缀。
总结: 这些自动配置类会在底层进行一系列的判读是否要生成自动配置类、初始化并加载到ioc容器中。
- springboot在启动的时候会加载大量的自动装配类
- 如果在业务需求中,看有没有已经有了我们需要的自动装配类
- 我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
- 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;
自动装配类是需要条件才能自动生成的,可以通过这个debug=true查看
10.日志框架的使用
10.1,日志框架
市面上有常见的日志框架:JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j....
日志框架分别有日志抽象层和日志实现层,springboot底层是spring ,spring使用的日志框架是jcl。抽象层 有JCL、SLF4J、jboo-logging,日志实现:log4jJ、log4j2、logback
spring boot 底层使用的是slf4j 和logback实现
10.2 slf4j的日志使用
- 如何在系统中使用SLF4j https://www.slf4j.org
- 以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法;给系统里面导入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");
}
}
10.3 日志使用
- 默认配置,只要是使用了日志记录器就可以使用
//记录器 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修改日志的默认配置
logging.level.com.atguigu=trace
#logging.path=
# 不指定路径在当前项目下生成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
11. Web开发
1.简介 (使用springboot)
- 创建springboot应用,选中我们需要的模块
- Springboot已经将这些默认的场景配置好了,我们只需要再文件中配置少量的配置就好了
- 主要的的精力放在业务逻辑上
提出问题:自动配置原理??
这个springboot帮助我们配置了什么?能不能修改??能修改哪些配置???能不能扩展???? 。。。。
xxxxAutoConfiguration:帮我们给容器中自动配置组件; xxxxProperties:配置类来封装配置文件的内容; |
2.SpringBoot对静态资源的映射规则;
在这个类下面可以配置查静态资源文件的路径
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties implements ResourceLoaderAware {
主要应用的类是
//可以设置和静态资源有关的参数,缓存时间等
ebMvcAuotConfiguration :
@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;
}
}
1.使用webjars的方式引用静态资源
静态资源的底层说明
//添加静态依赖的配置
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache()
.getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry
.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod))
.setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(
registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(
this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod))
.setCacheControl(cacheControl));
}
}
1.所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找资源;webjars:以jar包的方式引入静态资源;
访问路径:localhost:8080/webjars/jquery/3.3.1/jquery.js
<!‐‐引入jquery‐webjar‐‐>在访问的时候只需要写webjars下面资源的名称即可
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
2. "/**" 访问当前项目的任何资源,都去(静态资源的文件夹)找映射
"classpath:/META‐INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
"/":当前项目的根路径
3. 欢迎页; 静态资源文件夹下的所有index.html页面;被"/**"映射;
localhost:8080/ 找index页面
4.所有的 **/favicon.ico 都是在静态资源文件下找