简介
Spring Boot 是 Pivotal 团队在 Spring 的基础上提供的一套全新的开源框架,其目的是为了简化 Spring 应用的搭建和开发过程。Spring Boot 去除了大量的 XML 配置文件,简化了复杂的依赖管理。
Spring Boot 具有 Spring 一切优秀特性,Spring 能做的事,Spring Boot 都可以做,而且使用更加简单,功能更加丰富,性能更加稳定而健壮。随着近些年来微服务技术的流行,Spring Boot 也成了时下炙手可热的技术。
Spring Boot 集成了大量常用的第三方库配置,Spring Boot 应用中这些第三方库几乎可以是零配置的开箱即用(out-of-the-box),大部分的 Spring Boot 应用都只需要非常少量的配置代码(基于 Java 的配置),开发者能够更加专注于业务逻辑。
Spring Boot 具有以下特点:
1. 独立运行的 Spring 项目
Spring Boot 可以以 jar 包的形式独立运行,Spring Boot 项目只需通过命令“ java–jar xx.jar” 即可运行。
2. 内嵌 Servlet 容器
Spring Boot 使用嵌入式的 Servlet 容器(例如 Tomcat、Jetty 或者 Undertow 等),应用无需打成 WAR 包 。
3. 提供 starter 简化 Maven 配置
Spring Boot 提供了一系列的“starter”项目对象模型(POMS)来简化 Maven 配置。
4. 提供了大量的自动配置
Spring Boot 提供了大量的默认自动配置,来简化项目的开发,开发人员也通过配置文件修改默认配置。
5. 自带应用监控
Spring Boot 可以对正在运行的项目提供监控。
6. 无代码生成和 xml 配置
Spring Boot 不需要任何 xml 配置即可实现 Spring 的所有配置。
微服务介绍
2014,Martin fowler形象的介绍了微服务
Microservices:架构风格
一个应用应该是一组小型应用,每个小型应用可以运行在自己的进程中,可以通过HTTP通信
最终每一个元素都可以是独立升级,独立修改的软件单元
环境搭建:
maven的settings.xml配置文件的profiles标签添加
<profile>
<id>jdk-15</id>
<activation>
<jdk>15</jdk>
</activation>
<properties>
<maven.compiler.source>15</maven.compiler.source>
<maven.compiler.target>15</maven.compiler.target>
<maven.compiler.compilerVersion>15</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
快速入门
-
创建maven的项目:新建配置文件,application.properties
server.port=8080
-
导入依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.12.RELEASE</version> </parent> <properties> <maven.compiler.source>15</maven.compiler.source> <maven.compiler.target>15</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
-
新建springboot主程序入口
package cn.supperbro;
import org.springframework.boot.SpringApplication;
@org.springframework.boot.autoconfigure.SpringBootApplication
public class SpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootApplication.class,args);
}
}
- 编写controller和service业务逻辑等
package cn.supperbro.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello(){
return "hello springboot";
}
}
-
测试:启动main方法就OK,查看启动的端口号与逻辑进行访问
-
打包插件:通过package进行打包操作
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
- 本地执行:执行打包好的jar包
java -jar springboot01_helloWorld-1.0-SNAPSHOT.jar
SpringBoot特点
依赖管理
-
父项目依赖管理
导入maven的依赖时我们发现有一个parent标签,说明引入的父项目
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.12.RELEASE</version> </parent>
父项目spring-boot-starter-parent又依赖了spring-boot-dependencies
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.3.12.RELEASE</version> </parent>
在其中我们可以看到spring-boot-dependencies所依赖的坐标以及版本号
<*.version>*.*.*</*.version> <dependency> <groupId>*</groupId> <artifactId>*</artifactId> <version>${*.version}</version> </dependency>
-
无需关注版本号,自动版本仲裁
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
在我们的项目中导入的依赖可以不去定义其版本号,版本会根据父项目的spring-boot-dependencies默认版本号去自动仲裁
-
自定义版本号:
在springboot父项目依赖中如果不存在我们想要的版本号,可以通过手动添加我们项目的pom文件的方式进行版本的引入
如:修改数据库驱动的版本号 语法格式必须与其spring-boot-dependencies格式一样
<properties> <mysql.version>8.0.25</mysql.version> </properties>
-
starter场景启动器
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
spring-boot-starter-web表示web场景启动器
只要引入这个场景,该场景的所有依赖都会被自动引入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j6DZGJX3-1629704244285)(C:\Users\18175\AppData\Roaming\Typora\typora-user-images\image-20210817121209159.png)]
spring-boot-starter-*官方提供的场景
https://docs.spring.io/spring-boot/docs/2.3.12.RELEASE/reference/html/using-spring-boot.html#using-boot-starter
*-spring-boot-starter-*一般指的是第三方提供的场景依赖
所有的场景底层都依赖:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>*</version> </dependency> </dependencies>
自动配置
入门程序中,没有导入tomact,spring-mvc等等相关的依赖或者是配置,程序的执行依赖于springboot帮我们自动配置好的环境。
-
tomact配置:关于tomcat在spring-boot-dependencies依赖的坐标中可以发现,并且自动配置了其启动的端口号等等…
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <version>2.3.12.RELEASE</version> </dependency>
-
配置了SpringMVC的相关功能
上述中导入starter-web为web就会自动配置了其相关的功能,如dispatcherServlet,乱码问题…
-
默认的包结构
mvc阶段我们需要配置支持注解驱动的包空间
在springboot中默认指定了注解的包空间:即我们主程序SpringBootApplication的同级目录即其子包当中
- 也可以自己配置其指定的包空间:
@org.springframework.boot.autoconfigure.SpringBootApplication(scanBasePackages = "指定的包")
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan("包名") 这三个注解相当于一个 @SpringBootApplication
-
每个配置项都会有自己的默认值
-
配置都是按需加载
引入哪个starter就会加载哪个starter的配置
自动配置都会通过
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>2.3.12.RELEASE</version> </dependency>
容器功能
组件添加
- 装配组件
package cn.supperbro.config;
import cn.supperbro.pojo.Pet;
import cn.supperbro.pojo.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @Configuration 作用在类上标注该类为组件标注类
*
* @Bean 作用于方法上,注册组件,把方法名作为组件的id,把返回值类型作为组件的类型
*
* proxyBeanMethods为@Configuration的参数,true和false,默认为true
* proxyBeanMethods = true 表示该配置类的方法被springIOC代理的 即Full全局配置 有组件需要依赖别的组件时可以使用true
* proxyBeanMethods = false 为 lite 即轻量级配置 组件无需依赖时可以使用这个方法 加速spring的启动
*
* @Import({User.class,Pet.class})
* 导入的是User以及Pet的实例对象
*
* 关于Conditional的用法 例如
* @ConditionalOnBean(name = "tomcat01")
* 作用在类上时表示容器中有tomcat01这个组件才会去注册该类下的组件
* 作用在方法上时表示容器上有这个组件才会去注册该方法的组件
* 注意:线式编程从上到下
*/
@Import({User.class,Pet.class})
@Configuration(proxyBeanMethods = true)
public class MyConfig {
/**
* 默认是单实例的
* @return
*/
@Bean
public Pet tomcat01(){
return new Pet("tomcat");
}
@Bean
@ConditionalOnBean(name = "tomcat01")
public User user01(){
return new User("xxx","nan");
}
}
Conditional的一些注解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cT75mCfH-1629704244287)(C:\Users\18175\AppData\Roaming\Typora\typora-user-images\image-20210817151936243.png)]
-
引入原始方式配置的组件资源(xml方式配置的)
@ImportResource("classpath:bean.xml")//作用在配置类上
-
配置绑定
@Component + @ConfigurationProperties实现:作用在同一类上
@Component @ConfigurationProperties(prefix = "jdbc") @Data public class JDBCBean { private String driver; private String url; private String username; private String password; }
@EnableConfigurationProperties + @ConfigurationProperties 实现。EnableConfigurationProperties在我们bean的配置文件上配置;
自动配置原理入门
-
引导加载自动配置类
在主程序入口时:有三个核心的注解
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan
-
@SpringBootConfiguration
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2BuYD9kV-1629704244288)(C:\Users\18175\Pictures\Saved Pictures\QQ截图20210817162341.png)]
-
@ComponentScan
@Repeatable(ComponentScans.class) public @interface ComponentScan {}//自动扫描
-
@EnableAutoConfiguration
@AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {}
@AutoConfigurationPackage 自动配置包?
@Import(AutoConfigurationPackages.Registrar.class)//import的高级用法,给容器中导入组件 public @interface AutoConfigurationPackage {} //利用Registrar导入一系列的组件 //将主程序入口下的所有的导入进来
AutoConfigurationImportSelector
@AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {}
getAutoConfigurationEntry(annotationMetadata)//给容器中批量添加组件
List configurations = getCandidateConfigurations(annotationMetadata, attributes)//将所有的组件加载到容器当中
Map<String, List> loadSpringFactories(@Nullable ClassLoader classLoader)//得到所有的组件
spring.factories中加载所有的文件
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,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\ org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\ org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\ org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\ org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\ org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\ org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\ org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\ org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\ org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\ org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\ org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\ org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\ org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\ org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\ org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\ org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\ org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\ org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\ org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\ org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\ org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\ org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\ org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\ org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\ org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\ org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\ org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\ org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\ org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\ org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\ org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\ org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\ org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\ org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\ org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\ org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\ org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\ org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\ org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\ org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\ org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\ org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\ org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
-
-
按需开启自动配置项
springboot一次性加载了所有的127个组件,但是不会对每个组件都开启,最终会按照条件装配原则进行配置
-
定制化修改自动配置
SpringBoot默认会配置好所有的组件,但是用户配置了会议用户配置的优先。
- SpringBoot先加载好所有的自动配置类
- 每个自动的配置类会按照条件生效,默认会绑定配置文件绑定的值
- 生效的配置类就会在容器中配置很多的组件
- 容器中有了这些组件,这些功能就有了
- 自定义配置:
- 用户直接自定义@Bean来替换底层的bean
- 用户根据组件获取的配置文件的值去修改。
开发实践:
-
根据场景导入依赖
-
查看自动配置:
- 查看源码
- 配置debug=true开启自动配置报告Negative不生效/Positive生效
-
是否需要修改底层组件的配置
-
参照文档修改配置项
https://docs.spring.io/spring-boot/docs/2.3.12.RELEASE/reference/html/appendix-application-properties.html#common-application-properties
-
源代码查看配置项并且修改
-
自定义组件加入。
-
-
开发小工具
-
lombok
-
dev-tools
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency>
ctrl+f9可以进行项目的重新启动
-
Spring Initializr 快速构建springboot项目(初始化项目向导)
-
核心功能
配置文件
Spring Boot 的配置文件共有两种形式:.properties 文件和 .yml 文件,不管哪种形式,它们都能通过文件名的命名形式区分出不同的环境的配置
yaml
-
yaml 非常适合以数据为中心的配置文件
-
基本语法:
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不可以用table 用空格
- 空格数目不重要,相同等级的元素需要对齐
- #表示注解
- ‘’ “” 字符串类型 会不会被转义:单引号会将\n作为字符串输出,双引号会将\n转义为换行
-
数据类型
实体类
package cn.supperbro.pojo; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; @Data @Component @ConfigurationProperties(prefix = "person") public class Person { private String name; private int age; private Date birth; private Pet pet; private String [] interests; private List<String> nickname; private Map<String,Object> score; private Set<String> friends; private List<Map<String,Pet>> type; }
yaml
person: name: z age: 18 birth: 2003/3/13 interests: [篮球,足球] nickname: - zyx - sf_one score: {math: 88,chinese: 100, java: 1000} friends: - csr - hq - zzz pet: name: cat01 age: 15 type: - big: {name: cat11,age: 2} - small: {name: cat99,age: 3}
小技巧:
在配置yaml的时候想要配置提示可以导入
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
配置插件之后加入插件,之后就不会被打包到package之后的war或者jar
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build>
SpringMVC自动配置功能分析
静态资源
-
访问静态资源
Spring Boot serves static content from a directory called
/static
(or/public
or/resources
or/META-INF/resources
) in the classpath or from the root of theServletContext
.springboot默认放置静态资源的地方为类路径下的**/static**
/public
/resources
/META-INF/resources
原理:springboot首先会去controller查找看是否存在该名称的请求,如果有,就从controller中去响应,没有就去静态资源中查找,没有的话就报404
有时候为了方便配置拦截器/** 可以利用设置静态资源前缀将其排除在外
spring: mvc: static-path-pattern: /前缀名/**
-
修改静态资源访问路径
不使用自定义的资源路径的话可以进行修改
spring: resources: static-locations: classpath:/test/
-
webjar
webjar是将静态资源如js css打成jar包 可以通过添加依赖的方式进行添加 https://www.webjars.org/
springboot支持webjar的自动映射 路径要填写依赖路径
-
欢迎页面和网站导航图标
欢迎页面:1.静态资源中有index.xml可以默认为welcomepage 2. controller存在index请求头作为欢迎页面
favicon.ico命名的图标放置在静态资源路径上可以被自动映射
-
源码分析
-
springboot启动时会加载很多的自动配置文件**AutoConfiguration
-
WebMvcAutoConfiguration集中了springmvc的配置 通过@Conditional注解 查看生效
@Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })
-
给容器中配置了什么
@Configuration(proxyBeanMethods = false) @Import(EnableWebMvcConfiguration.class) @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class }) @Order(0) public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {}
-
文件相关的属性进行了绑定WebMvcProperties(prefix = “spring.mvc”), ResourceProperties(prefix = “spring.resources”)
-
WebMvcAutoConfigurationAdapter只有一个有参构造器,那么所有的的属性都是从容器中获取
-
请求处理
-
rest风格(此处主要处理的是表单)
常规发送不同的请求需要不同的请求名从而得到不同的响应体。rest风格可以发送同一个请求名根据请求方法的不同而进行不同的响应。
原理:
-
springboot中自动配置了HiddenHttpMethodFilter,会拦截请求需要手动配置,然后判断
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false)
默认为false 需要去手动配置
spring: mvc: hiddenmethod: filter: enabled: true
if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null)
-
根据它会去获取到我们隐藏的表单列传递的信息
-
通过HttpMethodRequestWrapper去进行封装最后去controller调用匹配的方法
案例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>welcome</title> </head> <body> <h1 style="text-align: center">欢迎</h1> <form action="/user" method="post"> <input type="submit" value="post请求" > </form><br> <form action="/user" method="get"> <input type="submit" value="get请求" > </form><br> <form action="/user" method="post"> <input type="hidden" name="_method" value="delete"> <input type="submit" value="delete请求" > </form><br> <form action="/user" method="post"> <input type="hidden" name="_method" value="put"> <input type="submit" value="put请求" > </form><br> </body> </html>
package cn.supperbro.springboot02_springmvc; import org.springframework.web.bind.annotation.*; @RestController public class UserController { //@RequestMapping(value = "/user",method = RequestMethod.POST)与下面写法一样 @PostMapping("/user") public String postUser(){ return "post"; } @GetMapping("/user") public String getUser(){ return "get"; } @DeleteMapping("/user") public String deleteUser(){ return "delete"; } @PutMapping("/user") public String putUser(){ return "put"; } }
拓展:
<input type="hidden" name="_method" value="delete">
由于springboot底层的要求,参数名字必须为_method 由于@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@Bean @ConditionalOnMissingBean(HiddenHttpMethodFilter.class) @ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false) public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() { return new OrderedHiddenHttpMethodFilter(); }
但是也可以定义HiddenHttpMethodFilter替代它默认的
package cn.supperbro.springboot02_springmvc; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.filter.HiddenHttpMethodFilter; @Configuration(proxyBeanMethods = false) public class Config { @Bean public HiddenHttpMethodFilter myHiddenHttpMethodFilter(){ HiddenHttpMethodFilter filter = new HiddenHttpMethodFilter(); filter.setMethodParam("div"); return filter; } }
-
请求参数
注解获取
//获取路径变量 restful风格 @PathVariable Map<String,String> all获取所有路径上的参数
@PathVariable("name")String username, @PathVariable("sex")String sex, @PathVariable Map<String,String> all,
//获取参数@RequestParam 通过其value去匹配参数名相同的值,获取
@RequestParam("inters")String inter, @RequestParam("inters")List<String> inters, @RequestParam Map<String,String> intersMap,
//获取请求头信息@RequestHeader根据参数名称去获取
@RequestHeader("Host")String Host, @RequestHeader Map<String,String> headers,
//CookieValue()获取cookie的相关信息 @CookieValue Cookie cookie直接获取到这个cookie
//@RequestBody String post,@RequestBody Map<String,String> 获取的是表单post提交的表单体
@RequestBody String post,@RequestBody Map<String,String> map
@Controller
public class Test {
@RequestMapping("/goto")
public String goTo(HttpServletRequest request){
request.setAttribute("msg","success....");
return "forward:success"; //转发请求
}
@ResponseBody
@RequestMapping("/success")
//@RequestAttribute("msg") String msg获取转发请求域中的值
public String success(@RequestAttribute("msg") String msg){
return msg;
}
矩阵变量请求:场景当cookie被禁用时,无法传递jseessionid时可以通过矩阵变量进行参数传递
案例:
//矩阵变量请求语法: /{path};matrix=value1;matrix=value2
// /{path};matrix=value,value2
@ResponseBody
@RequestMapping("/matrix/{path}")
//@MatrixVariable 获取矩阵变量的参数
public Map matrix(@MatrixVariable("name") List<String> name, @PathVariable("path")String path){
Map<String,Object> map = new HashMap<>();
map.put("name",name);
return map;
}
当然springboot底层是禁止使用矩阵变量的
开启方式
@Configuration
public class Config implements WebMvcConfigurer {
//继承WebMvcConfigurer 重写configurePathMatch进行修改
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper helper = new UrlPathHelper();
helper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(helper);
}
}
@Bean
public WebMvcConfigurer getConfigurer(){
return new WebMvcConfigurer() {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper helper = new UrlPathHelper();
helper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(helper);
}
};
}
处理特殊的矩阵请求
http://localhost:8080/matrix1/xx;name=xx/xxx;name=xxx
//处理特殊矩阵请求 xxxx/xx;name=xx/xxx;name=xxx
@ResponseBody
@RequestMapping("/matrix1/{path1}/{path2}")
//@MatrixVariable 获取矩阵变量的参数
public Map matrix1(@MatrixVariable(name = "name",pathVar = "path1")String name1, @MatrixVariable(name = "name",pathVar = "path2")String name2){
Map<String,Object> map = new HashMap<>();
map.put("name1",name1);
map.put("name2",name2);
return map;
}
原生API获取:
ServletRequestMethodArgumentResolver 包含的部分原始AIP的判断
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> paramType = parameter.getParameterType();
return (WebRequest.class.isAssignableFrom(paramType) ||
ServletRequest.class.isAssignableFrom(paramType) ||
MultipartRequest.class.isAssignableFrom(paramType) ||
HttpSession.class.isAssignableFrom(paramType) ||
(pushBuilder != null && pushBuilder.isAssignableFrom(paramType)) ||
Principal.class.isAssignableFrom(paramType) ||
InputStream.class.isAssignableFrom(paramType) ||
Reader.class.isAssignableFrom(paramType) ||
HttpMethod.class == paramType ||
Locale.class == paramType ||
TimeZone.class == paramType ||
ZoneId.class == paramType);
}
复杂参数:
Map Model (可以将数据存放到请求域 request.setAttribute)
RedirectAttribute(重定向携带数据)
ServletResponse(response响应)
自定义对象参数:
自定义pojo可以自动配置绑定,pojo属性名与表单属性名相同,在默认的spring由表单提交的数据都会根据pojo去解析与转发,但是同时也是可以自定义其转化规则的
案例:
实体类
package cn.supperbro.springboot02_springmvc;
import lombok.Data;
@Data
public class Person {
private String name;
private Pet pet;
}
package cn.supperbro.springboot02_springmvc;
import lombok.Data;
@Data
public class Pet {
private String name;
private int age;
}
表单
<form action="/person" method="post">
用户名:<input type="text" name="name">
宠物信息:<input type="text" name="pet">
<input type="submit" value="put请求" >
</form>
配置
@Bean
public WebMvcConfigurer getConfigurer(){
return new WebMvcConfigurer() {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper helper = new UrlPathHelper();
helper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(helper);
}
//配置stringx'hu
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new Converter<String, Pet>() {
@Override
public Pet convert(String s) {
if (!StringUtils.isEmpty(s)){
Pet pet = new Pet();
String[] split = s.split(",");
pet.setName(split[0]);
pet.setAge(Integer.parseInt(split[1]));
return pet;
}else {
return null;
}
}
});
}
};
}
响应数据
springboot可以返回多种数据格式的数据如json,xml等…(底层原理源码)
根据不同的客户端需求,spring根据内容协商也可以返回不同的文本类型
内容协商:
springboot中的web场景包含了json数据格式化,如果想要发送xml需要导入jar包
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.12.4</version>
</dependency>
导入之后springboot会自动配置,访问时(根据客户端能获取到的数据类型)会响应相关配置过的数据格式
场景案例
浏览器发的请求响应xml
ajax发的请求响应json
自定义app发的请求响应自定义数据格式
解决思路:自定义响应数据格式 响应数据格式由底层的messageConverter控制,想要自定义数据格式可以被返回,需要添加自定义的xxconverter,在容器中添加
@Bean
public WebMvcConfigurer getConfigurer(){
return new WebMvcConfigurer() {
//通过url去判断访问
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
Map<String, MediaType> mediaTypeMap = new HashMap<>();
mediaTypeMap.put("json",MediaType.APPLICATION_JSON);
mediaTypeMap.put("xml",MediaType.APPLICATION_XML);
mediaTypeMap.put("div",MediaType.parseMediaType("application/div"));
//制定了哪些请求参数所对应的数据返回类型
ParameterContentNegotiationStrategy strategy = new ParameterContentNegotiationStrategy(mediaTypeMap);
strategy.setParameterName("type");//修改参数的名字 对应的是url指定的那种数据格式前面的参数类型
HeaderContentNegotiationStrategy strategy1 = new HeaderContentNegotiationStrategy();
configurer.strategies(Arrays.asList(strategy,strategy1));
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new DivMessageConverter());
}
};
}
添加之后需要新建自定义的messageController
package cn.supperbro.springboot02_springmvc;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
public class DivMessageConverter implements HttpMessageConverter<Person> {
//MessageConverter是否可以读取该数据
@Override
public boolean canRead(Class<?> aClass, MediaType mediaType) {
return false;
}
//MessageConverter是否可以写出该数据
@Override
public boolean canWrite(Class<?> aClass, MediaType mediaType) {
return aClass.isAssignableFrom(Person.class);
}
/**
* 服务器要统计出所有的messageConverter能够写出那些数据类型,处理哪些请求头所要求的数据格式
* @return
*/
@Override
public List<MediaType> getSupportedMediaTypes() {
return MediaType.parseMediaTypes("application/x-div");
}
@Override
public Person read(Class<? extends Person> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
return null;
}
@Override
public void write(Person person, MediaType mediaType, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
//自定义返回的格式
OutputStream body = httpOutputMessage.getBody();
body.write(person.toString().getBytes());
}
}
视图解析
由于springboot不支持jsp模板引擎,它是以jar包的形式加载。
Thymeleaf是一个Java模板引擎,支持html、xml、text、javascript、css、raw这几种模型。性能没有很好,适合单体项目
spring-boot-starter-thymeleaf通过引入starter就可以使用该模板引擎了,由于这个模板引擎是spring的定制化的模板引擎,大多数数据都已经被默认配置了。
视图解析器:ThymeleafViewResolver
视图解析位置:classpath:/templates/
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
private boolean checkTemplate = true;
private boolean checkTemplateLocation = true;
private String prefix = "classpath:/templates/";
private String suffix = ".html";
private String mode = "HTML";
测试:
@RequestMapping("/thymeleaf")
//@MatrixVariable 获取矩阵变量的参数
public String testThymeleaf(Model model){
Person person = new Person();
Pet pet = new Pet();
pet.setName("小黄");
pet.setAge(18);
person.setName("祥哥");
person.setPet(pet);
model.addAttribute("user",person);
return "success";
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>thymeleaf入门</title>
</head>
<body>
<h>welcome</h>
<p th:text="${user.getPet().getName()}"></p>
<p th:text="${user.getName()}"></p>
</body>
</html>
拦截器
web开发中拦截器有着很大的作用,如过过滤用户等功能,实现拦截器需要去实现HandlerInterceptor接口
步骤:
-
指定一个拦截器,实现HandlerInterceptor接口,在三种方法书写对应的拦截逻辑
-
配置WebMvcConfigurer 重写addInterceptor方法
-
指定拦截规则(要是拦截所有请求还要指定放行静态资源)
代码实现
package com.supperbro.shopping.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginHandlerInterceptor implements HandlerInterceptor { /** * 在请求响应之前执行 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return false; } /** * 在请求响应之后执行 * @param request * @param response * @param handler * @param modelAndView * @throws Exception */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } /** * 在请求完成之后执行(页面渲染之后) * @param request * @param response * @param handler * @param ex * @throws Exception */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
package com.supperbro.shopping.config; import com.supperbro.shopping.interceptor.LoginHandlerInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginHandlerInterceptor()). addPathPatterns("/**").//添加拦截的请求,/**表示拦截所有的请求 excludePathPatterns("/","/css/**");//除去静态资源拦截或者指定请求拦截/css/**"表示css文件下的所有资源 } }
文件上传
springboot默认了请求大小,与文件大小,可以自定义
spring:
servlet:
multipart:
max-file-size: 10MB #单个文件的最大请求大小
max-request-size: 100MB #整个请求的最大大小
文件上传代码
package com.supperbro.shopping.util;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
@Controller
public class UploadFile {
@ResponseBody
@RequestMapping("/file")
public String getFiles(
String username,
String text,
@RequestPart MultipartFile headerImg,
@RequestPart MultipartFile [] files
) throws IOException {
if (!headerImg.isEmpty()){
String filename = headerImg.getOriginalFilename();
File file = new File("D://test_data//"+filename);//路径
headerImg.transferTo(file);
}
if (files.length>0){
for (MultipartFile file : files) {
if (!file.isEmpty()){
String filename = file.getOriginalFilename();
File filePath = new File("D://test_data//"+filename);
file.transferTo(filePath);
}
}
}
return username+text;
}
}
异常处理
-
默认机制:
spring默认的是响应一个error,对于浏览器响应的是一个错误页面,对于机器客户端可以响应的是json格式数据
-
自定义
-
方法:可以自动添加error命令的静态资源在static 或者是 模板引擎的目录下
-
源码流程
-
-
自定义错误逻辑
-
自定义页面逻辑:可以根据源码赋值默认值逻辑,去获取相对应的错误 如 :status 状态码
<h1 class="title mb-5" th:text="${status}">404</h1> <h2 class="sub-title mb-4" th:text="${error}">Page Cannot Be Found!</h2> <p class="short-desc mb-7" th:text="${message}"></p>
-
自定义controller控制异常处理:@ControllerAdvice+@ExceptionHandler处理
@ControllerAdvice public class ExceptionController { @ExceptionHandler({ArithmeticException.class,ClassNotFoundException.class})//标注这个类可以处理哪些类型的异常 public ModelAndView exceptionHandler(Exception e){ ModelAndView view = new ModelAndView(); view.setViewName("test"); view.addObject("message",e.getMessage()); return view; } }
-
自定义异常request+@ResponseStatus
@Controller @RequestMapping("/user") public class LoginController { @RequestMapping("/login") public String goToLogin(int a){ if (a>3){ throw new DivException("大于3"); } return "/login-register"; }
package com.supperbro.shopping.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; //指定状态码和异常原因 @ResponseStatus(value = HttpStatus.EXPECTATION_FAILED, reason = "div异常信息") public class DivException extends RuntimeException{ public DivException(){ } public DivException(String message){ super(message); } }
-
自定义异常解析器:每个异常的处理,在spring的底层会交给一个异常解析器去完成,我们也可以自定义个异常解析器去解析异常
@Order(value = Ordered.HIGHEST_PRECEDENCE) //设置优先级,因为在springboot的底层中有多个异常处理器,如果其他的处理器可以处理相关异常,就不会轮到我们处理该异常了 @Component //实现异常处理机制的接口andlerExceptionResolver达到自定义异常处理器目标 public class DivExceptionHandler implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { try { httpServletResponse.sendError(403,"div的信息"); } catch (IOException ioException) { ioException.printStackTrace(); } return new ModelAndView(); //返回的模型视图为默认的,会自动匹配错误码,到对应的页面 } }
-
原生组件注入
web原生组件 servlet filter listener
-
使用servletAPI
首先指定springboot能够扫描到我们的servlet,指定其扫描空间
@ServletComponentScan(basePackages = "cn.supperbro.shopping.servlet") //当然不指定的话就是默认值:@SpringBootApplication所在包下及其子包
定义原生的servlet
@WebServlet("/myServlet") public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("原生servlet"); } }
对于filter listener也是同理
@WebFilter @WebListener @WebServlet(urlPatterns = "/ss")
-
使用RegistrationBean
ServletRegistrationBean,FilterRegistrationBean,ListenerRegistrationBean通过配置注册注入原生组件
@Controller public class ServletRegister { @Bean public ServletRegistrationBean myServlet(){ MyServlet myServlet = new MyServlet(); //可以映射多个地址 return new ServletRegistrationBean(myServlet,"/xxx","/xxx1"); } }
自动配置原理总结:
- 原理套路:
-
定制化方式
- 修改配置文件
- 定制化容器xxxxCustomizer
- 编写自定义的配置类,xxxConfiguration+@Bean,去增加容器中的默认组件。
- web应用可以实现WebMvcConfigurer接口定制化web功能。
- @EnableWebMVC+实现WebMvcCongigurer接口可以去全面接管SpringMVC(慎用);实现所有的配置自动化。
数据访问
SQL数据库
整合druid
-
数据源自动配置
-
导入数据库场景
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency>
starter场景下添加了,数据库相关操作的依赖
<dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>3.4.5</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.15.RELEASE</version> <scope>compile</scope> </dependency>
JDBC的场景中有数据源操作,事务操作,JDBC操作但是没有数据库驱动,需要手动导入对应的数据库的驱动,官方对数据库版本进行了仲裁
<mysql.version>8.0.25</mysql.version>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> 修改版本: 1. 可以直接添加依赖并且设定版本(maven的就近依赖原则) 2. 重新声明版本(maven就近优先原则) <properties> 要根据spring的设定规则 <mysql.version></mysql.version> </properties>
-
分析数据库场景自动配置
-
DataSourceAutoConfiguration 数据源自动配置
-
绑定了DataSourceProperties数据源参数配置–>prefix = “spring.datasource” 即springboot配置文件指定前缀
-
配置数据源PooledDataSourceConfiguration
@Conditional({DataSourceAutoConfiguration.PooledDataSourceCondition.class}) @ConditionalOnMissingBean({DataSource.class, XADataSource.class}) @Import({Hikari.class, Tomcat.class, Dbcp2.class, OracleUcp.class, Generic.class, DataSourceJmxConfiguration.class}) protected static class PooledDataSourceConfiguration { protected PooledDataSourceConfiguration() { } }
-
-
-
配置数据库配置项
spring: datasource: url: mysql://localhost:3306/jdbctest?serverTimezone=Asia/Shanghai&useSSL=true&useUnicode=true&characterEncoding=UTF-8 username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver
-
JDBC操作模板
JDBCTemplate
JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); JdbcProperties.Template template = properties.getTemplate(); jdbcTemplate.setFetchSize(template.getFetchSize()); jdbcTemplate.setMaxRows(template.getMaxRows()); if (template.getQueryTimeout() != null) { jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds()); } return jdbcTemplate; }
根据其绑定的JdbcCProperties可以来进行相关属性的配置@ConfigurationProperties(prefix = “spring.jdbc”)
spring: jdbc: template: query-timeout: 3
可以根据template操作数据库了:
注意导入场景的区别spring-boot-starter-jdbc包含spring-boot-starter-data-jdbc
-
-
数据源配置
-
自定义设置druid
首先还是在项目中去添加依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.3</version> </dependency>
接下来就是参照druid文档进行配置
package cn.supperbro.springboot01.config; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; import java.sql.SQLException; import java.util.Arrays; @Configuration public class DataSourceConfiguration { //在springboot底层中@ConditionalOnMissingBean({DataSource.class, XADataSource.class})去判断我们容器中是否有DataSource, // 一旦存在,就使用我们自己的,否则使用默认的。 @Bean @ConfigurationProperties("spring.datasource") //自己指定绑定的数据源配置 public DataSource dataSource() throws SQLException { DruidDataSource dataSource=new DruidDataSource(); //加入开启监控功能 dataSource.setFilters("stat"); //添加防火墙 dataSource.setFilters("wall"); //也可以写成dataSource.setFilters("stat,wall") return dataSource; } //配置druid监控页的功能 @Bean public ServletRegistrationBean<StatViewServlet> registrationBean(){ StatViewServlet statViewServlet = new StatViewServlet(); ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean(statViewServlet, "/druid/*"); //初始化<StatViewServlet>,例如设置登录控制 registrationBean.addInitParameter("loginUsername","admin"); registrationBean.addInitParameter("loginPassword","123456"); return registrationBean; } //配置webStatFilter监控web-jdbc数据 @Bean public FilterRegistrationBean<WebStatFilter> webStatFilter (){ WebStatFilter webStatFilter = new WebStatFilter(); FilterRegistrationBean<WebStatFilter> filterFilterRegistrationBean = new FilterRegistrationBean<>(webStatFilter); //设置其拦截路径 filterFilterRegistrationBean.setUrlPatterns(Arrays.asList("/*")); //设置其初始化参数,排除其监控的参数 filterFilterRegistrationBean.addInitParameter("exclusions","*.js,*.css,*.gig,*.jpg,*.png,/druid/*"); return filterFilterRegistrationBean; } }
-
导入druid场景进行配置。
首先导入场景依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.3</version> </dependency>
自动配置 DruidDataSourceAutoConfigure 该类中配置了相关配置
@Import({DruidSpringAopConfiguration.class, DruidStatViewServletConfiguration.class, DruidWebStatFilterConfiguration.class, DruidFilterConfiguration.class})
配置文件中配置相关信息
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/jdbctest?serverTimezone=Asia/Shanghai&useSSL=true&useUnicode=true&characterEncoding=UTF-8 password: root username: root druid: filter: stat: enabled: true wall: enabled: true stat-view-servlet: enabled: true #配置是否开启stat-view-servlet监控 login-username: admin login-password: admin reset-enable: false web-stat-filter: enabled: true exclusions: '*.js,*.css,*.gig,*.jpg,*.png,/druid/*' url-pattern: /*
整合Mybatis
方式一:
-
导入mybatis场景
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency>
-
了解mybatisAutoConfiguration自动配置原理
-
配置文件
mybatis: config-location: classpath:mybatis/mybatis-config.xml mapper-locations: classpath:mybatis/mapper/*.xml configuration: map-underscore-to-camel-case: true #开启驼峰命名
-
同样可以去指定mybatis配置文件,和mapper映射,处理方式还是一样
-
注意事项:
mybatis的全局配置通过mybatis-config.xml配置(推荐)
也可以通过application的配置文件来进行配置。
@MapperScan作用在主类上指定扫描的包空间上,就可以在扫描的包下省略@Mapper注解
方式二:通过注解来配置
-
同样导入场景,同样操作,注解是指加在mapper接口方法上的注解。
-
整合mybatis-plus
-
导入依赖mybatis-plus场景包括JDBC的场景,也包括mybatis的场景导入一个就够了
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.2</version> </dependency>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mHMFtuUO-1629704244293)(C:\Users\18175\AppData\Roaming\Typora\typora-user-images\image-20210822082752197.png)]
优点:mybatis-plus场景下我们的mapper只有去继承了baseMapper那么就会具有基本的增删改查的功能。
使用:https://mp.baomidou.com/guide/quick-start.html
NoSQL数据库
redis
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
-
导入场景
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
-
自动配置
-
spring: redis: host: localhost port: 6379 password: root
基本的配置项
junit5
Springboot2.4以后移除了对junit4的支持,要想支持junit4,需要导入junit4的测试引擎
springboot整合junit5之后,只需要添加@Test注解就可以测试(@Test为junit5的注解)
同时也会兼容springboot的相关注解,例如@Autowired,@Transactional(测试后事务会进行回滚)
-
常用注解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uZ1iK63M-1629704244294)(C:\Users\18175\AppData\Roaming\Typora\typora-user-images\image-20210823081551217.png)]
-
断言机制
JUnit Jupiter附带了许多JUnit 4拥有的断言方法,并添加了一些可以很好地用于Java 8 lambdas的断言方法。
所有JUnit木星断言都是org.junit.jupiter.api.Assertions
中的静态方法断言类。1.简单断言
用来对单个值进行简单的验证。如:
方法 说明 assertEquals 判断两个对象或两个原始类型是否相等 assertNotEquals 判断两个对象或两个原始类型是否不相等 assertSame 判断两个对象引用是否指向同一个对象 assertNotSame 判断两个对象引用是否指向不同的对象 assertTrue 判断给定的布尔值是否为 true assertFalse 判断给定的布尔值是否为 false assertNull 判断给定的对象引用是否为 null assertNotNull 判断给定的对象引用是否不为 null 测试:前面断言失败,后面不会继续执行
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; public class AssertTest { @Test @DisplayName("simple assertion") public void simple() { assertEquals(3, 1 + 2, "simple math"); assertNotEquals(3, 1 + 1); assertNotSame(new Object(), new Object()); Object obj = new Object(); assertSame(obj, obj); assertFalse(1 > 2); assertTrue(1 < 2); assertNull(null); assertNotNull(new Object()); } }
2.数组断言
@Test @DisplayName("array assertion") public void array() { assertArrayEquals(new int[]{1, 2}, new int[] {1, 2}); }
3.组合断言
assertAll 方法接受多个 org.junit.jupiter.api.Executable 函数式接口的实例作为要验证的断言,可以通过 lambda 表达式很容易的提供这些断言
@Test @DisplayName("assert all") public void all() { assertAll("Math", () -> assertEquals(2, 1 + 1), () -> assertTrue(1 > 0) ); }
4.异常断言
在JUnit4时期,想要测试方法的异常情况时,需要用**@Rule注解的ExpectedException变量还是比较麻烦的。而JUnit5提供了一种新的断言方式Assertions.assertThrows()** ,配合函数式编程就可以进行使用。
@Test @DisplayName("异常测试") public void exceptionTest() { ArithmeticException exception = assertThrows( //扔出断言异常 ArithmeticException.class, () -> System.out.println(1 % 0)); }
5.超时断言
断定业务一定在指定时间内完成,否则失败
@Test @DisplayName("超时测试") public void timeoutTest() { //如果测试方法时间超过1s将会异常 assertTimeout(Duration.ofMillis(1000), () -> Thread.sleep(500)); }
6.快速失败
@Test @DisplayName("fail") public void shouldFail() { fail("This should fail"); }
-
前置条件
JUnit 5 中的前置条件(assumptions【假设】)类似于断言,不同之处在于不满足的断言会使得测试方法失败,而不满足的前置条件只会使得测试方法的执行终止。前置条件可以看成是测试方法执行的前提,当该前提不满足时,就没有继续执行的必要。
@Test @DisplayName("assumptions") public void testAssumptions(){ assumeTrue(true); assumeFalse(true); System.out.println("assumptions"); }
-
嵌套测试
JUnit 5 可以通过 Java 中的内部类和@Nested 注解实现嵌套测试,从而可以更好的把相关的测试方法组织在一起。在内部类中可以使用@BeforeEach 和@AfterEach 注解,而且嵌套的层次没有限制。
-
参数化测试
参数化测试是JUnit5很重要的一个新特性,它使得用不同的参数多次运行测试成为了可能,也为我们的单元测试带来许多便利。
利用**@ValueSource**等注解,指定入参,我们将可以使用不同的参数进行多次单元测试,而不需要每新增一个参数就新增一个单元测试,省去了很多冗余代码。
@ValueSource: 为参数化测试指定入参来源,支持八大基础类以及String类型,Class类型
@NullSource: 表示为参数化测试提供一个null的入参
@EnumSource: 表示为参数化测试提供一个枚举入参
@CsvFileSource:表示读取指定CSV文件内容作为参数化测试入参
@MethodSource:表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个Stream)
当然如果参数化测试仅仅只能做到指定普通的入参还达不到让我觉得惊艳的地步。让真正感到他的强大之处的地方在于他可以支持外部的各类入参。如:CSV,YML,JSON 文件甚至方法的返回值也可以作为入参。只需要去实现ArgumentsProvider接口,任何外部文件都可以作为它的入参。
public class ParamTest { @ParameterizedTest @ValueSource(strings = {"one", "two", "three"}) @DisplayName("参数化测试1") public void parameterizedTest1(String string) { System.out.println(string); Assertions.assertTrue(StringUtils.isNotBlank(string)); } @ParameterizedTest @MethodSource("method") //指定方法名 @DisplayName("方法来源参数") public void testWithExplicitLocalMethodSource(String name) { System.out.println(name); Assertions.assertNotNull(name); } static Stream<String> method() { return Stream.of("apple", "banana"); } }
指标监控
springboot actutor
-
简介:
未来每一个服务都部署在云上后,我们需要对它进行追踪,审计,监控,控制等,springboot就抽取了这么一个场景,springboot actutor,可以使得每个服务都可以快速获取到生产级别的监控,需要导入场景的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
暴露所有的信息在http上
management: endpoints: enabled-by-default: true #开启所有的监控端点 web: exposure: include: '*' #以web的方式暴露所有的监控端点
-
Actuator endpoints监控端点
监控分成两类:原生端点和用户自定义扩展端点,原生的主要有
路径 | 描述 |
---|---|
/autoconfig | 提供了一份自动配置报告,记录哪些自动配置条件通过了,哪些没通过 |
/beans | 描述应用程序上下文里全部的Bean,以及它们的关系 |
/env | 获取全部环境属性 |
/configprops | 描述配置属性(包含默认值)如何注入Bean |
/dump | 获取线程活动的快照 |
/health | 报告应用程序的健康指标,这些值由HealthIndicator的实现类提供 |
/info | 获取应用程序的定制信息,这些信息由info打头的属性提供 |
/mappings | 描述全部的URI路径,以及它们和控制器(包含Actuator端点)的映射关系 |
/metrics | 报告各种应用程序度量信息,比如内存用量和HTTP请求计数 |
/shutdown | 关闭应用程序,要求endpoints.shutdown.enabled设置为true |
/trace | 提供基本的HTTP请求跟踪信息(时间戳、HTTP头等) |
原理功能
profile环境切换功能
-
使用步骤:
首先可以创建不同的配置环境:
application.properties/yaml------>默认配置文件
application-prod.properties/yaml------->生产配置文件
application-test.properties/yaml--------->测试生产环境
需要某套配置环境时,可以在默认配置直接指定其生产环境版本
spring: profiles: active: test #指定test生产环境
指定以后,application.properties/yaml+application-prod.properties/yaml都会生效,同名的配置项会以指定版本有效
但我们的项目已经打包以后,同样可以通过命令行指定配置文件
java -jar xxx.jar --spring.profiles.active = prod --spring.xxx.xxx=xxx(也可以去设置配置文件的配置参数)
-
通过@Profile(“xxxx”)指定xxxx的配置文件生效时,该注解作用的类或者是该注解作用的方法生效。
tNull(name);
}static Stream<String> method() { return Stream.of("apple", "banana"); }
}
指标监控
springboot actutor
-
简介:
未来每一个服务都部署在云上后,我们需要对它进行追踪,审计,监控,控制等,springboot就抽取了这么一个场景,springboot actutor,可以使得每个服务都可以快速获取到生产级别的监控,需要导入场景的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
暴露所有的信息在http上
management: endpoints: enabled-by-default: true #开启所有的监控端点 web: exposure: include: '*' #以web的方式暴露所有的监控端点
-
Actuator endpoints监控端点
监控分成两类:原生端点和用户自定义扩展端点,原生的主要有
路径 | 描述 |
---|---|
/autoconfig | 提供了一份自动配置报告,记录哪些自动配置条件通过了,哪些没通过 |
/beans | 描述应用程序上下文里全部的Bean,以及它们的关系 |
/env | 获取全部环境属性 |
/configprops | 描述配置属性(包含默认值)如何注入Bean |
/dump | 获取线程活动的快照 |
/health | 报告应用程序的健康指标,这些值由HealthIndicator的实现类提供 |
/info | 获取应用程序的定制信息,这些信息由info打头的属性提供 |
/mappings | 描述全部的URI路径,以及它们和控制器(包含Actuator端点)的映射关系 |
/metrics | 报告各种应用程序度量信息,比如内存用量和HTTP请求计数 |
/shutdown | 关闭应用程序,要求endpoints.shutdown.enabled设置为true |
/trace | 提供基本的HTTP请求跟踪信息(时间戳、HTTP头等) |
原理功能
profile环境切换功能
-
使用步骤:
首先可以创建不同的配置环境:
application.properties/yaml------>默认配置文件
application-prod.properties/yaml------->生产配置文件
application-test.properties/yaml--------->测试生产环境
需要某套配置环境时,可以在默认配置直接指定其生产环境版本
spring: profiles: active: test #指定test生产环境
指定以后,application.properties/yaml+application-prod.properties/yaml都会生效,同名的配置项会以指定版本有效
但我们的项目已经打包以后,同样可以通过命令行指定配置文件
java -jar xxx.jar --spring.profiles.active = prod --spring.xxx.xxx=xxx(也可以去设置配置文件的配置参数)
-
通过@Profile(“xxxx”)指定xxxx的配置文件生效时,该注解作用的类或者是该注解作用的方法生效。