残りのバージョン管理の問題を完全に処理するソリューションを実装しました。
一般的に言えば、残りのバージョン管理には3つの主要なアプローチがあります。
クライアントがURLでバージョンを定義するパスベースのアプローチ:
http://localhost:9001/api/v1/user
http://localhost:9001/api/v2/user
クライアントがAcceptヘッダーでバージョンを定義するContent-Typeヘッダー:
http://localhost:9001/api/v1/user with
Accept: application/vnd.app-1.0+json OR application/vnd.app-2.0+json
カスタムヘッダー:クライアントがカスタムヘッダーでバージョンを定義します。
問題と最初ののアプローチは、バージョンを変更した場合のがV1から言わせていることである- > V2、おそらくあなたはv2のパスに変更されていないv1のリソースをコピー&ペーストする必要があります
2番目のアプローチの問題は、http://swagger.io/のような一部のツールは、同じパスで異なるContent-Typeの操作を区別できないことです(問題https://github.com/OAI/OpenAPI-Specification/issues/を確認してください) 146)
ソリューション
私は残りのドキュメンテーションツールでたくさん作業しているので、最初のアプローチを使用することを好みます。私のソリューションは最初のアプローチで問題を処理するため、エンドポイントを新しいバージョンにコピーアンドペーストする必要はありません。
ユーザーコントローラーにv1とv2のバージョンがあるとします。
package com.mspapant.example.restVersion.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* The user controller.
*
* @author : Manos Papantonakos on 19/8/2016.
*/
@Controller
@Api(value = "user", description = "Operations about users")
public class UserController {
/**
* Return the user.
*
* @return the user
*/
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/api/v1/user")
@ApiOperation(value = "Returns user", notes = "Returns the user", tags = {"GET", "User"})
public String getUserV1() {
return "User V1";
}
/**
* Return the user.
*
* @return the user
*/
@ResponseBody
@RequestMapping(method = RequestMethod.GET, value = "/api/v2/user")
@ApiOperation(value = "Returns user", notes = "Returns the user", tags = {"GET", "User"})
public String getUserV2() {
return "User V2";
}
}
要件は、私が要求した場合であるV1私が取らなければならないユーザーリソースの「ユーザーV1」私が要求しそうでない場合は、repsonseをV2、V3をので、私は取らなければならない上、「ユーザーV2」の応答を。
これを春に実装するには、デフォルトのRequestMappingHandlerMapping動作をオーバーライドする必要があります。
package com.mspapant.example.restVersion.conf.mapping;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class VersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
@Value("${server.apiContext}")
private String apiContext;
@Value("${server.versionContext}")
private String versionContext;
@Override
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
HandlerMethod method = super.lookupHandlerMethod(lookupPath, request);
if (method == null && lookupPath.contains(getApiAndVersionContext())) {
String afterAPIURL = lookupPath.substring(lookupPath.indexOf(getApiAndVersionContext()) + getApiAndVersionContext().length());
String version = afterAPIURL.substring(0, afterAPIURL.indexOf("/"));
String path = afterAPIURL.substring(version.length() + 1);
int previousVersion = getPreviousVersion(version);
if (previousVersion != 0) {
lookupPath = getApiAndVersionContext() + previousVersion + "/" + path;
final String lookupFinal = lookupPath;
return lookupHandlerMethod(lookupPath, new HttpServletRequestWrapper(request) {
@Override
public String getRequestURI() {
return lookupFinal;
}
@Override
public String getServletPath() {
return lookupFinal;
}});
}
}
return method;
}
private String getApiAndVersionContext() {
return "/" + apiContext + "/" + versionContext;
}
private int getPreviousVersion(final String version) {
return new Integer(version) - 1 ;
}
}
実装は、URL内のバージョンを読み取り、URLを解決するようにスプリングから要求します。このURLが存在しない場合(たとえば、クライアントがv3を要求した場合)、v2を使用して、リソースの最新バージョンが見つかるまで試行します。。
この実装の利点を確認するために、ユーザーと会社の2つのリソースがあるとします。
http://localhost:9001/api/v{version}/user
http://localhost:9001/api/v{version}/company
クライアントを壊す会社の「契約」に変更を加えたとしましょう。したがって、を実装し、http://localhost:9001/api/v2/company
クライアントからv1ではなくv2に変更するように依頼します。
したがって、クライアントからの新しいリクエストは次のとおりです。
http://localhost:9001/api/v2/user
http://localhost:9001/api/v2/company
の代わりに:
http://localhost:9001/api/v1/user
http://localhost:9001/api/v1/company
ここでの最良の部分は、このソリューションでは、クライアントがユーザーv2から新しい(同じ)エンドポイントを作成する必要なく、 v1からユーザー情報とv2から会社情報を取得できることです。
残りのドキュメント
先に述べたように、URLベースのバージョン管理アプローチを選択したのは、swaggerなどの一部のツールでは、同じURLでコンテンツタイプが異なるエンドポイントのドキュメントが異なることがないためです。このソリューションでは、URLが異なるため、両方のエンドポイントが表示されます。
ギット
ソリューションの実装:https :
//github.com/mspapant/restVersioningExample/