1. 概要

このチュートリアルでは、 Flips、 Spring Core、Spring MVC、およびSpring Bootアプリケーション用の強力な注釈の形式で機能フラグを実装するライブラリを見ていきます。

機能フラグ(またはトグル)は、新しい機能を迅速かつ安全に提供するためのパターンです。 これらのトグルにより、新しいコードを変更またはデプロイすることなく、アプリケーションの動作を変更できます Martin Fowlerのブログには、機能フラグここに関する非常に有益な記事があります。

2. Mavenの依存関係

始める前に、Flipsライブラリを pom.xml:に追加する必要があります。

<dependency>
    <groupId>com.github.feature-flip</groupId>
    <artifactId>flips-core</artifactId>
    <version>1.0.1</version>
</dependency>

Maven Centralには最新バージョンのライブラリがあり、Githubプロジェクトはここです。

もちろん、Springも含める必要があります。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>1.5.10.RELEASE</version>
</dependency>

FlipsはまだSpringバージョン5.xと互換性がないため、4.xブランチでは最新バージョンのSpring Bootを使用します。

3. フリップ用のシンプルなRESTサービス

新しい機能とフラグを追加および切り替えるための簡単なSpring Bootプロジェクトをまとめましょう。

私たちのRESTアプリケーションは、Fooリソースへのアクセスを提供します。

public class Foo {
    private String name;
    private int id;
}

Foosのリストを維持するServiceを作成するだけです。

@Service
public class FlipService {

    private List<Foo> foos;

    public List<Foo> getAllFoos() {
        return foos;
    }

    public Foo getNewFoo() {
        return new Foo("New Foo!", 99);
    }
}

今後、追加のサービスメソッドを参照しますが、このスニペットは、FlipServiceがシステムで何をするかを説明するのに十分なはずです。

そしてもちろん、コントローラーを作成する必要があります。

@RestController
public class FlipController {

    private FlipService flipService;

    // constructors

    @GetMapping("/foos")
    public List<Foo> getAllFoos() {
        return flipService.getAllFoos();
    }
}

4. 構成に基づく制御機能

Flipsの最も基本的な使用法は、構成に基づいて機能を有効または無効にすることです。 Flipsには、このためのいくつかの注釈があります。

4.1. 環境プロパティ

FlipServiceに新しい機能を追加したと想像してみてください。 IDでFoosを取得します。

新しいリクエストをコントローラーに追加しましょう。

@GetMapping("/foos/{id}")
@FlipOnEnvironmentProperty(
  property = "feature.foo.by.id", 
  expectedValue = "Y")
public Foo getFooById(@PathVariable int id) {
    return flipService.getFooById(id)
      .orElse(new Foo("Not Found", -1));
}

@FlipOnEnvironmentProperty は、このAPIが使用可能かどうかを制御します。

簡単に言えば、feature.foo.by.idYの場合、IDでリクエストできます。 定義されていない(またはまったく定義されていない)場合、FlipsはAPIメソッドを無効にします。

機能が有効になっていない場合、Flipsは FeatureNotEnabledException をスローし、SpringはRESTクライアントに「未実装」を返します。

プロパティをNに設定してAPIを呼び出すと、次のように表示されます。

Status = 501
Headers = {Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Body = {
    "errorMessage": "Feature not enabled, identified by method 
      public com.baeldung.flips.model.Foo
      com.baeldung.flips.controller.FlipController.getFooById(int)",
    "className":"com.baeldung.flips.controller.FlipController",
    "featureName":"getFooById"
}

予想どおり、Springは FeatureNotEnabledException をキャッチし、ステータス501をクライアントに返します。

4.2. アクティブプロファイル

Springは長い間、Beanを dev test prodなどのさまざまなプロファイルにマップする機能を提供してきました。 この機能を拡張して、機能フラグをアクティブプロファイルにマッピングすることは、直感的に理解できます。

アクティブなSpringプロファイルに基づいて機能がどのように有効または無効になるかを見てみましょう。

@RequestMapping(value = "/foos", method = RequestMethod.GET)
@FlipOnProfiles(activeProfiles = "dev")
public List getAllFoos() {
    return flipService.getAllFoos();
}

@FlipOnProfiles アノテーションは、プロファイル名のリストを受け入れます。 アクティブなプロファイルがリストにある場合、APIにアクセスできます。

4.3. 春の表現

Springの式言語(SpEL)は、ランタイム環境を操作するための強力なメカニズムです。 Flipsには、機能を切り替える方法もあります。

@FlipOnSpringExpression は、ブール値を返すSpEL式に基づいてメソッドを切り替えます。

簡単な式を使用して、新しい機能を制御してみましょう。

@FlipOnSpringExpression(expression = "(2 + 2) == 4")
@GetMapping("/foo/new")
public Foo getNewFoo() {
    return flipService.getNewFoo();
}

4.4. 無効にする

機能を完全に無効にするには、@FlipOffを使用します。

@GetMapping("/foo/first")
@FlipOff
public Foo getFirstFoo() {
    return flipService.getLastFoo();
}

この例では、 getFirstFoo()に完全にアクセスできません。

以下に示すように、Flipsアノテーションを組み合わせて、 @FlipOff を使用して、環境またはその他の基準に基づいて機能を無効にすることができます。

5. 日付/時刻による制御機能

フリップは、日付/時刻または曜日に基づいて機能を切り替えることができます。 新機能の可用性をその日または日付に結び付けることには、明らかな利点があります。

5.1. 日時

@FlipOnDateTime は、 ISO8601形式でフォーマットされたプロパティの名前を受け入れます。

それでは、3月1日にアクティブになる新機能を示すプロパティを設定しましょう。

first.active.after=2018-03-01T00:00:00Z

次に、最初のFooを取得するためのAPIを記述します。

@GetMapping("/foo/first")
@FlipOnDateTime(cutoffDateTimeProperty = "first.active.after")
public Foo getFirstFoo() {
    return flipService.getLastFoo();
}

Flipsは名前付きプロパティをチェックします。 プロパティが存在し、指定された日時が経過している場合、この機能は有効になります。

5.2. 曜日

ライブラリは@FlipOnDaysOfWeekを提供します。これは、A/Bテストなどの操作に役立ちます。

@GetMapping("/foo/{id}")
@FlipOnDaysOfWeek(daysOfWeek={DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY})
public Foo getFooByNewId(@PathVariable int id) {
    return flipService.getFooById(id).orElse(new Foo("Not Found", -1));
}

getFooByNewId()は、月曜日と水曜日にのみ利用できます。

6. Beanを置き換える

メソッドのオンとオフを切り替えることは便利ですが、新しいオブジェクトを介して新しい動作を導入したい場合があります。 @FlipBean は、新しいBeanのメソッドを呼び出すようにFlipsに指示します。

Flipsアノテーションは、任意のSpring @Componentで機能します。これまでのところ、 @RestController のみを変更しました。次に、Serviceを変更してみましょう。

FlipServiceとは異なる動作の新しいサービスを作成します。

@Service
public class NewFlipService {
    public Foo getNewFoo() {
        return new Foo("Shiny New Foo!", 100);
    }
}

古いサービスのgetNewFoo()を新しいバージョンに置き換えます。

@FlipBean(with = NewFlipService.class)
public Foo getNewFoo() {
    return new Foo("New Foo!", 99);
}

フリップは呼び出しをに転送します getNewThing() NewFlipService。 @FlipBean 他のトグルと組み合わせると最も便利なもう1つのトグルです。 それを見てみましょう。

7. トグルの組み合わせ

複数を指定してトグルを組み合わせます。 Flipsは、暗黙の「AND」ロジックを使用して、これらを順番に評価します。 したがって、機能をオンに切り替えるには、それらすべてがtrueである必要があります。

前の例の2つを組み合わせてみましょう。

@FlipBean(
  with = NewFlipService.class)
@FlipOnEnvironmentProperty(
  property = "feature.foo.by.id", 
  expectedValue = "Y")
public Foo getNewFoo() {
    return new Foo("New Foo!", 99);
}

構成可能な新しいサービスを利用しました。

8. 結論

この簡単なガイドでは、単純なSpring Bootサービスを作成し、Flipsアノテーションを使用してAPIのオンとオフを切り替えました。 構成情報と日付/時刻を使用して機能を切り替える方法と、実行時にBeanを交換することで機能を切り替える方法を確認しました。

コードサンプルは、いつものように、GitHubにあります。