微服務--API版本控制

URLhtml

http://example.com/v1/helloworldjava

HEADERweb

各大公司作法

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

Spring Boot實踐API版本管理

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

Spring Boot加載過程以下,因此咱們能夠經過自定義WebMvcRegistrationsAdapter來改寫RequestMappingHandlerMapping。bash

ApiVersion.javarestful

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.javamvc

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.javaapp

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.javaide

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複製代碼

項目結構

演示

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

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

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

參考資料

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

相關文章
相關標籤/搜索