java——springboot(1)
springboot需要一个主程序类,通过@SpringBootApplication来标注,例:
@SpringBootApplication public class LzjSts2Application { public static void main(String[] args) { SpringApplication.run(LzjSts2Application.class, args); } }
这里的这个标注@SpringBootApplication所起到的作用我们可以看代码:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication {
@SpringBootConfiguration:表示这是springboot的一个配置类;
而之所以spring-boot几乎不用写什么配置文件就在于@EnableAutoConfiguration这个标注类;里面是:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {
这里的@AutoConfigurationPackage会使得容器扫描主程序类所在包以下的所有子包,相当于之前做配置时的扫描功能;而AutoConfigurationImportSelector.class这个是自动导入配置的选择器;里面定义了一个selectImports()方法将要导入的组件类名以String[]的形式返回。这些组件就会被添加到容器中;同时也会导入这些组件所对应的自动配置类:(xxxAutoConfiguration);而这些自动配置类其实是存在于依赖的jar包里:
至此,springboot就仅仅通过一个@SpringBootApplication标注就把我们之前需要大量配置的步骤都给省略了;
pom.xml解析:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
这个父项目里面还有个父项目spring-boot-dependencies,这里面就定义好了各种导入依赖的版本,Spring Boot的版本仲裁中心;
spring-boot-starter:spring boot场景启动器,帮我们导入 了各种模块正常运行时所依赖的组件;
spring-boot的资源目录:
默认的全局配置文件名是固定的:
application.properties和application.yml;
主要来说下yml格式的配置文件,这是以数据为中心的文件,因为里面省略的大量的标签及无实际意义的标注符号,其基本的语法:k:(空格)v,通过左缩进来表示子级关系,同一列的左缩进其层级相同,列表里的元素通过-(空格)v来表示,也可以通过[]中括号、里面用,逗号隔开来表示;大小写敏感;---三短横杆可以在一个文档分成多文档;
获取全局配置文件的数据:
可以通过@ConfigurationProperties(prefix = "xxx"),这个xxx是表示在yml文件中具体对应的元素;
@ConfigurationProperties就是告诉springboot将本类中所有的属性和配置文件相关的配置进行绑定;而如果要想@ConfigurationProperties起作用,那它所标记的类一定得是容器的组件,也就是说它得被@Component标注;
在做配置文件时可以导入spring-boot-configuration-procrssor这个文件处理器依赖,这样在文件进行绑定时就会有提示;
可以通过@Value来传值:
如:
所谓的松散绑定就是用“_”或“-”后接小写字母都表示是大写字母,即:
firstName == first-name
数据校验指的是可以限定变量是哪种类型的,如
如果lastName通过配置文件所注入的值不是邮箱的格式,那么就会报错;
复杂类型封装是指如Map、对象封装之类的数据类型,Value并不能直接表示一个对象‘;
-------------------------------------------------------------------------------------------------------------------------------
突然想做个备注:@RestController注解相当于@ResponseBody + @Controller合在一起的作用。
-------------------------------------------------------------------------------------------------------------------------------
@PropertySource:加载指定的配置文件
@ImportResource:导入Spring的配置文件,让配置文件生效,因此这个标准是标注在一个配置类里的,如主配置类中:
但是这种导入并不值得提倡,常用的还是编写配置类,如:
@Configuration //指明配置类 public class MyAppConfig{ @Bean//将方法的返回值加入组件中,且其名字即是方法名 public HelloService helloService(){ return } }
上述这种添加配置文件的方法才是Spring提倡的,这和springmvc其实是一致的。
springboot里可以使用${app.name}来指定某个值,如果找不到该值想使用默认值的话只需通过冒号后引入即可,如${app.name:默认值}
Profile多环境支持:如
默认的配置文件是application.properties;
当我们想在不同环境运行时,如在开发环境中使用开发配置文件,生产环境中使用生产配置文件,这个时候我们可以同过编写配置文件application-{profile}.properties,如:application-dev.properties或application-prod.properties;然后激活对应的profile即可,激活的方式有以下几种:
1、在默认配置文件中激活指定的profile,如spring.profiles.active=dev;加上这个生命后,程序运行所使用的就是application-dev.properties这个配置文件了;
2、在启动时命令行中指定--spring.profiles.active=dev激活;这里包括直接测试时在命令行加入,也可在打包后运行jar文件时加入,都能起到效果
3、虚拟机激活,在虚拟机运行参数中加入参数-Dspring.profiles.active=dev;
SpringBoot配置文件的加载路径:
所有配置都会被加载,即会形成一种互补机制;
外部配置的加载顺序:
自动配置原理:
以一个例子来说明如何实现自动配置:
@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(ServerProperties.class)//启用指定类的ConfigurationProperties功能; @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)//判断当前应用是不是web应用,如果是这个配置类才会生效 @ConditionalOnClass(CharacterEncodingFilter.class)//判断当前项目有没有这个类 @ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)//判断配置文件是否有server.servlet.encoding=true;如果没有,其实也是默认true的;
public class HttpEncodingAutoConfiguration {
点进去ServerProperties这个类中,截取部分内容如下:
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public class ServerProperties { /** * Server HTTP port. */ private Integer port; /** * Network address to which the server should bind. */ private InetAddress address; @NestedConfigurationProperty private final ErrorProperties error = new ErrorProperties(); /** * Strategy for handling X-Forwarded-* headers. */ private ForwardHeadersStrategy forwardHeadersStrategy;
这里就表明了我们配置文件能配置哪些信息了,如:server.port、server.address、server.forwardHeadersStrategy等等;
也就是这个类前面的种种标准都是用来判断这个配置类是否生效?如果生效,下面的代码:
@Bean @ConditionalOnMissingBean public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE)); return filter; }
即为容器加入一个CharacterEncodingFilter组件,而该组件所用的值this.properties.getCharset().name()就是根据
@EnableConfigurationProperties(ServerProperties.class)//启用指定类的ConfigurationProperties功能;
这个指定类所对应的properties配置了;
对于自动配置类是否加载组件进容器,是需要在一定条件下才能生效的,大部分会通过@Conditional来判断是否生效;而怎么才能知道哪些配置类有用哪些没用呢?
可以在配置文件里配置debug=true属性,来让控制台打印自动配置报告,这样就可以很方便知道哪些自动配置类生效;
这里的自动配置类原理比较重要,也算是以后熟络Spring-Boot的必经之路,做下总结: