バックエンドの開発者としてメインレベルは、毎日の仕事で、行うには、最も厄介な事はパラメータ校正およびインタフェースのバージョンをサポートするために言うことができます。学生のクライアントの場合、歴史的負担の中小企業は、新十分の開発を指示し、ビジネスの変化に互換性がない表示されたときに、多くなりますが、バックエンドはそれほど単純ではありません、インターフェースは歴史サポートし、新規事業もサポートを得る、Hangchihangchiはどのように行う、新しいサービス・インターフェース、URLを追加し、前と同じにすることはできませんか?唯一の同様のどこかを追加することができv1
、v2
...
バージョン管理方法をサポートする他の方法を通じて、URLを変更しないでくださいありますか?
この記事では、クライアントのバージョンを使用して、パスヘッド要求を説明し、同じURLで要求のこのバージョンでは、最も適したインターフェースの例例を見つけます
主に使用する知識:
- RequestCondition
- RequestMappingHandlerMapping
I.シナリオ
我々は常に異なるバージョン間のトラフィックが最も適切なバックエンドインターフェイスパラメータを選択する要求されたバージョンによる要求に応答するために完全に互換性がない場合でも、同じURLで同じビジネスをしたいです
1.表記
上記のケースを達成するために必要な、すべての最初の二つの規則があります
- 各要求は、バージョンパラメータを運ばなければなりません
- 各インタフェースはサポートされているバージョンで定義されています
2.ルール
上記2点を明らか前提した後、基本的なルールです
バージョン定義
設計の一般的な三段階のバージョンによると、バージョンの形式は、以下のように定義されます
x.x.x
- ここで、最初のx:大規模なバージョンに対応し、一般的には、唯一の主要な変更はアップグレードする、変更されます
- xの第二は:反復のバージョン番号、通常のアプリのアップグレードをリリースし、それぞれ、この値を通常の業務を表し+1
- 最後のx:主にバグ修正のために、例えば、アプリをリリースし、その結果が異常だった、あなたは緊急の修理を必要とする、バージョンをリリースする必要性が、この時間は+この値であってもよいです
インタフェースの選択
通常のWebリクエストはURLのマッチングルールを経由して対応する応答インタフェースを選択するようにしているが、我々の場合には、URLは、複数の異なるインタフェースがあるかもしれません、どのように選択するには?
- まず、要求から、versionパラメータのバージョンを入手
- インターフェースの全てより少ないバージョンを見つけるためにインターフェイス上のバージョンに応じて定義されているすべて同じインタフェースからURL、
- 上記インターフェース条件を満たす、最大応答要求インタフェースの選択されたバージョンで
II。アプリケーションが実現します
明確上記のシナリオの後、設計および実装し始めました
1.インタフェース定義
まず、我々はバージョンタグWebサービス・インタフェースのバージョン定義に注釈を付ける必要がある、デフォルトのバージョンは1.0.0良いです
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Api {
/**
* 版本
*
* @return
*/
String value() default "1.0.0";
}
第二版は、対応するエンティティクラス、次の実装、デフォルトのバージョンに注意を払う必要が1.0.0
あり、実装Comparable
インタフェース、バージョンのサポートとの間の比較を
@Data
public class ApiItem implements Comparable<ApiItem> {
private int high = 1;
private int mid = 0;
private int low = 0;
public ApiItem() {
}
@Override
public int compareTo(ApiItem right) {
if (this.getHigh() > right.getHigh()) {
return 1;
} else if (this.getHigh() < right.getHigh()) {
return -1;
}
if (this.getMid() > right.getMid()) {
return 1;
} else if (this.getMid() < right.getMid()) {
return -1;
}
if (this.getLow() > right.getLow()) {
return 1;
} else if (this.getLow() < right.getLow()) {
return -1;
}
return 0;
}
}
バージョンはApiItem変換クラスの変換文字列の形式を必要とし、デフォルトのバージョンをサポートしている1.0.0
セット
public class ApiConverter {
public static ApiItem convert(String api) {
ApiItem apiItem = new ApiItem();
if (StringUtils.isBlank(api)) {
return apiItem;
}
String[] cells = StringUtils.split(api, ".");
apiItem.setHigh(Integer.parseInt(cells[0]));
if (cells.length > 1) {
apiItem.setMid(Integer.parseInt(cells[1]));
}
if (cells.length > 2) {
apiItem.setLow(Integer.parseInt(cells[2]));
}
return apiItem;
}
}
2. HandlerMappingインターフェイスオプション
、URLが必要です要求複数のインターフェースをサポートし、で考えることができるRequestCondition
実現することが、次のように特定のカテゴリです
public class ApiCondition implements RequestCondition<ApiCondition> {
private ApiItem version;
public ApiCondition(ApiItem version) {
this.version = version;
}
@Override
public ApiCondition combine(ApiCondition other) {
// 选择版本最大的接口
return version.compareTo(other.version) >= 0 ? new ApiCondition(version) : new ApiCondition(other.version);
}
@Override
public ApiCondition getMatchingCondition(HttpServletRequest request) {
String version = request.getHeader("x-api");
ApiItem item = ApiConverter.convert(version);
// 获取所有小于等于版本的接口
if (item.compareTo(this.version) >= 0) {
return this;
}
return null;
}
@Override
public int compareTo(ApiCondition other, HttpServletRequest request) {
// 获取最大版本对应的接口
return other.version.compareTo(this.version);
}
}
上記は比較的簡単ですが、2つのロジックを注意することが必要であるが
getMatchingCondition
方法、以下ApiConditionバージョンの制御のみ要求パラメータバージョンは、ルールが満たされますcompareTo
複数指定したがある場合ApiCoondition
、この要求を満たすために時間を、最大のバージョンを選択
カスタムRequestMappingHandlerMapping
実装クラスApiHandlerMapping
public class ApiHandlerMapping extends RequestMappingHandlerMapping {
@Override
protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
return buildFrom(AnnotationUtils.findAnnotation(handlerType, Api.class));
}
@Override
protected RequestCondition<?> getCustomMethodCondition(Method method) {
return buildFrom(AnnotationUtils.findAnnotation(method, Api.class));
}
private ApiCondition buildFrom(Api platform) {
return platform == null ? new ApiCondition(new ApiItem()) :
new ApiCondition(ApiConverter.convert(platform.value()));
}
}
登録
@Configuration
public class ApiAutoConfiguration implements WebMvcRegistrations {
@Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new ApiHandlerMapping();
}
}
これに基づいて、バージョン管理が実装インタフェースマイクロフレームワークが完了した;次に、テストセッションを入力します
III。実験
CASE1。メソッドのバージョンを追加します。
3つのインターフェース、追加のコメントを設計し、ノートの2つの異なるバージョンに2を追加
@RestController
@RequestMapping(path = "v1")
public class V1Rest {
@GetMapping(path = "show")
public String show1() {
return "v1/show 1.0.0";
}
@Api("1.1.2")
@GetMapping(path = "show")
public String show2() {
return "v1/show 1.1.2";
}
@Api("1.1.0")
@GetMapping(path = "show")
public String show3() {
return "v1/show 1.1.0";
}
}
指定されたバージョンとをそれぞれプルバージョンなしの開始要求は、対応する応答をテストする場合
- それはデフォルトに上記スクリーンショット、要求なしヘッダバージョンから分かるよう
1.0.0
バージョン - インタフェースの要求されたバージョン、最大応答のバージョンよりも小さいです
方法のケース2。+クラスのバージョンバージョン
各方法で版ボーリングビットを追加し、上記に定義されたアノテーションは、支持体のクラスにアノテーション、クラス、メソッド、および注釈を有する場合には、実現から見ることができる、最大のバージョンを選択
@Api("2.0.0")
@RestController
@RequestMapping(path = "v2")
public class V2Rest {
@Api("1.1.0")
@GetMapping(path = "show")
public String show0() {
return "v2/show0 1.1.0";
}
@GetMapping(path = "show")
public String show1() {
return "v2/show1 2.0.0";
}
@Api("2.1.1")
@GetMapping(path = "show")
public String show2() {
return "v2/show2 2.1.1";
}
@Api("2.2.0")
@GetMapping(path = "show")
public String show3() {
return "v2/show3 2.2.0";
}
}
なり、実装、show0と対応show1のための私達の規則によると、<2.1.1
バージョン要求は、この時間は競合があるでしょう。
- 上記のスクリーンショット、要求はバージョン2.0.0未満を見ることができ、それは、404に報告されています
- リクエストのバージョン2.1.1は、以下の要求よりも、その違反の例外を報告しています
IV。その他
0. 项目&相关博文
- 工程:https://github.com/liuyueyi/spring-boot-demo
- 源码: https://github.com/liuyueyi/spring-boot-demo/blob/master/spring-case/201-web-api-version
相关博文
1. 一灰灰 Blog
尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现 bug 或者有更好的建议,欢迎批评指正,不吝感激
下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
- 一灰灰 Blog 个人博客 https://blog.hhui.top
- 一灰灰 Blog-Spring 专题博客 http://spring.hhui.top