@babydragon
2015-11-13T06:12:29.000000Z
字数 2664
阅读 2427
博客
项目中需要在不同环境切换,之前类似的需求,主要在于一些配置的不同,如数据库配置等。这样的场景,通过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@Cloudpublic class CloudWebFilterConfig {private static final String FROM = "aliyun";@Beanpublic Filter ssoFilter() {return new SSOFilter();}@Beanpublic 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@Cloudpublic class UserServiceAImpl implements UserService {public List<AegisUser> fuzzyQuery(String query) {...}}
@Service@Cloudpublic 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即可。