• 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;
        }
    }
    人生如修仙,岂是一日间。何时登临顶,上善若水前。
  • 相关阅读:
    BurpSuite—-Spider模块(蜘蛛爬行)
    BurpSuite系列(一)----Proxy模块(代理模块)
    hadoop HA集群搭建步骤
    HBase详解
    MapReduce两种执行环境介绍:本地测试环境,服务器环境
    HBase性能优化方法总结
    HDFS原理解析
    ZooKeeper 典型应用场景
    Redis总结
    基于Apache Curator框架的ZooKeeper使用详解
  • 原文地址:https://www.cnblogs.com/f-society/p/10636775.html
Copyright © 2020-2023  润新知