三、自定义配置

在向应用程序加入Spring Boot时,有个名为spring-boot-autoconfigure的JAR文件,其中包含很多的配置类。所有的配置如此的与众不同,原因是它们利用了Spring的条件化配置条件化配置允许配置存在于应用程序中,但在满足某些特定条件之前都忽略这个配置。
举个例子:

@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {
    ...
}

以上是Spring Boot自动配置里的DataSourceAutoConfiguration的一个片段。DataSourceAutoConfiguration添加了@Configuration注解,表明这是一个配置类。最重要的是该类添加了@ConditionalOnClass注解,要求Classpath里必须要有DataSource和EmbeddedDatabaseType。如果他们不存在,条件就不成立,DataSourceAutoConfiguration提供的配置就会被忽略掉。

自动配置中使用的条件化注解:

  • @ConditionalOnBean: 配置了某个特定Bean
  • @ConditionalOnMissingBean: 没有配置特定的Bean
  • @ConditionalOnClass: Classpath里有指定的类
  • @ConditionalOnMissingClass: Classpath里缺少指定的类
  • @ConditionalOnExpression: 给定的SpEL表达式计算结果为true
  • @ConditionalOnJava :Java的版本匹配特定值或者一个范围值
  • @ConditionalOnJndi: 参数中给定的JNDI位置必须存在一个,如果没有参数,则需要JNDI InitialContext
  • @ConditionalOnProperty: 指定的配置属性要有一个明确的值
  • @ConditionalOnResource: Classpath里有指定的资源
  • @ConditionalOnWebApplication: 这是一个Web应用程序
  • @ConditionalOnNotWebApplication: 这不是一个Web应用程序

1.覆盖Spring Boot 的自动配置

我们以Spring Security来举例。想要使用Spring Security,首先在pom.xml添加如下依赖:

  
            org.springframework.boot
            spring-boot-starter-security
  

添加完依赖后,重构项目,此时该项目就可以运行。但访问url地址时,它会提示你登录。没错,此时只是用的Spring Security默认的配置,默认的配置可能满足不了我们的需求,那么我们可以显式地覆盖Spring Security的自动配置。


三、自定义配置_第1张图片
默认的登录页面.png

覆盖自动配置的显示安全配置:

package com.jasonper.readinglist;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

@Configuration
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private ReaderRepository readerRepository;

    /**
     * 此configure方法设置了一个自定义的userDetailsService,这个服务可以是任意实现了userDetailsService的类,用于查找指定用户名的用户。
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(username -> readerRepository.findOne(username));
    }

    /**
     * 此configure方法指明:
     *      "/"的请求只有经过身份认证且具有READER角色的用户采纳访问,其他的所有请求路径向所有的用户开放了访问权限。
     *      这里还指定了登录页面和登录失败页面
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/").access("hasRole('READER')")
                .antMatchers("/**").permitAll()
                .and()
                .formLogin()
                .loginPage("/login")
                .failureUrl("/login?error=true");
    }
}

上面的例子足以演示如何覆盖Spring Boot提供的安全自动配置。想要覆盖Spring Boot的自动配置,我们所要做的仅仅是编写一个显示的java配置而已。

2.通过属性文件外置配置

Spring Boot应用程序有多种设置途径,包括如下几处:
(1)命令行参数
(2)java:comp/env里的JNDI(Java Naming and Directory Interface)
(3)JVM系统属性
(4)操作系统环境变量
(5)随机生成的带random.*前缀的属性
(6)应用程序以外的application.properties或者application.yml文件
(7)打包在应用程序内的application.properties或者application.yml文件
(8)通过@PropertySource标注的属性源
(9)默认属性

Tips:上列表按照优先级排序。
application.properties和application.yml文件能放在以下四个位置:

  • 外置,在相对于应用程序运行目录的/config子目录里
  • 外置,在应用程序运行的目录里
  • 内置,在config包内
  • 内置,在Classpath根目录
    此外,如果你在同一优先级位置同时有application.properties和application.yml,那么application.yml里的属性会覆盖application.properties里的属性
  1. 自动配置微调

在Spring Boot里有300多个属性可以用来微调应用程序里的Bean。
例如,通过application.yml来更改嵌入式服务器端口:

server:
  port: 8000
  1. 应用程序的Bean的配置外置

假设我们在application.yml配置了如下信息:

person:
  name: 张三
  age: 20

想要在某个类上拿到刚刚所配置的信息,那很简单,只需在类上配置如下注解,即可在该用的地方使用刚刚配置的属性:
@ConfigurationProperties(prefix = "person")

当然,我们也可以在一个Bean里加载配置属性:

package com.jasonper.readinglist;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties("person") // 从application.yml里的person中获得属性
public class PersonProperties {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
  1. 使用Profile进行配置
    当应用程序需要部署到不同的运行环境时,一些配置细节通常会有所不同。比如数据库连接在开发环境和生产环境下就会不一样,在测试环境下又不一样。此时可以使用Profile。Profile是一种条件化配置,基于运行时激活的Profile,会使用或者忽略不同的Bean或配置类。
    以Spring Security为例:
@Profile("production")
@Configuration
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    ...
}

这里的@Profile注解要求运行时激活production Profile,这样才能应用该配置。激活配置的方式有很多种,这里使用application.yml文件来激活:

spring:
  profiles:
    active: production
  1. 使用特定于Profile的属性文件

如果你正在使用application.properties,可以创建额外的属性文件,遵循application-{profile}.properties这种命名格式,这样就能提供特定于Profile的属性了。

  1. 使用多Profile YAML文件进行配置

如果使用YAML来配置属性,则可以遵循与配置文件相同的命名规范:application-{profile}.yml这样的YAML文件,并将与Profile无关的属性继续配置在application.yml里。

同时,可以把所有的Profile的配置属性都放在同一个application.yml文件里。使用日志配置来举个例子:

logging:
  level: 
    root: INFO
    
---
spring:
  profiles: dev

logging:
  level: 
    root: DEBUG

---

spring:
  profiles: production

logging:
  path: /tmp/
  file: BookWorm.log
  level:
    root: WARN

这个application.yml分为三部分,使用一组三个连字符作为分隔符。第二段和第三段分别指定了不同的环境下的日志配置。第二段是开发环境下的,第三段是生产环境下的。
另一方面,第一段未指定spring.profile,因此这里的属性对全部Profile都生效,或者对那些未设置该属性的激活Profile生效。

3.定制应用程序的错误页面

定制应用程序的错误页面,只需在src/main/resources/templates中加入自己写的错误页面即可。Spring Boot会为错误视图提供如下错误属性:

  • timestamp:错误发生的时间
  • status:错误状态码
  • error:错误的原因
  • exception:异常的类型
  • message:异常消息(如果这个错误是由异常引起的)
  • errors:BindingResult异常里的各种错误(如果这个错误是由异常引起的)
  • trace:异常跟踪信息(如果这个错误是由异常引起的)
  • path:错误发生时请求的url路径

你可能感兴趣的:(三、自定义配置)