Spring Boot 学习(二)特点

    xiaoxiao2021-03-25  56

    一、SpringApplication

    banner,就是启动时输出的信息,可以在classpath下添加 banner.txt,或者设置 banner.location 来指向特定的文件。(默认编码utf-8,或者通过banner.charset指定) 除了txt,你还可以使用 banner.gif (jpg / png),或者设定 banner.imgage.location。 下面是默认的banner(忽略吧,没意义的东西): banner变量,只有应用相关的信息,略,见pdf。 还可以使用通过 SpringApplication.setBanner(…) 来设置。通过实现 org.springframework.boot.Banner 接口,可以实现自己的 printBanner() 。 通过设置 spring.main.banner-mode 来决定是否在  System.out  (console) 上显示banner。使用配置的logger (log)或者全不用 (off)。  输出的banner会被注册成一个单例的bean,名字springBootBanner。     如果,你想创建一个分层次的ApplicationContext (多个context,有父子关系),可以使用  SpringApplicationBuilder 。它可以让你链式调用方法,并且设置父子关系。如下: new SpringApplicationBuilder() .bannerMode(Banner.Mode.OFF) .sources(Parent.class) .child(Application.class) .run(args);

    SpringApplicationBuilder使用起来有一些限制,详见javadoc。     Application事件和监听器 除了Spring框架的事件(如ContextRefreshedEvent)之外,SpringApplication还提供了一些额外的事件。 但是,有些事件是在ApplicationContext创建之前,所以无法通过@Bean形式注册监听器。可以通过SpringApplication.addListeners(…) 或者 SpringApplicaitonBuilder.listeners(…) 来注册。 另外,如果想以与application创建形式无关的方式来注册listeners,可以这样做:创建一个 META-INF/spring.factories 文件。内容如下: org.springframework.context.ApplicationListener=com.example.project.MyListener

    多个监听器,应该用逗号连接吧???   Application Events,以下面的顺序发送: ApplicationStartedEvent 应用启动时发送,是除了注册监听器和初始化之外最早的。ApplicationEnvironmentPreparedEvent 创建context之前,已知道context需要使用的Environment时。ApplicationPreparedEvent 发生在context刷新之前,但在bean 定义加载之后。ApplicationReadyEvent 发生在刷新和任何相关回调被处理之后,表明应用已准备好响应请求了。ApplicationFailedEvent 发生在启动期间发生异常时。 没必要使用这些事件,但是了解一下还是挺有用的。Spring Boot内部使用这些事件来处理很多任务。   Web 环境 SpringApplication 会试图创建正确的 ApplicationContext。默认的,使用 AnnotationConfigApplicationContext 或者 AnnotationConfigEmbeddedWebApplicationContext ,这取决于是否web应用。 可以使用覆盖 setWebEnvironment(boolean webEnvironment) 默认设置。 也可以使用 setApplicationContextClass(…) 来控制 ApplicationContext 的类型。 注意:当在JUnit环境下使用SpringApplication时,通常需要设置 setWebEnvironment(false) 。   访问应用的参数 如何访问传递给SpringApplication.run(…) 的参数? 你可以注入一个 org.springframework.boot.ApplicationArguments bean。这是一个接口,提供了 String[] 和 option/non-option 参数形式。 import org.springframework.boot.* import org.springframework.beans.factory.annotation.* import org.springframework.stereotype.* @Component public class MyBean { @Autowired public MyBean(ApplicationArguments args) { boolean debug = args.containsOption("debug"); List<String> files = args.getNonOptionArgs(); // if run with "--debug logfile.txt" debug=true, files=["logfile.txt"] } }

     

    注意,Spring Boot还会在Spring Environment中注册一个 CommandLinePropertySource 。它可以让你使用 @Value 注解注入application argument。 就是,如果有argument –larry.name=larry,那么可以使用@Value(“${larry.name}”}String larryName;  

    ApplicationRunner or CommandLineRunner

    如果想在SpringApplication启动后执行一些特定的代码,可以让这些代码实现  ApplicationRunner  or CommandLineRunner 接口。二者都提供了一个run(),可以在SpringApplication.run(…) 完成之前被调用。 区别: CommandLineRunner 只提供对传递参数的默认访问形式 String[],而  ApplicationRunner 则使用了上面提到的 ApplicationArguments 接口。 import org.springframework.boot.* import org.springframework.stereotype.* @Component public class MyBean implements CommandLineRunner { public void run(String... args) { // Do something... } }

    如果,定义了多个  CommandLineRunner  or ApplicationRunner beans,那么可以通过实现 org.springframework.core.Ordered 接口或使用 org.springframework.core.annotation.Order 注解来控制加载顺序。   Application exit 每一个 SpringApplication 都注册了一个shutdown hook with JVM,以确保 ApplicationContext 顺利的关闭。所有的Spring生命周期中的回调(如 DisposableBean 接口,或者 @PreDestroy 注解)都可以使用。 另外,如果想在应用退出时返回特定的exit code,那beans可以实现 org.springframework.boot.ExitCodeGenerator 接口。 个人经验:同样可以使用@Order控制顺序,只不过相反。 个人经验:使用@Order控制的顺序,不能打破大的顺序。例如上面(ApplicationRunner or CommandLineRunner)的顺序,永远在SpringApplication启动完成之前调用。

    Admin features(略)

     

    Externalized Configuration(需要认真看看)

    外来配置?就是说,通过设定这些配置,可以在不同的工作环境下运行相同的代码达到相同的目的。 Spring Boot支持的:properties文件、yaml文件、environment 变量、命令行参数。 然后,可以通过 @Value 注解注入到bean中,或者通过Spring 的 Environment 访问,或者通过 @ConfigurationProperties  绑定到结构化对象中。 个人经验:@Value 的工作是在SpringApplication启动完成 之后进行的,在此之前值为null。 注意:不同方式的配置的优先级不一样。基本上,除了测试情况外,命令行参数优先级最高。尤其要注意指定profile下的优先级比默认的高。具体如下: @TestPropertySource annotations on your tests.Command line arguments.Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property)ServletConfig init parameters.ServletContext init parameters.JNDI attributes from java:comp/env.Java System properties (System.getProperties()).OS environment variables.A RandomValuePropertySource that only has properties in random.*.Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)Application properties outside of your packaged jar (application.properties and YAML variants).Application properties packaged inside your jar (application.properties and YAML variants).@PropertySource annotations on your @Configuration classes.Default properties (specified using SpringApplication.setDefaultProperties).  

     Configuring random values

    RandomValuePropertySource 用于注入随机数值,它可以生成int、long、uuid 或者 字符串。如下: my.secret=${random.value} my.number=${random.int} my.bignumber=${random.long} my.uuid=${random.uuid} my.number.less.than.ten=${random.int(10)} my.number.in.range=${random.int[1024,65536]}

     

    Accessing command line properties

    默认,SpringApplication会将任何命令行参数(以–开头,如–server.port=8900)转成一个property,并添加到Spring Environment中。 再次强调:命令行参数的优先级最高。 如果不想添加到Spring Environment中,你可以禁用它们: SpringApplication.setAddCommandLineProperties(false) 。   关于application.properties文件 SpringApplication默认从以下地址加载,并添加到Spring Environment 中。 /config / classpath/ classpath/config

    注意,优先级从上往下依次降低。 如果不想使用默认的名字,可以自行指定(两种方式): java -jar myproject.jar --spring.config.name=myproject java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

    注意,默认的加载地址 永远有效,但可以添加新的,且新的地址的优先级更高。 注意,多数系统的环境变量不允许使用点分隔的键名,可以使用下划线代替。如: SPRING_CONFIG_NAME 代替 spring.config.name 。 另外,如果在容器中执行,还可以使用JNDI properties或者 Servlet Context初始化参数。   Profile-specific properties 在 application.properties 之外,还会加载 application-{profile}.properties 。由于 Environment 提供了一个默认的profile,所以,默认还会加载 application-default.properties 。 奇怪,这什么意思: If you have specified any files in spring.config.location, profile-specific variants of those files will not be considered. Use directories in `spring.config.location` if you also want to also use profile-specific properties.   properties中的占位符 application.properties 中的值是按顺序加载到已有的 Environment 中,所以,后面的值可以使用前面的值,使用方法就是占位符。如下: app.name=MyAppapp.description=${app.name} is a Spring Boot application 可以利用该技术创建短的变量?   YAML是JSON的超集!(略) classpath中只要有SnakeYAML 库,SpringApplication就可以自动支持YAML。 而,Starters默认就含有SnakeYAML 库。   类型安全的Configuration Properties 这里的意思是说,通过Java类来确保类型安全,但 值还是要在YAML中提供!!! @ConfigurationProperties(prefix="connection") public class ConnectionProperties { private String username; private InetAddress remoteAddress; // ... getters and setters }

    那么,@Value(“${property}”)  和@ConfigurationProperties 的区别? 暂略。 注意: 通过 @ConfigurationProperties 类进行的properties设置,需要在 @Configuration 类上开启 @EnableConfigurationProperties 注解才行,而且,需要手动添加 @ConfigurationProperties  类,如下: @Configuration @EnableConfigurationProperties(ConnectionProperties.class) public class MyConfiguration { }

     

    需要注意的是, @ConfigurationProperties 类对应的bean有一个约定好的名字:  <prefix>-<fqn> 。fqn是full qualified name。 前面的例子,对应的名字是: connection-com.example.ConnectionProperties ,这里假定它在包 com.example 中。 但是,@ConfigurationProperties 类对应的bean还有一个默认的名字!!!只是,不建议在environment之外使用而已。   除了上面的红字部分,由于 @EnableConfigurationProperties 注解 会被自动应用到项目中,所以,只要确保 @ConfigurationProperties 类 是一个bean(即@Component),就会被自动添加到 Environment 。如下: @Component //确保是一个bean即可! @ConfigurationProperties(prefix="connection") public class ConnectionProperties { // ... getters and setters of username and remoteAddress, and so on }

    这种形式的配置可以和YAML配置完美的配合。为什么要配合? 因为上面只是类型安全,没有值!!! # application.yml connection: username: admin remoteAddress: 192.168.1.1 # additional configuration as required

      个人经验:奇怪,为什么STS提示我在pom中添加spring-boot-starter-configxxxxx ? 提示:使用 @ConfigurationProperties,还可以生成meta-data文件,以供IDE使用。   第三方配置? @ConfigurationProperties 还可以用于 @Bean 方法上。如下: @ConfigurationProperties(prefix = "foo") @Bean public FooComponent fooComponent() { ... }

    这样,就是给bean加一个前缀,这个bean就可被用作ConfigurationProperties了!!!! 貌似也没别的了,一个bean而已。   灵活的绑定:是指对名字的匹配 例如: @ConfigurationProperties(prefix="person") public class OwnerProperties { private String firstName; public String getFirstName() { return this.firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } }

     

    这里的 firstName 可以绑定如下内容: person.firstNameStandard camel case syntax.person.first-nameDashed notation, recommended for use in.properties and .yml files.person.first_nameUnderscore notation, alternative format for use in .properties and .yml files.PERSON_FIRST_NAMEUpper case format. Recommended when using a system environment variables.

    Properties conversion,转换,类似SpringMVC的转换 如果要自定义类型转换,三种方式:创建一个 ConversionService bean,或者创建一个 property editors(通过 CustomEditorConfigurer bean),或者创建一个 Converters (@ConfigurationPropertiesBinding)。 注意:这个bean在应用早期被调用,所以,注意限制它的依赖!   @ConfigurationProperties validation Spring Boot默认使用JSR-303去校验,所以可以使用JSR-303的注解。如下: @ConfigurationProperties(prefix="connection") public class ConnectionProperties { @NotNull private InetAddress remoteAddress; // ... getters and setters }

    如果有嵌套属性,需要使用@Valid来触发校验。如: @ConfigurationProperties(prefix="connection") public class ConnectionProperties { @NotNull @Valid private RemoteAddress remoteAddress; // ... getters and setters public static class RemoteAddress { @NotEmpty public String hostname; // ... getters and setters } }

     

    也可以使用自定的Spring Validator,bean id是 configurationPropertiesValidator 即可。 注意: spring-boot-actuator 模块有一个端点,对外暴露了所有的 @ConfigurationProperties beans。浏览器中访问 /configprops 即可。也可以使用相应的JMX端点??? 个人经验:其实还有很多地址,详见启动信息。如下:     @Value(“${property}”)  和@ConfigurationProperties 的区别 @Value 是core container的feature。不支持灵活绑定,不支持Meta-data。但支持spELl。 @ConfigurationProperties 则支持灵活绑定,支持Meta-data。但不支持spELl。 官方指导里 推荐使用后者。   Profiles @Profile 可以用于 @Component 或 @Configuration 。 使用  spring.profiles.active Environment property 来指定运行时的 profile 。如: #application.properties spring.profiles.active=dev,hsqldb #command line argument –spring.profiles.active=dev,hsqldb

    有时候,添加profile 比替换profile 更有用。 spring.profiles.include property 可以做到无条件的添加profile。 SpringApplication也提供了API来添加profile: setAdditionalProfiles() 。 还可以使用 Spring的 ConfigurableEnvironment 接口(实验了下,太麻烦,不建议使用)。 问题:@Profile在类上和在方法上,是怎么结合的???怎么出问题了。     Logging Spring Boot 使用JCL接口,但未指定实现。默认的实现包括JUL、Log4j2、Logback。均已设置console输出。 如果使用Starter模块,则使用Logback。 Log Level:ERROR, WARN, INFO, DEBUG or TRACE 注意,Logback没有FATAL,如果设置了FATAL,会被映射成ERROR。 开启debug模式:–debug,或者在 application.properties:debug=true。 注意,是debug模式,不是DEBUG Level。   彩色输出 终端支持ANSI才行,不过现在还有不支持的吗? 需要设置 spring.output.ansi.enabled 。 STS中以Spring Boot Application启动时,应该默认设置了。 问题是,为什么我直接以Java Application启动就不行?– 因为没有设置颜色。囧~~   File output 默认Log只会ouput到console。如果想输出到File,应该设置  logging.file 或者 logging.path  property 。 注意:输出文件大小到达10 Mb时,会重新开始? 注意:logging系统是在应用的早期初始化的,所以,不能在通过 @PropertySource 加载的文件中配置。 注意:logging properties 与实际的logging系统无关,所以,Spring Boot不会管理具体的配置文件,如 logback.configurationFile 或 logback.xml 。  会加载,会执行,但与Spring Boot无关,是logging系统自己的东西。   Log Levels 所有Spring Boot支持的logging系统,都可以在Spring Environment 中设置(如application.properties),格式:logging.level.*=LEVEL。 其中,LEVEL可以是TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF。 root logger可以使用 logging.level.root 设置。如下: logging.level.root=WARN logging.level.org.springframework.web=DEBUG logging.level.org.hibernate=ERROR

     

      自定义log配置 可以使用不同的logging系统, 只要在classpath中添加相应的jars即可。更进一步,还可以在classpath提供一个相应的配置文件,或者在一个指定的位置(需要使用 logging.config 来指定)。 也可以使用一个特定的logging系统,使用 org.springframework.boot.logging.LoggingSystem  来指定,注意,该键对应的值是具体logging实现的全路径,如为none,则默认完全禁用Spring Boot的logging配置。 再次提醒:logging系统初始化较早,不能使用 @Configuration 里的 @PropertySources 来控制。   根据不同的logging实现,加载不同的配置文件。如下: Logbacklogback-spring.xml, logback-spring.groovy, logback.xml or logback.groovyLog4j2log4j2-spring.xml or log4j2.xml

    JDK (Java Util Logging)

    logging.properties

    注意:官方建议使用 -spring的文件名,否则Spring不能完全控制log初始化(因为初始化太早)。

    警告:直接运行fat jar时,JUL会有问题,建议避免使用它。   个人问题: Spring Environment 和 System properties 什么关系?为什么书上说一些properties会从前者传到后者,以帮助自定义? Spring EnvironmentSystem PropertyCommentslogging.exception-conversion-wordLOG_EXCEPTION_CONVERSION_WORDThe conversion word that’s used when logging exceptions.异常?例外?logging.fileLOG_FILEUsed in default log configuration if defined.logging.pathLOG_PATHUsed in default log configuration if defined.logging.pattern.consoleCONSOLE_LOG_PATTERNThe log pattern to use on the console (stdout). (Only supported with the default logback setup.) 仅支持默认logback设置。logging.pattern.fileFILE_LOG_PATTERNThe log pattern to use in a file (if LOG_FILE enabled). (Only supported with the default logback setup.) 仅支持默认logback设置。logging.pattern.levelLOG_LEVEL_PATTERNThe format to use to render the log level (default %5p).(Only supported with the default logback setup.)  仅支持默认logback设置。PIDPIDThe current process ID (discovered if possible and when not already defined as an OS environment variable).

    注意,如果要使用占位符,应该使用Spring Boot的,而非Spring的。 例子就是Logback的分隔符,应该用“:”,而非“:-”。 提示:SB包含了Logback的大量扩展,用于协助配置。可以在 logback-spring.xml 中使用它们。 注意: 不能在  logback.xml  中使用这些扩展,因为它被加载的太早了。   Profile-specific Configuration (logging) 可以在 <configuration> 内部使用 <springProfile>,然后在 name 属性里设置profiles。如下: <springProfile name="staging"> <!-- configuration to be enabled when the "staging" profile is active --> </springProfile> <springProfile name="dev, staging"> <!-- configuration to be enabled when the "dev" or "staging" profiles are active --> </springProfile> <springProfile name="!production"> <!-- configuration to be enabled when the "production" profile is not active --> </springProfile>

      <springProperty> 标签可以使用Spring Environment 中的properties。 <springProperty scope="context" name="fluentHost" source="myapp.fluentd.host" defaultValue="localhost"/> <appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender"> <remoteHost>${fluentHost}</remoteHost> ... </appender>

    关键:scope、source、defaultValue。                            

    转载请注明原文地址: https://ju.6miu.com/read-50238.html

    最新回复(0)