其实呀,纵观“简历”的一生:
- 从咱们学java基础,勉勉强强为笔试八股题以及所谓java基础知识点开了一个头
- 再到数据库、javaweb、JDBC等,不都是在学咱们要在简历模板中(以及能使用在咱们工作中的东西(不也是在不断填空嘛)要填空的东西嘛。
- 到了框架后,咱们才发现,原来学的东西在框架中翻翻就能找到呀,有的是要翻翻框架的底层构造(反射、设计模式等),有的要在使用框架这个大型简历的时候用,不仅帮咱们融合了学的东西,咱们自己也对如何使用知识或者说框架有了新的认识----------框架大法好方便呀
but,随着社会的发展,时代的进步(依稀想到了每次高中作文的开头),方便好用这一点上,大家一致觉得:越方便越好越好用越好,越越方便越越好用越越好…(当然啦,凡是有两面,理性看待哈)
Part1:说点方言~Spring Boot并并是对Spring功能上的增强,而是提供了一种快速使用 Spring的方式【Spring的功能非常强大,但也有些弊端。比如:我们需要手动去配置大量的参数,在XML中啦、在各种配置文件中啦,没有默认值(SpringBoot中会在...Spring.factories中提供默认值),需要我们管理大量的jar包和它们的依赖。】
。
- 看一哈官网咋王婆卖瓜滴:
- Spring Boot is the starting point for building all Spring-based applications. Spring Boot is designed to get you up and running as quickly as possible, with minimal upfront configuration of Spring.
- 由于
Spring配置太多时显得过于繁琐并且依赖也很难处理
,故SpringBoot横空出世(约定大于配置)(在使用Spring框架进行开发的过程中,需要配置很多Spring框架包的依赖,如spring-core、spring-bean、spring-context等,而这些配置通常都是重复添加的,而且需要做很多框架使用及环境参数的重复配置,如开启注解、配置日志等。Spring Boot致力于弱化这些不必要的操作,提供默认配置,当然这些默认配置是可以按需修改的,快速搭建、开发和运行Spring应用)【使用 Spring 进行开发各种配置过于麻烦比如开启某些 Spring 特性时,需要用 XML 或 Java 进行显式配置。于是,Spring Boot 诞生了
!Spring 旨在简化 J2EE 企业应用程序开发。Spring Boot 旨在简化 Spring 开发(减少配置文件,开箱即用!)
】
- 什么叫约定大于配置呢?或者说如何理解约定优于配置呢?
- Spring Boot 并没有像以前使用 Spring MVC 一样需要指定一大堆关于 HTTP 请求和响应的 XML 配置。事实上,Spring Boot 的运行过程同样还是依赖于 Spring MVC,但是
Spring Boot它把原本需要开发人员指定的各种配置项设置了默认值,并内置在了运行时环境中,例如默认的服务器端口就是 8080,如果我们不需要对这些配置项有定制化需求,就可以不做任何的处理,采用既定的开发约定即可。这就是 Spring Boot 所倡导的约定优于配置(Convention over Configuration)设计理念
。
- Spring Boot 并没有像以前使用 Spring MVC 一样需要指定一大堆关于 HTTP 请求和响应的 XML 配置。事实上,Spring Boot 的运行过程同样还是依赖于 Spring MVC,但是
- 或者说,举个很贴近咱们做项目情景的例子。
- 没有 Spring Boot 的时候,我们写一个 RestFul Web 服务,还首先需要进行如下配置。
- 然后再用配置文件配置组件扫描【扫描哪个包下的类,你这些类肯定通过xml配置文件或者注解已经标识好了身份了】,然后就是注解驱动【注解驱动,主要解决的是SpringMVC那里面的处理器适配器、处理器映射器等】
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context/ http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc/ http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.howtodoinjava.demo" /> <mvc:annotation-driven /> <!-- JSON Support --> <bean name="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/> <bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/> </beans>
- 用了SpringBoot之后,我们只需要添加相关依赖,无需配置,通过启动类中的 main 方法即可启动。并且,我们通过 Spring Boot 的全局配置文件 application.properties或application.yml即可对项目进行设置比如更换端口号,配置 JPA 属性等等。
- 再比如说,咱们用的最多的Redis,直接在项目中引入redis对应的starter即可。
- 我觉得这个starter横空出世就是为了减少我们的工作量,哪些工作量呢,就是
咱们用mybatis、连接redis、连接mongodb、使用rocketmq、使用excel功能等等这些功能的话,需要再把下面的步骤再重复一次又一次,工作量无形当中增加了不少,而且有很多重复的工作
。
- 另外,还是有个问题,每次到要到maven中找合适的版本,如果哪次找的mybatis.jar包 和 mybatis-spring.jar包版本不兼容,程序不是会出现问题?。
SpringBoot为了解决以上两个问题引入了starter机制
。
- 另外,还是有个问题,每次到要到maven中找合适的版本,如果哪次找的mybatis.jar包 和 mybatis-spring.jar包版本不兼容,程序不是会出现问题?。
- 我觉得这个starter横空出世就是为了减少我们的工作量,哪些工作量呢,就是
- 没有 Spring Boot 的时候,我们写一个 RestFul Web 服务,还首先需要进行如下配置。
- 以下是使用SpringBoot的一些好处
- (Springboot用来简化Spring,快速构建一个个功能独立的微服务应用)
- 自动装配,开箱即用,
不用像SSM那样一个项目配置一堆xml文件
(对于很多Spring应用程序常见的应用功能,SpringBoot能自动提供相关默认配置,我们作为开发者集成功能时只需很少的配置
),(自动配置,使用基于类路径和应用程序上下文的智能默认值,当然也可以根据需要重写它们以满足开发人员的需求)- Spring Boot的自动配置是一个运行时 (更准确地说,
是应用程序启动时
)SpringBoot自动完成的过程,SpringBoot考虑了众多因素,才决定Spring配置应该用哪个,不该用哪个
。 - 在使用Spring框架进行开发的过程中,需要配置很多Spring框架包的依赖,如spring-core、spring-bean、spring-context等,
而这些配置通常都是重复添加的,而且需要做很多框架使用及环境参数的重复配置,如开启注解、配置日志等
。Spring Boot致力于弱化这些不必要的操作
,提供默认配置,当然这些默认配置是可以按需修改的,快速搭建、开发和运行
Spring应用。
- Spring Boot的自动配置是一个运行时 (更准确地说,
以后开启某个功能(组件):@EnableXXX,这个放在springboot的核心启动类的main方法上面
- 创建Spring Boot Starter 项目时,可以选择选择需要的功能,Spring Boot将为你管理依赖关系
- 以前咱们需要引入一个有一个依赖,但是SpringBoot帮咱们把很多依赖打包在了一起,咱们只需要引入极个别,然后SpringBoot就会为咱们管理依赖关系。
- SpringBoot项目可以打包成jar文件。可以使用Java-jar命令从命令行将应用程序作为独立的Java应用程序运行(
也就是说,咱们可以打包咱们自己的应用为jar并通过使用java -jar来运行咱们的Spring Web应用
) - 在开发web应用程序时,
springboot会配置一个嵌入式Tomcat服务器
,以便它可以作为独立的应用程序运行。(Tomcat是默认的,当然你也可以配置Jetty或Undertow) - SpringBoot包括许多有用的非功能特性(例如安全和健康检查)
- 什么叫约定大于配置呢?或者说如何理解约定优于配置呢?
当然啦,Springboot的弊端就是:
springboot也因为内嵌了太多的配置呀、依赖呀等等,也比较容易出问题,比如迁移数据库主从分离的时候,很容易陷入依赖的死循环中等。
Part2:新建的SpringBoot应用或者说项目的基本结构:Spring Boot 中文参考文档:http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/pages/getting-started.html#getting-started-first-application
- Part2-1:pom.xml(springboot所有的依赖都是以spring-boot-starter开头的,所以要集成直接往后面续就行,springboot就会帮我们自动导入web环境所有的依赖)
起步依赖:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> //继承spring-boot-start-parent这个父依赖,父依赖可以控制所有SpringBoot官方起步依赖的版本(下来当我们使用官方起步依赖时,就不用指定版本号了) //有一个父项目,父项目名字叫做spring-boot-starter-parent //spring-boot-dependencies的核心依赖在父工程中,你一层一层往里点点到最上面一层后,就可以看到最里面的一层有很多的依赖,咱们只是在咱们springboot项目的pom.xml中进行一个调用而已 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.13-SNAPSHOT</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example.mall.tiny</groupId> <artifactId>demo-mall-prevexercise</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo-mall-prevexercise</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> //我们在写或者引入一些springboot依赖的时候,不需要指定版本,就是因为有pom.xml中这些版本(仓库,仓库里面已经提前写好了很多很多<XXX.version>...</XXX.version>),不一定是在这里,有可能是在这个项目的父项目依赖中,按住ctrl往进点一点就可以看到 //**你那些什么内嵌的tomcat、dispatcherServlet、xml都不都是因为你配置了这个依赖才不用你再配了嘛,springboot帮咱们自动配置了嘛** <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> //SpringBoot插件,可以把应用打包为可执行Jar <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <releases> <enabled>false</enabled> </releases> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <releases> <enabled>false</enabled> </releases> </pluginRepository> </pluginRepositories> </project>
关于上面依赖除了注释之外有几点补充:
- Servlet && 过滤器 && 监听器:
- Springboot中文文档:http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/pages/spring-boot-features.html#boot-features-embedded-container
- servlet:SpringBoot集成servlet,里面就是比如咱们MyServlet extends HttpServlet了的话,那么重写doGet()等方法即可,然后类上加@WebServlet(name = “自定义的servlet名称”, urlPattern = “/对应请求匹配的类”),这个@WebServlet(…)注解就是替代了咱们SSM中的web.xml(中的servlet以及映射等)
- 在启动类上面得加上@ServletComponentScan
- 将自定义的servlet注册到Spring容器中的代码或者说源码【可以使用 ServletRegistrationBean、FilterRegistrationBean和ServletListenerRegistrationBean 类将对应的Servlet、Filter、Listen注册中Spring容器中】。【当配置了ServletRegistrationBean类中的urlMapping参数后,servlet自己的配置就不会生效了】
- Filter
- Listen
- 启动器:指的是pom.xml中的…spring-boot-start-狗…,就指得是一个狗的启动器
**springboot会将所有的功能场景都变成一个一个的启动器**,所以我们想要用什么功能,或者说集成什么功能时就只需要找到对应的启动器就可以了,也就是一个一个狗的启动器,把那几句依赖坐标配上就行。去spring官网,然后找springboot,learn点Dependency version <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-狗</artifactId> </dependency>
- 利器在手,如虎添翼,看看人家SpringBoot官方文档怎么说Starter:
- http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/pages/using-spring-boot.html#using-boot-starter
- 如何理解 Spring Boot 中的 Starters?
- Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成 Spring 及其他技术,而不需要到处找示例代码和依赖包。如你想使用 Spring JPA 访问数据库,只要加入 spring-boot-starter-data-jpa 启动器依赖就能使用了。Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖
- 一个starter的META-INF目录下需要包含:
- pom.protperties 配置maven所需的项目version、groupId和artifactId
- pom.xml 配置所依赖的jar包。pom.xml文件中会引入一些jar包,其中除了引入spring-boot-starter,还有xxx-spring-boot-autocconfigure,这就对应着一个又一个xxx-spring-boot-autocconfigure.jar
- spring-configuration-metadata.json和additional-spring-configuration-metadata.json:spring-configuration-metadata.json和additional-spring-configuration-metadata.json的功能差不多,我们在applicationContext.properties文件中输入spring时,会自动出现下面的配置信息可供选择
- 如果pom.xml中引入了spring-boot-configuration-processor包,则会自动生成spring-configuration-metadata.json。
如果需要手动修改里面的元数据,则可以在additional-spring-configuration-metadata.json中编辑,最终两个文件中的元数据会合并到一起
。
- 如果pom.xml中引入了spring-boot-configuration-processor包,则会自动生成spring-configuration-metadata.json。
- MybatisProperties类是属性实体类:比如以Mybatis为例。
Mybatis初始化所需要的很多属性都在这里,相当于一个JavaBean
。
- MybatisAutoConfiguration:比如以Mybatis为例。
MybatisAutoConfiguration这个类就是一个Configuration(配置类),它里面定义很多bean
,其中最重要的就是SqlSessionFactory的bean实例,SqlSessionFactory实例是Mybatis的核心功能,用它创建SqlSession,对数据库进行CRUD操作。@org.springframework.context.annotation.Configuration @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class }) @ConditionalOnBean(DataSource.class) @EnableConfigurationProperties(MybatisProperties.class) @AutoConfigureAfter(DataSourceAutoConfiguration.class) public class MybatisAutoConfiguration { private static final Logger logger = LoggerFactory.getLogger(MybatisAutoConfiguration.class); private final MybatisProperties properties; private final Interceptor[] interceptors; private final ResourceLoader resourceLoader; private final DatabaseIdProvider databaseIdProvider; private final List<ConfigurationCustomizer> configurationCustomizers; public MybatisAutoConfiguration(MybatisProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider, ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) { this.properties = properties; this.interceptors = interceptorsProvider.getIfAvailable(); this.resourceLoader = resourceLoader; this.databaseIdProvider = databaseIdProvider.getIfAvailable(); this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable(); } @PostConstruct public void checkConfigFileExists() { if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) { Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation()); Assert.state(resource.exists(), "Cannot find config location: " + resource + " (please add config file or check your Mybatis configuration)"); } } @Bean @ConditionalOnMissingBean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setVfs(SpringBootVFS.class); if (StringUtils.hasText(this.properties.getConfigLocation())) { factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); } Configuration configuration = this.properties.getConfiguration(); if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) { configuration = new Configuration(); } if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) { for (ConfigurationCustomizer customizer : this.configurationCustomizers) { customizer.customize(configuration); } } factory.setConfiguration(configuration); if (this.properties.getConfigurationProperties() != null) { factory.setConfigurationProperties(this.properties.getConfigurationProperties()); } if (!ObjectUtils.isEmpty(this.interceptors)) { factory.setPlugins(this.interceptors); } if (this.databaseIdProvider != null) { factory.setDatabaseIdProvider(this.databaseIdProvider); } if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); } if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); } if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { factory.setMapperLocations(this.properties.resolveMapperLocations()); } return factory.getObject(); } @Bean @ConditionalOnMissingBean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { ExecutorType executorType = this.properties.getExecutorType(); if (executorType != null) { return new SqlSessionTemplate(sqlSessionFactory, executorType); } else { return new SqlSessionTemplate(sqlSessionFactory); } } public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware { private BeanFactory beanFactory; private ResourceLoader resourceLoader; @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); try { if (this.resourceLoader != null) { scanner.setResourceLoader(this.resourceLoader); } List<String> packages = AutoConfigurationPackages.get(this.beanFactory); if (logger.isDebugEnabled()) { for (String pkg : packages) { logger.debug("Using auto-configuration base package '{}'", pkg); } } scanner.setAnnotationClass(Mapper.class); scanner.registerFilters(); scanner.doScan(StringUtils.toStringArray(packages)); } catch (IllegalStateException ex) { logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex); } } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } } @org.springframework.context.annotation.Configuration @Import({ AutoConfiguredMapperScannerRegistrar.class }) @ConditionalOnMissingBean(MapperFactoryBean.class) public static class MapperScannerRegistrarNotFoundConfiguration { @PostConstruct public void afterPropertiesSet() { logger.debug("No {} found.", MapperFactoryBean.class.getName()); } } }
- 除此之外,MybatisAutoConfiguration类还包含了下面这一些注解,这些注解都是一些辅助功能,决定Configuration是否生效,当然这些注解不是必须的。
- 除此之外,MybatisAutoConfiguration类还包含了下面这一些注解,这些注解都是一些辅助功能,决定Configuration是否生效,当然这些注解不是必须的。
- spring.factories:spring.factories文件中只有一行配置:(key为EnableAutoConfiguration,value为MybatisAutoConfiguration。)
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
- spring-configuration-metadata.json和additional-spring-configuration-metadata.json:spring-configuration-metadata.json和additional-spring-configuration-metadata.json的功能差不多,我们在applicationContext.properties文件中输入spring时,会自动出现下面的配置信息可供选择
- MANIFEST.MF 这个文件描述了该Jar文件的很多信息
- spring.provides 配置所依赖的artifactId,给IDE使用的,没有其他的作用
- 一个starter的META-INF目录下需要包含:
- springboot会
将所有的功能场景都变成一个一个的启动器
,所以我们想要用什么功能,或者说集成什么功能时就只需要找到对应的启动器就可以了,也就是一个一个狗的启动器,把那几句依赖坐标配上就行
----去spring官网,然后找springboot,learn点Dependency version - springboot就会帮我们自动导入web环境所有的依赖
- Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成 Spring 及其他技术,而不需要到处找示例代码和依赖包。如你想使用 Spring JPA 访问数据库,只要加入 spring-boot-starter-data-jpa 启动器依赖就能使用了。Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖
这个启动器咱们也可以DIY
,思路步骤如下:你要自己实现一个Starter,那你不得有一个项目,第一步,创建threadpool-spring-boot-starter工程【SpringBoot中文文档中创建自己的 Starter:http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/pages/spring-boot-features.html#boot-features-custom-starter
】
- 创建好项目之后,引入 Spring Boot 相关依赖
- 创建redis-spring- boot-autoconfigure模块
- 创建redis-spring- boot starter模块,依赖redis-spring-boot-autoconfigure的模块
- 在redis-spring-boot- autoconfigure模块中初始化Jedis的Bean。
并在创建的工程的resource包行啊创建定义META-INF/spring.factories 文件
- 在测试模块中引入自定义的redis- starter依赖,测试获取Jedis的Bean,操作redis。
举个例子:这个注解的意思就是当这个bean不存在的时候,后面这个name=类名,这个类才生效。那当咱们自己写了与这个类名同名的类后相当于这个类已经存在了,那么相当于默认的类这个bean就被咱们给替换掉了
Spring Boot Starter 的工作原理是什么?
- Spring Boot 在启动的时候会干这几件事情:总结一下,
其实就是 Spring Boot 在启动的时候,按照约定去读取 Spring Boot Starter 的配置信息,再根据配置信息对资源进行初始化,并注入到 Spring 容器中
。这样 Spring Boot 启动完毕后,就已经准备好了一切资源,使用过程中直接注入对应 Bean 资源即可Spring Boot 在启动时会去依赖的 Starter 包中寻找 resources/META-INF/spring.factories 文件,然后根据文件中配置的 Jar 包去扫描项目所依赖的 Jar 包
根据 spring.factories 配置加载 AutoConfigure 类
根据 @Conditional 注解的条件,进行自动配置并将 Bean 注入 Spring Context
- Spring Boot 在启动的时候会干这几件事情:总结一下,
- 利器在手,如虎添翼,看看人家SpringBoot官方文档怎么说Starter:
- spring-boot-starter-parent起步依赖:像上面代码中说的,把这个
spring-boot-starter-parent源码,
点进去之后
- 再往进点,就到了spring-boot-dependencies中:
下面都是一些技术的版本信息:可以说,项目中的版本信息都来自父工程,就是为了防止冲突
。在spring-boot-starter-parent中定义了各种技术的版本信息,组合了一套最优搭配的技术版本。
【在各种starter中,定义了完成该功能需要的坐标合集
,其中大部分版本信息来自于父工程。我们的工程继承parent,引入starter后, 通过依赖传递,就可以简单方便获得需要的jar包,并且不会存在版本冲突等问题。
】
- 再往进点,就到了spring-boot-dependencies中:
- Part2-2:src/main/java/XXXXXApplication.java:应用程序启动类,起配置和引导的作用
启动run()方法相当于开启了一个服务
,SpringApplication这个类调用的run()方法主要做了四件事情【SpringBoot的run()方法启动源码解析:https://github.com/AIminminAI/MindMaps/blob/main/SpringBoot%E7%9A%84run()%E6%96%B9%E6%B3%95%E5%90%AF%E5%8A%A8%E6%BA%90%E7%A0%81.png】- 推断应用的类型是普通的项目还是Web项目,用无参构造(无参构造本来生来就是用来进行初始化数据的)初始化数据
- 查找并加载所有可用的初始化器,设置到initializers属性中
- 找出所有的应用程序监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
- Part2-3:src/main/resource下的
这里面主要有两种配置(读取配置文件的自定义属性:springboot在自动配置很多组件的时候,会先去看spring容器中有没有用户自己配置的(当用户在yml配置文件中配了端口、属性等信息时,相当于用户没有用autoconfig.jar下的META-INF下的spring.factories中的很多配置类中用注解引入或者叫绑定的配置文件中的默认属性,自己给配置文件的属性赋了新值,就叫做容器中有了用户自己配置的))文件值得好好注意一下:
- properties:application.properties或者说xxx.properties配置文件:比如server.port=8080
- yml配置文件:
YAML文件的扩展名可以使用.yml或者.yaml
。也就是说两个差不多
- yaml配置文件:YAML全称是YAML Ain’t Markup Language。YAML是一种直观的能够被电脑识别的的数据数据序列化格式,并且容易被人类阅读,容易和脚本语言交互的,可以被支持YAML库的不同的编程语言程序导入,比如: C/C+ +, Ruby, Python, Java, Perl, C#, PHP等。
YML文件是以数据为核心的,比传统的xml方式更加简洁
。- springboot在自动配置很多组件的时候,会先去看spring容器中有没有用户自己配置的(当用户在yml配置文件中配了端口、属性等信息时,相当于用户没有用autoconfig.jar下的META-INF下的spring.factories中的很多配置类中用注解引入或者叫绑定的配置文件中的默认属性,自己给配置文件的属性赋了新值,就叫做容器中有了用户自己配置的)
这里面咱们经常用的时候,需要注意一下他的语法格式:
参数引用:
- properties:application.properties或者说xxx.properties配置文件:比如server.port=8080
- 读取SpringBoot配置内容的方式有三种:很多时候我们需要将一些常用的配置信息比如阿里云 oss、发送短信、微信认证的相关配置信息等等放到配置文件中。
- @Value:
比较常用,使用 @Value("${property}") 读取比较简单的配置信息
:
- Environment
- @ConfigurationProperties:比较常用,
通过@ConfigurationProperties读取配置信息并与 bean 绑定,或者说让配置内容和对象相互绑定
【可以像使用普通的 Spring bean 一样,将其注入到类中使用】- 在yml配置文件中可以直接给实体类赋值:
给实体类上写:@ConfigurationProperties(prefix = "实体类名小驼峰")。记住,当时写代码碰到的坑,每个业务类都有1/4的身份标识注解哦
- 给实体类传值之前在SSM中咱们是这样干的:
- 现在在springboot中的yml配置文件里咱们是直接在yml配置文件中进行注入赋值等操作:【不写前缀,就会注入到一个同名的普通属性中,而不是对象的属性中,不就出错了嘛】
- 把SpringBoot配置文件(xxx.properties或者yaml或者yml)中的配置信息赋到实体中(假如现在咱们在配置文件中配置了一个Person实体),在实体中怎么搞才能把配置文件中的信息拉到自己体内。常用的有两种方法:【
@Value 和 @ConfigurationProperties 的区别:https://cloud.tencent.com/developer/article/1522660
】- 给每个属性上面:@Value(“配置文件中的实体.实体的属性”),这也太麻烦了,给每个都加
给实体类上写:@ConfigurationProperties(prefix = "实体类名小驼峰")。记住,当时写代码碰到的坑,每个业务类都有1/4的身份标识注解哦
- 给实体类传值之前在SSM中咱们是这样干的:
- 此时就引出了,
人家SpringBoot已经提前给咱们把DataSource、mvc等的配置信息写好了,那咱们用咋用,不就是@ConfigurationProperties(prefix = "实体类名小驼峰")嘛【相当于这个@ConfigurationProperties(prefix = "实体类名小驼峰")货就把实体类名小驼峰里面的信息从配置文件中拉到/赋值到/装到某个类肚子里面了】,那这个@ConfigurationProperties(prefix = "实体类名小驼峰")的原理咱不看看能行?
- 在yml配置文件中可以直接给实体类赋值:
- @@PropertySource(不常用):@PropertySource读取指定 properties 文件,@PropertySource(“classpath:xxx.properties”)
- @Value:
- Spring Boot中如何实现
对不同环境的属性配置文件的支持
:
你没有IDEA这些开发工具时,只能用虚拟机参数或者命令行参数时怎么办?对吧。就只能在命令行窗口中执行这些命令。
- Spring Boot支持不同环境的属性配置文件切换
- 通过创建application-{profile}.properties文件,其中{profile}是具体的环境标识名称【相当于我们
可以把不同环境的配置分别配置到单独的文件中
,看每个文件第一行的 profile=“”。当然,我们也可以在一个配置文件中使用:】,例如:
- application-dev.properties用于开发环境,
- 如果要想使用application-dev.properties文件,则在application.properties文件中添加spring.profiles.active=dev。
- application-test.properties用于测试环境,
- 如果要想使用application-test.properties文件,则在application.properties文件中添加spring.profiles.active=test。
- application-pro.properties用于生产环境,
- application-uat.properties用于uat环境。
- 【
Spring 在启动的过程中,会去这几个地方寻找 spring.profiles.active 的属性值:操作系统环境变量、JVM 系统变量、web.xml 中定义的参数、JNDI。寻找 “spring.profiles.active” 的属性值后根据这个属性值来的
。】如果要想使用application-dev.properties文件,则在application.properties文件中添加spring.profiles.active=dev
- 如果要想使用application-test.properties文件,则在application.properties文件中添加spring.profiles.active=test
- 【
- application-dev.properties用于开发环境,
- 通过yml多文档方式,例如:
- 最简单的方式莫过于在程序启动的时候指定:-Dspring.profiles.active=“profile1,profile2”
- 如果是
Spring Boot 的话我们一般会创建 application.properties、application-dev.properties、application-prod.properties 等文件,其中 application.properties 配置各个环境通用的配置,application-{profile}.properties 中配置特定环境的配置,然后在启动的时候指定 profile
:java -Dspring.profiles.active=prod -jar JavaDoop.jar - 如果是单元测试中使用的话,在测试类中使用 @ActiveProfiles 指定
- 如果是
- 当然,我们也可以通过代码的形式从 Environment 中设置 profile:
- 通过创建application-{profile}.properties文件,其中{profile}是具体的环境标识名称【相当于我们
- Spring Boot支持不同环境的属性配置文件切换
- 新建的SpringBoot应用或者说项目的基本结构还有最后一个就是:src/test/java/XXXXXApplicationTests.java:基本的集成测试类,有时候要在springboot中写其他测试类时可以仿照这个集成测试类中的格式去写
//用@RunWith和@SpringBootTesy来创建Spring应用上下文 @RunWith(SpringRunner.class) @SpringBootTest public class MallTinyApplicationTests { ...... //@Test注解来声明一个测试方法 @Test public void testMethod() { ...... } }
- 有了Spring Boot Test我们就不需要再使用main方法来测试了
- JUnit是一款Java语言的单元测试框架,目前大多数Java开发环境都已经支持它了。
JUnit测试也就是所谓的白盒测试,在程序员知道程序内部逻辑的基础上进行的测试
,使用JUnit能让我们快速地完成单元测试。Spring Boot Test将JUnit和其他测试框架结合起来,提供了便捷高效的测试手段,目前Spring Boot 2.7版本采用的是JUnit 5。JUnit 5官方文档 - Spring Boot Test常用的注解: macrozheng老师关于Spring Boot Test常用的注解的基本使用,很详细,值得一看
- SpringBootTest的使用步骤:
- 在项目中集成Spring Boot Test的话,需要先在pom.xml中添加如下依赖
使用@SpringBootTest注解启用单元测试,使用@Test指定测试方法,使用Assertions类的方法来断言结果是否符合预期
,点击测试方法左侧按钮即可进行测试。执行完成后我们在IDEA的执行窗口中就可以看到方法测试通过了,由于使用@SpringBootTest启用了Spring Boot环境,日志中会输出Spring Boot的banner。
- 在项目中集成Spring Boot Test的话,需要先在pom.xml中添加如下依赖
- 一般咱们实战中,设计好数据库以及实体这些之后,就是先测
Dao层---->Service层---->Controller层
,- Dao层测试:如果我们的项目需要对数据访问层Dao中的方法进行测试的话,
直接注入Mapper接口,在测试方法中直接调用即可
- 例子这里对根据ID查询品牌的Mapper方法进行测试。
- 例子这里对根据ID查询品牌的Mapper方法进行测试。
- Service层测试:对业务层Service中的方法测试也是一样的,
直接注入Service接口,在测试方法中直接调用即可
- 例子这里对根据ID查询品牌的Service方法进行测试。
- 例子这里对根据ID查询品牌的Service方法进行测试。
- Controller层测试:
对于Controller层方法进行测试,有时我们需要模拟请求,使用MockMvc即可
- 例子这里模拟测试下分页查询品牌列表的接口。
- 例子这里模拟测试下分页查询品牌列表的接口。
- Dao层测试:如果我们的项目需要对数据访问层Dao中的方法进行测试的话,
- JUnit是一款Java语言的单元测试框架,目前大多数Java开发环境都已经支持它了。
- 有了Spring Boot Test我们就不需要再使用main方法来测试了
不管是测试代码还是其他代码,用到这两个注解,他的作用就是这样的:
ok,上面说了这么多,总结就是,其实作为 Spring 家族新的一员,Spring Boot 提供了令人兴奋的特性,这些特性的核心价值在于确保了开发过程的简单性,具体体现在编码、配置、部署、监控等多个方面。【首先,Spring Boot 使编码更简单。我们只需要在 Maven 中添加一项依赖并实现一个方法就可以提供微服务架构中所推崇的 RESTful 风格接口。】、【其次,Spring Boot 使配置更简单。它把 Spring 中基于 XML 的功能配置方式转换为 Java Config,同时提供了 .yml 文件来优化原有基于 .properties 和 .xml 文件的配置方案,.yml 文件对配置信息的组织更为直观方便
,语义也更为强大。同时,基于 Spring Boot 的自动配置特性,对常见的各种工具和框架均提供了默认的 starter 组件来简化配置
。】、【最后,在部署方案上,Spring Boot 也创造了一键启动的新模式。】、【另外,基于 Spring Boot 新提供的 Actuator 组件,开发和运维人员可以通过 RESTful 接口获取应用程序的当前运行时状态并对这些状态背后的度量指标进行监控和报警。例如可以通过“/env/{name}”端点获取系统环境变量、通过“/mapping”端点获取所有 RESTful 服务、通过“/dump”端点获取线程工作状态以及通过“/metrics/{name}”端点获取 JVM 性能指标等。】
概念特点小杂烩到此结束…baibai
巨人的肩膀:
https://www.bilibili.com/video/BV1PE411i7CV?p=60
https://www.javalearn.cn/
小姐姐养的狗老师关于Spring Boot 性能优化的文章
苏三说技术