微服務--API版本控制

AskHarries發表於2018-12-14

URL

http://example.com/v1/helloworld

HEADER

微服務--API版本控制

各大公司做法

http://www.lexicalscope.com/blog/2012/03/12/how-are-rest-apis-versioned/

Spring Boot實踐API版本管理

原理 在SpringMVC中RequestMappingHandlerMapping是比較重要的一個角色,它決定了每個URL分發至哪個Controller。

Spring Boot載入過程如下,所以我們可以通過自定義WebMvcRegistrationsAdapter來改寫RequestMappingHandlerMapping。

微服務--API版本控制

ApiVersion.java

package com.freud.apiversioning.configuration;
import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;
import org.springframework.web.bind.annotation.Mapping;
@Target({ ElementType.METHOD, ElementType.TYPE })@Retention(RetentionPolicy.RUNTIME)@Documented@Mappingpublic @interface ApiVersion {
    /**     * version     *      * @return     */    int value();}複製程式碼

ApiVersionCondition.java

package com.freud.apiversioning.configuration;
import java.util.regex.Matcher;import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
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;    }
    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());    }
    public ApiVersionCondition getMatchingCondition(HttpServletRequest request) {        Matcher m = VERSION_PREFIX_PATTERN.matcher(request.getRequestURI());        if (m.find()) {            Integer version = Integer.valueOf(m.group(1));            if (version >= this.apiVersion) // when applying version number bigger than configuration, then it will take                                            // effect                return this;        }        return null;    }
    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;    }
}複製程式碼

ApiVersioningRequestMappingHandlerMapping.java

package com.freud.apiversioning.configuration;
import org.springframework.core.annotation.AnnotationUtils;import org.springframework.web.servlet.mvc.condition.RequestCondition;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.Method;
public class ApiVersioningRequestMappingHandlerMapping 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());    }}複製程式碼

WebMvcRegistrationsConfig.java

package com.freud.apiversioning.configuration;
import org.springframework.boot.autoconfigure.web.WebMvcRegistrationsAdapter;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
@Configurationpublic class WebMvcRegistrationsConfig extends WebMvcRegistrationsAdapter {
    @Override    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {        return new ApiVersioningRequestMappingHandlerMapping();    }
}複製程式碼

測試

TestVersioningController.java

package com.freud.apiversioning.v1.controller;
import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;
import com.freud.apiversioning.configuration.ApiVersion;
@ApiVersion(1)@RequestMapping("/{api_version}")@RestController("TestVersioningController-v1")public class TestVersioningController {
    @RequestMapping("/hello")    public String hello() {        return "hello v1";    }}複製程式碼

TestVersioningController.java

package com.freud.apiversioning.v2.controller;
import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;
import com.freud.apiversioning.configuration.ApiVersion;
@ApiVersion(2)@RequestMapping("/{api_version}")@RestController("TestVersioningController-v2")public class TestVersioningController {
    @RequestMapping("/hello")    public String hello() {        return "hello v2";    }}複製程式碼

ApiVersioningApplication.java

package com.freud.apiversioning;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class ApiVersioningApplication {
    public static void main(String[] args) {        SpringApplication.run(ApiVersioningApplication.class, args);    }}複製程式碼

application.yml

server:  port: 7905複製程式碼

專案結構

微服務--API版本控制

演示

v1 訪問http://localhost:7905/v1/hello

微服務--API版本控制

v2 訪問http://localhost:7905/v2/hello

微服務--API版本控制

v100 訪問http://localhost:7905/v100/hello

微服務--API版本控制

參考資料

Spring Boot API 版本許可權控制: http://blog.csdn.net/u010782227/article/details/74905404

讓SpringMVC支援可版本管理的Restful介面:

http://www.cnblogs.com/jcli/p/springmvcrestfulversion.html

如何做到API相容:

https://kb.cnblogs.com/page/108253/

解析@EnableWebMvc 、WebMvcConfigurationSupport和WebMvcConfigurationAdapter:

http://blog.csdn.net/pinebud55/article/details/53420481

How are REST APIs versioned?:

http://blog.csdn.net/pinebud55/article/details/53420481

微服務--API版本控制


相關文章