springboot实现接口版本控制(一)


一、接口版本控制目的:

 1.1 保证减少停服务升级(减少升级影响用户的使用,这里只涉及到接口层,其实还要考虑数据层的版本控制,比如:版本间要双写、字段不能删除等)
 1.2 版本向后兼容

二、接口版本控制的同种做法:

  2.1 在URI中标记版本  https://xxx.com/api/v3/list  【我们今天讲的是这种】

  2.2 用参数的形式传递版本号:https://xxx.com/api/list?version=3.0

  2.3 将版本号放到request header里:api-version:v1

  2.4 通过token来判断版本号: https://xxx.com/api/list?token=5782b5e0512c7d47345d10af413b3d28   // 服务端token处理器处理 ------> 确定请求API的内部版本 -----> 执行具体API ------>返回结果

三、实现:【sprinbboot+annotation+spring configuration+mvc】

3.1 自定义注解 ApiVersion.java

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface ApiVersion {
    double value() default 1.0;
}

3.2 版本匹配

public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {
    private static final Pattern VERSION_PREFIX_PATTERN = Pattern.compile("^\\S+/([1-9][.][0-9])$");
    private double apiVersion;

    public ApiVersionCondition(double apiVersion) {
        this.apiVersion = apiVersion;
    }

    public double getApiVersion() {
        return apiVersion;
    }

    public void setApiVersion(double apiVersion) {
        this.apiVersion = apiVersion;
    }

    @Override
    public ApiVersionCondition combine(ApiVersionCondition other) {
        return new ApiVersionCondition(other.getApiVersion());
    }

    @Override
    public ApiVersionCondition getMatchingCondition(HttpServletRequest httpServletRequest) {

        Matcher matcher = VERSION_PREFIX_PATTERN.matcher(httpServletRequest.getRequestURI());
        if (matcher.find()) {
            Double version = Double.valueOf(matcher.group(1));
            System.out.println("version:" + version + ",this.apiVersion:" + this.apiVersion);
            if (version >= this.apiVersion) {
                return this;
            }
        }
        return null;
    }

    @Override
    public int compareTo(ApiVersionCondition apiVersionCondition, HttpServletRequest httpServletRequest) {
        return Double.compare(apiVersionCondition.getApiVersion(), this.apiVersion);
    }
}

3.3 URL请求映射(带@ApiVersion注解的走匹配规则)

public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {


    @Override
    protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType,ApiVersion.class);
        return createCondition(apiVersion);
    }

    @Override
    protected RequestCondition<?> 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());
    }
}


3.4控制器映射请求定义(URL映射)

@SpringBootConfiguration
public class WebMvcRegistrationsConfig implements WebMvcRegistrations {

    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        return new CustomRequestMappingHandlerMapping();
    }
}

3.5创建控制器


@RestController
public class ImageController {

    @GetMapping("/api/test/{version}")
    @ApiVersion(2.0)
    public String searchTargetImage() {
        return "Hello,Welcome to version 2.0";
    }

    @GetMapping("/api/test/{version}")
    @ApiVersion(1.0)
    public String searchTargetImage2() {
        return "Hello,Welcome to version 1.0";
    }


    @GetMapping("/api/test/{version}")
    @ApiVersion(3.0)
    public String searchTargetImage3() {
        return "Hello,Welcome to version 3.0";
    }

}

3.6执行

localhost:8383/api/test/2.0 => 结果:Hello,Welcome to version 2.0
localhost:8383/api/test/1.0 => 结果:Hello,Welcome to version 1.0


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM