SpringBoot實(shí)現(xiàn)接口版本控制的示例代碼
概述
接口版本控制,比如微服務(wù)請(qǐng)求中某個(gè)接口需要升級(jí),正常做法是升級(jí)我們的版本
比如:localhost:80/api/v1/test
技術(shù)實(shí)現(xiàn)
我們可以將版本相關(guān)的控制以包的形式引入到我們的項(xiàng)目中,那么我們就需要開(kāi)發(fā)我們的對(duì)應(yīng)的版本控制的sdk
1,自定義注解
@Documented
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiVersion {
/**
* 版本號(hào)
* @return
*/
int value() default 1;
}
2,控制開(kāi)關(guān)屬性
@RefreshScope
@Data
@ConfigurationProperties(prefix = "api.version")
public class ApiVersionProperties {
boolean enabled;
}
3,重寫(xiě)RequestMapping
public class ApiRequestHandlerMapping extends RequestMappingHandlerMapping {
@Override
protected RequestCondition<ApiVersionCondition> getCustomTypeCondition(Class<?> handlerType) {
ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
return createCondition(apiVersion);
}
@Override
protected RequestCondition<ApiVersionCondition> getCustomMethodCondition(Method method) {
ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class);
return createCondition(apiVersion);
}
private RequestCondition<ApiVersionCondition> createCondition(ApiVersion apiVersion) {
return apiVersion == null ? null : new ApiVersionCondition(apiVersion.value());
}
}
public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {
/**
* extract the version part from url. example [v0-9]
*/
private final static Pattern VERSION_PREFIX_PATTERN = Pattern.compile("v(\\d+)/");
private int apiVersion;
public ApiVersionCondition(int apiVersion) {
this.apiVersion = apiVersion;
}
/**
* // 和另外一個(gè)請(qǐng)求匹配條件合并,具體合并邏輯由實(shí)現(xiàn)類(lèi)提供
* @param other
* @return
*/
@Override
public ApiVersionCondition combine(ApiVersionCondition other) {
// latest defined would be take effect, that means, methods definition with
// override the classes definition
return new ApiVersionCondition(other.getApiVersion());
}
/**
* // 檢查當(dāng)前請(qǐng)求匹配條件和指定請(qǐng)求request是否匹配,如果不匹配返回null,
* // 如果匹配,生成一個(gè)新的請(qǐng)求匹配條件,該新的請(qǐng)求匹配條件是當(dāng)前請(qǐng)求匹配條件
* // 針對(duì)指定請(qǐng)求request的剪裁。
* // 舉個(gè)例子來(lái)講,如果當(dāng)前請(qǐng)求匹配條件是一個(gè)路徑匹配條件,包含多個(gè)路徑匹配模板,
* // 并且其中有些模板和指定請(qǐng)求request匹配,那么返回的新建的請(qǐng)求匹配條件將僅僅
* // 包含和指定請(qǐng)求request匹配的那些路徑模板。
* @param request
* @return
*/
@Override
public ApiVersionCondition getMatchingCondition(HttpServletRequest request) {
Matcher m = VERSION_PREFIX_PATTERN.matcher(request.getRequestURI());
if (m.find()) {
Integer version = Integer.valueOf(m.group(1));
// when applying version number bigger than configuration, then it will take
if (version >= this.apiVersion) {
// effect
return this;
}
}
return null;
}
/**
* 針對(duì)指定的請(qǐng)求對(duì)象request比較兩個(gè)請(qǐng)求匹配條件。
* 該方法假定被比較的兩個(gè)請(qǐng)求匹配條件都是針對(duì)該請(qǐng)求對(duì)象request調(diào)用了
* #getMatchingCondition方法得到的,這樣才能確保對(duì)它們的比較
* 是針對(duì)同一個(gè)請(qǐng)求對(duì)象request,這樣的比較才有意義(最終用來(lái)確定誰(shuí)是
* 更匹配的條件)。
* @param other
* @param request
* @return
*/
@Override
public int compareTo(ApiVersionCondition other, HttpServletRequest request) {
// when more than one configured version number passed the match rule, then only
// the biggest one will take effect.
return other.getApiVersion() - this.apiVersion;
}
public int getApiVersion() {
return apiVersion;
}
}
4,注冊(cè)
@Configuration
@EnableConfigurationProperties(ApiVersionProperties.class)
@ConditionalOnProperty(
value = {"api.version.enabled"},
matchIfMissing = true
)
public class WebConfig implements WebMvcRegistrations {
@Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new ApiRequestHandlerMapping();
}
}
5,最后resource/MATE-INFO/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.springbootgray.apiversion.WebConfig,\
使用
@RestController
@ApiVersion(value = 1)
@RequestMapping("/api/{version}")
調(diào)用使用
localhost:8080/api/v1/test
到此這篇關(guān)于SpringBoot實(shí)現(xiàn)接口版本控制的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot接口版本控制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Swing窗體關(guān)閉事件的調(diào)用關(guān)系
這篇文章主要為大家詳細(xì)介紹了Java Swing窗體關(guān)閉事件的調(diào)用關(guān)系,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
Java線(xiàn)程池的幾種實(shí)現(xiàn)方法及常見(jiàn)問(wèn)題解答
下面小編就為大家?guī)?lái)一篇Java線(xiàn)程池的幾種實(shí)現(xiàn)方法及常見(jiàn)問(wèn)題解答。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05
idea同時(shí)編輯多行問(wèn)題-win&mac都支持
這篇文章主要介紹了idea同時(shí)編輯多行問(wèn)題-win&mac都支持,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09
SpringMVC實(shí)現(xiàn)文件的上傳和下載實(shí)例代碼
本篇文章主要介紹了SpringMVC實(shí)現(xiàn)文件的上傳和下載實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05
從源碼角度簡(jiǎn)單看StringBuilder和StringBuffer的異同(全面解析)
下面小編就為大家分享一篇從源碼角度簡(jiǎn)單看StringBuilder和StringBuffer的異同(全面解析),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
創(chuàng)建Java線(xiàn)程安全類(lèi)的七種方法
線(xiàn)程安全是指某個(gè)方法或某段代碼,在多線(xiàn)程中能夠正確的執(zhí)行,不會(huì)出現(xiàn)數(shù)據(jù)不一致或數(shù)據(jù)污染的情況,我們把這樣的程序稱(chēng)之為線(xiàn)程安全的,反之則為非線(xiàn)程安全的,下面這篇文章主要給大家介紹了關(guān)于創(chuàng)建Java線(xiàn)程安全類(lèi)的七種方法,需要的朋友可以參考下2022-06-06
JAVA實(shí)現(xiàn)往字符串中某位置加入一個(gè)字符串
這篇文章主要介紹了JAVA實(shí)現(xiàn)往字符串中某位置加入一個(gè)字符串,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08

