zoukankan      html  css  js  c++  java
  • 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;
        }
    }
    人生如修仙,岂是一日间。何时登临顶,上善若水前。
  • 相关阅读:
    [转载]使用SecureCRT进行vim编辑的时候,小键盘变成字母的解决办法
    [转载]运行中的程序突然出现"Killed"原因
    [转载]IPv6地址表示方法详解
    【转载】深入浅出Pairwise算法
    [转载]不要用强制方法杀掉python线程
    [转载]Python SQLite3的问题sqlite3.ProgrammingError: SQLite objects created in a thread
    SQL语句中distinct的分页和查询数据数量
    SQL语句中获取时间的方法
    SQLService中使用SQL语句书写分页
    使用Angular下拉自动加载
  • 原文地址:https://www.cnblogs.com/f-society/p/10636775.html
Copyright © 2011-2022 走看看