@babydragon
2015-11-13T14:12:29.000000Z
字数 2664
阅读 2177
博客
项目中需要在不同环境切换,之前类似的需求,主要在于一些配置的不同,如数据库配置等。这样的场景,通过maven的profile,结合resource filter即可。但是这次需要针对不同的场景,使用不同的实现类,以此来对接外部不同的系统。
本文基本上参考了spring博客中的介绍,通过@profile
注解,来区分不同的使用场景。
@Profile注解需要接受一个字符串,作为场景名。这样每个地方都需要记住这个字符串。Spring的@Profile注解支持定义在其他注解之上,以创建自定义场景注解。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Profile("cloud")
public @interface Cloud {
}
这样就创建了一个@Cloud
注解,该注解可以标识bean使用于cloud这个场景。后续就不再需要使用@Profile("cloud")
的方式。这样即可以简化代码,同时可以利用IDE的自动补全:)
有了上面定义的注解,可以直接在有@Configure
注解的配置类上的增加,以控制该类创建的Bean,只在指定场景下激活。例如:
@Configuration
@Cloud
public class CloudWebFilterConfig {
private static final String FROM = "aliyun";
@Bean
public Filter ssoFilter() {
return new SSOFilter();
}
@Bean
public FilterRegistrationBean ssoFilterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(ssoFilter());
filterRegistrationBean.setName("ssoFilter");
filterRegistrationBean.setUrlPatterns(Collections.singletonList("/*"));
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistrationBean;
}
}
上面的配置类,创建了两个bean,其中一个是springboot使用的filter,使用我们针对云上单点登录的实现;另一个是这个filter的配置,配置了这个filter的路径和名称,还有顺序。这里的配置和直接在web.xml中配置filter类似。唯一不同的是,FilterRegistrationBean支持设置filter的优先级。
除了上述通过配置类的方式控制之外,@Profile
和自定义的(@Cloud
)注解还可以直接应用的@Service
、@Component
等注解创建的服务实现上。同样,带上场景注解之后,这些服务实现只会在场景激活之后才会实例化。
例如,我们可以定义一个用户查询接口:
public interface UserService {
List<AegisUser> fuzzyQuery(String query);
}
在不同场景下,我们需要有不同的实现。
@Service
@Cloud
public class UserServiceAImpl implements UserService {
public List<AegisUser> fuzzyQuery(String query) {
...
}
}
@Service
@Cloud
public class UserServiceBImpl implements UserService {
public List<AegisUser> fuzzyQuery(String query) {
...
}
}
上面创建了两个UserService的实现,一个标记为内部使用,一个标记为云上使用。
这样,对于上层平台,只需要直接@Autowired
注解注入即可,无须再通过@Qualifier
注解指定具体的实现了。运行时注入,会通过场景指定具体的实现类。
spring boot在启动时需要指定当前激活的场景,主要方式有两个:
spring.profiles.active=cloud
参数为了能够在打包的时候就确定启动场景,最终还是采用了后者,并且和maven的resource filter结合。即在properties文件中使用占位符,在maven的profile中通过filter,通过maven profile来编译时替换。
<profiles>
<profile>
<id>internal</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<build.profile.id>internal</build.profile.id>
</properties>
</profile>
<profile>
<id>cloud</id>
<properties>
<build.profile.id>cloud</build.profile.id>
</properties>
</profile>
</profiles>
<build>
<filters>
<filter>profiles/${build.profile.id}/config.properties</filter>
</filters>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
...
</build>
这样只要在maven编译时通过-P参数指定maven profile即可。