您的位置:首页 > 其它

特性开关之开关策略

2018-03-10 17:56 351 查看
特性开关有时只是简简单单的通过配置true or false来决定开或关,而有时要根据某种策略来决定开或关。对于开关策略,特性开关框架一般会提供不少默认的策略给我们用,但有时我们也会遇到框架没有提供而我们又想要的,这时则需要我们自定义。掌握特性开关框架默认提供的开关策略及如何自定义开关策略都很重要。下面我以FF4J这个框架为例,介绍它自带提供的策略及如何扩展实现自己的策略。
FF4J默认提供的策略


上面截图列出了FF4J提供的所有默认策略,有基于表达式的策略,有基于时间的策略,有白名单黑名单策略,有权重策略等,下面我们看看默认策略怎么用。
默认策略示例 
<feature uid="laolaxin" enable="true">
   <flipstrategy class="org.ff4j.strategy.time.ReleaseDateFlipStrategy">
       <param name="releaseDate" value="2018-02-26-12:15"/>
   </flipstrategy>
   <custom-properties>
       <property name="return" value="活动未开始,尽请期待"/>
   </custom-properties>
</feature>
 
@RequestMapping("/activity/laolaxin")
@Feature(name="laolaxin")
public String laolaxin(){
   //TODO laolaxin
   return "完成活动!!";
}
这里我们使用了ReleaseDateFlipStrategy这个策略,其实自定义策略的用法也是一样的,不同的姿势 class 字段配的值不一样。下面我们看看如何自定义策略。
如何自定义策略FF4J使用了策略模式实现开关策略,具备良好的扩展性,所以我们扩展自定义策略也是蛮简单。要自定义自己的策略,需要实现 FlipStrategy 接口。



而FF4J为我们提供了一个抽象类 AbstractFlipStrategy



所有我们其实只需要继承AbstractFlipStrategy,然后实现evaluate方法,必要时也可以override init和 getInitParams 方法。下面我会通过一个例子来细说。
自定义策略示例《xxx》app后台那边有这样一种场景,APP新版本对某一旧接口做了较大的逻辑修改,但新逻辑不能被旧app访问到,旧app要求还是访问旧逻辑,为了实现这个,开发会在代码中引入if…else…分支,通过版本号来做判断。这一场景也可以用特性开关来做,不过需要自定义策略,下面我们看看这个策略怎么写.
自定义策略类
 
/**
* 自定义版本策略,对新版本开,对老版本关,新版本的版本值可配置
*/
public class VersionStrategy extends AbstractFlipStrategy {
   private String version;
   public static final String VERSION = "version";
   private List<Integer> versionList = new ArrayList<>();
   public void init(String featureName, Map<String, String> initParams) {
       super.init(featureName, initParams);
       assertRequiredParameter(VERSION);
       if (initParams != null && initParams.containsKey(VERSION)) {
           this.version = initParams.get(VERSION);
           String[] versionStrArr = version.split("\\.");
           for (String item : versionStrArr) {
               versionList.add(Integer.parseInt(item));
         }
      }
   }
   @Override
   public boolean evaluate(String s, FeatureStore featureStore, FlippingExecutionContext flippingExecutionContext) {
       return isNewVersion(flippingExecutionContext);
   }
   /**
    * 判断是否是新版本
    * 版本格式要求:数字.数字.数字…譬如 2.12.14
    * @param flippingExecutionContext 上下文
    * @return boolean
    */
   protected boolean isNewVersion(FlippingExecutionContext flippingExecutionContext) {
       String clientVersion = flippingExecutionContext.getValue(VERSION, false) == null ? null : flippingExecutionContext.getString(VERSION);
       if (clientVersion == null || clientVersion.trim().length() == 0) return false;
       String clientVersionArr[] = clientVersion.split("\\.");
       if (versionList.size() != clientVersionArr.length) return false;
       for (int i = 0; i < versionList.size(); i++) {
           int iversion = versionList.get(i);
           int iClientVersion = Integer.parseInt(clientVersionArr[i]);
           if (iClientVersion < iversion) return false;
      }
       return true;
   }
}
这里我们可以看到我们自定义了一个VersionStrategy策略类,继承了AbstractFlipStrategy ,重写了init方法,实现了evaluate方法。init 方法是干嘛的?它是初始化开关配置数据的,如上所示我们将配置的version值做了初始化。evaluate方法是做什么的?它是用来判断开关状态的,如上所示我们通过比较配置的版本号与客户端传过来的版本来判断是否是新版本,来决定开关是开还是关。下面我们看看自定义的这个策略怎么用。
使用自定义策略
 
<feature uid="oldAndNew" enable="true">
   <flipstrategy class="com.ppmoney.ppmon.feature.ff4j.test.VersionStrategy">
       <param name="version" value="2.1.9"/>
   </flipstrategy>
</feature>
 
@Autowired
private FF4j ff4j;
@RequestMapping("/oldAndNew")
public String oldAndNew(HttpServletRequest request) {
   FlippingExe
ce14
cutionContext executionContext = new FlippingExecutionContext();
   executionContext.addValue("version", request.getHeader("version"));
   if (ff4j.check("oldAndNew", executionContext)) {
       //重构后的新逻辑
       return 1 + 2 + "";
   } else {
       //上个版本的旧逻辑
       return 1 + 1 + "";
   }
}
如上我们在配置中指定了 VersionStrategy,并且配置了version值 “2.1.9", 业务代码中我们将请求头里的版本值赋给 FlippingExecutionContext 对象,并通过ff4j的check方法判断开关状态,事实上 check 方法最终会调用到 evaluate 方法来决定,请看下面源码。



到此我想大家都知道怎么自定义和使用开关策略了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  特性开关 FF4J