springboot版本控制


HandlerMapping通過繼承InitializingBean接口在完成實例后,掃描所有的Controller和標識RequestMapping的方法,緩存這個映射對應關系。然后在應用運行的時候,根據請求的request來找到相應的handler來處理這個請求。在這里,我們添加擴展類:

  • ApiVersion
  • ApiVesrsionCondition
  • CustomRequestMappingHandlerMapping
  • WebConfig

現分別來看下這個類,首先看下ApiVersion這個注解:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface ApiVersion {
    /**
     * 版本號
     * @return
     */
    int value();
}

 

這個注解用來標識某個類或者方法要處理的對應版本號,使用如下:

@Controller
@RequestMapping("/{version}/")
public class HelloController {
 
    @RequestMapping("hello/")
    @ApiVersion(1)
    @ResponseBody
    public String hello(HttpServletRequest request){
        System.out.println("haha1..........");
         
        return "hello";
    }
     
    @RequestMapping("hello/")
    @ApiVersion(2)
    @ResponseBody
    public String hello2(HttpServletRequest request){
        System.out.println("haha2.........");
         
        return "hello";
    }
     
    @RequestMapping("hello/")
    @ApiVersion(5)
    @ResponseBody
    public String hello5(HttpServletRequest request){
        System.out.println("haha5.........");
         
        return "hello";
    }
}

 

現在我們就可以通過 /v1/hello/, /v2/hello/, /v5/hello來分別調用版本1,2,5的管理。當然我們也要解決剛才說的兩點問題,如果用戶通過 /v4/hello/來訪問接口,則要自動適配到 /v2/hello/,因為 v2是比v4低的版本中最新的版本。

再來看下 ApiVersionCondition 這個類。這個類就是我們自定義一個條件篩選器,讓SpringMVC在原有邏輯的基本上添加一個版本號匹配的規則:

public class ApiVesrsionCondition implements RequestCondition<ApiVesrsionCondition> {
 
    // 路徑中版本的前綴, 這里用 /v[1-9]/的形式
    private final static Pattern VERSION_PREFIX_PATTERN = Pattern.compile("v(\\d+)/");
     
    private int apiVersion;
     
    public ApiVesrsionCondition(int apiVersion){
        this.apiVersion = apiVersion;
    }
     
    public ApiVesrsionCondition combine(ApiVesrsionCondition other) {
        // 采用最后定義優先原則,則方法上的定義覆蓋類上面的定義
        return new ApiVesrsionCondition(other.getApiVersion());
    }
 
    public ApiVesrsionCondition getMatchingCondition(HttpServletRequest request) {
        Matcher m = VERSION_PREFIX_PATTERN.matcher(request.getPathInfo());
        if(m.find()){
            Integer version = Integer.valueOf(m.group(1));
            if(version >= this.apiVersion) // 如果請求的版本號大於配置版本號, 則滿足
                return this;
        }
        return null;
    }
 
    public int compareTo(ApiVesrsionCondition other, HttpServletRequest request) {
        // 優先匹配最新的版本號
        return other.getApiVersion() - this.apiVersion;
    }
 
    public int getApiVersion() {
        return apiVersion;
    }
 
}

 

要把這個篩選規則生效的話,要擴展原胡的HandlerMapping,把這個規則設置進去生效,看下CustomRequestMappingHandlerMapping的代碼:

public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
 
    @Override
    protected RequestCondition<ApiVesrsionCondition> getCustomTypeCondition(Class<?> handlerType) {
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
        return createCondition(apiVersion);
    }
 
    @Override
    protected RequestCondition<ApiVesrsionCondition> getCustomMethodCondition(Method method) {
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class);
        return createCondition(apiVersion);
    }
     
    private RequestCondition<ApiVesrsionCondition> createCondition(ApiVersion apiVersion) {
        return apiVersion == null ? null : new ApiVesrsionCondition(apiVersion.value());
    }
}

 

最后,得讓SpringMVC加載我們定義的CustomRequestMappingHandlerMapping以覆蓋原先的RequestMappingHandlerMapping, 所以要去掉前面說的<mvc:annotation-driven/>這個配置,我們通過JavaConfig的方式注入:

@Configuration
public class WebConfig extends WebMvcConfigurationSupport{
 
    @Override
    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandlerMapping();
        handlerMapping.setOrder(0);
        handlerMapping.setInterceptors(getInterceptors());
        return handlerMapping;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM