SpringBoot API版本控制

歡迎使用Markdown編輯器寫博客

後端開發人員經常遇到接口升級、優化接口甚至重新定義一模一樣新接口而且還得兼容舊版本接口。這樣我們得維護兩個一模一樣接口,版本管理越來越重要。基於自定義註解獲得請求頭Header中apiVersion參數,版本大的轉發不同接口上。

RequestMappingHandlerMapping請求詳情
在這裏插入圖片描述

  • 自定義版本註解
/**
 * @Author: LailaiMonkey
 * @Description:
 * @Date:Created in 2020-10-14 17:47
 * @Modified By:
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiVersion {
   
   

    /**
     * 版本號
     * @return
     */
    int value();
}
  • 重寫RequestCondition,自定義url匹配邏輯
/**
 * @Author: LailaiMonkey
 * @Description:
 * @Date:Created in 2020-10-14 16:59
 * @Modified By:
 */
public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {
   
   

    /**
     * 版本
     */
    private int apiVersion;

    ApiVersionCondition(int apiVersion) {
   
   
        this.apiVersion = apiVersion;
    }

    /**
     * 最近優先原則,方法定義的 @ApiVersion > 請求頭定義apiVersion
     *
     * @param apiVersionCondition
     * @return
     */
    @Override
    public ApiVersionCondition combine(ApiVersionCondition apiVersionCondition) {
   
   
        return new ApiVersionCondition(apiVersion);
    }

    /**
     * 獲得符合匹配條件的ApiVersionCondition
     *
     * @param httpServletRequest
     * @return
     */
    @Override
    public ApiVersionCondition getMatchingCondition(HttpServletRequest httpServletRequest) {
   
   
        //獲得header傳遞的版本號
        String apiVersion = httpServletRequest.getHeader("apiVersion");
        if (StringUtils.isNotBlank(apiVersion)) {
   
   
            try {
   
   
                Integer version = Integer.valueOf(apiVersion);
                if (version >= this.apiVersion) {
   
   
                    return this;
                }
            } catch (Exception e) {
   
   
                System.out.println("版本號不合法:{}" + apiVersion);
            }
        }
        return null;
    }

    /**
     * 優先匹配最大版本號
     *
     * @param apiVersionCondition
     * @param httpServletRequest
     * @return
     */
    @Override
    public int compareTo(ApiVersionCondition apiVersionCondition, HttpServletRequest httpServletRequest) {
   
   
        return apiVersionCondition.getApiVersion() - this.apiVersion;
    }

    private int getApiVersion() {
   
   
        return apiVersion;
    }
}
  • 重寫RequestMappingHandlerMapping,自定義匹配的處理器
/**
 * @Author: LailaiMonkey
 * @Description:
 * @Date:Created in 2020-10-15 09:54
 * @Modified By:
 */
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());
    }
}
  • 配置註冊自定義WebMvcRegistrations
/**
 * @Author: LailaiMonkey
 * @Description:
 * @Date:Created in 2020-10-15 09:57
 * @Modified By:
 */
@Configuration
public class WebMvcRegistrationsConfig implements WebMvcRegistrations {
   
   

    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
   
   
        return new ApiVersioningRequestMappingHandlerMapping();
    }
}
  • 測試Controller
	@ApiVersion(1)
    @GetMapping("/version")
    public Object version()  {
   
   
        return "version";
    }

    @ApiVersion(3)
    @GetMapping("/version")
    public Object version1()  {
   
   
        return "version1";
    }

訪問localhost:8080/version且header中apiVersion爲1或2走第一個接口,apiVersion大於等於3走第二個接口

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章