Spring扩展之基于HandlerMapping实现接口灰度发布实例

 更新时间:2023年08月31日 08:32:39   作者:轻尘×  
这篇文章主要介绍了Spring扩展之基于HandlerMapping实现接口灰度发布实例,灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式,灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度,需要的朋友可以参考下

背景

面试经常被问到,你了解spring源码吗?有基于spring做过什么扩展吗?

除了PropertyPlaceholderConfigurer处理占位符(被说烂了)还有其他的吗?

看了springmvc的源码,有了一个新的案例可讲(吹)

基于HandlerMapping实现接口灰度发布

说这个之前可以先铺垫一下,将故事讲的生动一点,我们来简单模拟一下。

面试官:“简历上说你对spring源码比较熟悉,能简单讲讲你对ioc、aop的理解吗?”

张三:“ioc是……aop是……巴拉巴拉”

(背了一大段八股文,毫无新意,面试官面无表情,然后打断张三,继续问)

面试官:你说对spring源码很熟悉,有多熟悉,在实际开发中有用过?扩展过吗?

张三:“有过呀,当时有个系统,升级改动比较大,对于同一批接口,老用户和新用户返回的数据不一样,为了实现系统的最小化改动,我当时就用spring的HandlerMapping解决了这个问题,前端访问的接口不变,只在参数中加一个接口版本号,就能实现灰度……,具体实现是这样的”

实现方案

自定义注解

新增一个自定义注解,用来标注接口的适配的版本号,默认为1.0版本

package com.fast.alibaba.annotation;
import java.lang.annotation.*;
/**
 * 自定义版本号注解
 */
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiVersion {
    double value() default 1.0;
}
 

自定义HandleMapping

自定义HandleMapping,继承spring家的HandleMapping,并重写两个getCustomTypeCondition方法

package com.fast.alibaba.handlemapping;
import com.fast.alibaba.annotation.ApiVersion;
import com.fast.alibaba.condition.ApiVersionRequestCondition;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.Method;
public class ApiVersionHandleMapping extends RequestMappingHandlerMapping {
    @Override
    protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        ApiVersion apiVersion = AnnotationUtils.getAnnotation(handlerType, ApiVersion.class);
        return new ApiVersionRequestCondition(apiVersion != null ? apiVersion.value() : 1.0);
    }
    @Override
    protected RequestCondition<?> getCustomMethodCondition(Method method) {
        ApiVersion apiVersion = AnnotationUtils.getAnnotation(method, ApiVersion.class);
        if(apiVersion == null){
            apiVersion = AnnotationUtils.getAnnotation(method.getDeclaringClass(), ApiVersion.class);
        }
        return new ApiVersionRequestCondition(apiVersion != null ? apiVersion.value() : 1.0);
    }
}

实现RequestCondition接口

以便识别前端传送的版本与接口上注解版本匹配

package com.fast.alibaba.condition;
import com.alibaba.cloud.commons.lang.StringUtils;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import javax.servlet.http.HttpServletRequest;
public class ApiVersionRequestCondition implements RequestCondition<ApiVersionRequestCondition> {
    private double apiVersion = 1.0;
    private static final String VERSION_NAME = "api-version";
    public double getApiVersion() {
        return apiVersion;
    }
    public ApiVersionRequestCondition(double apiVersion){
        this.apiVersion=apiVersion;
    }
    @Override
    public ApiVersionRequestCondition combine(ApiVersionRequestCondition method) {
        return method;
    }
    @Override
    public int compareTo(ApiVersionRequestCondition other, HttpServletRequest request) {
        return Double.compare(other.getApiVersion(),this.getApiVersion());
    }
    @Override
    public ApiVersionRequestCondition getMatchingCondition(HttpServletRequest request) {
        double reqVersionDouble = 1.0;
        String reqVersion = request.getHeader(VERSION_NAME);
        if(StringUtils.isEmpty(reqVersion)){
            reqVersion = request.getParameter(VERSION_NAME);
        }
        if(!StringUtils.isEmpty(reqVersion)){
            reqVersionDouble = Double.parseDouble(reqVersion);
        }
        if(this.getApiVersion() == reqVersionDouble){
            return this;
        }
        return null;
    }
}

自定义WebMvcRegistrations

package com.fast.alibaba.register;
import com.fast.alibaba.handlemapping.ApiVersionHandleMapping;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
/**
 * 注册自定义的 ApiVersionHandleMapping
 */
public class ApiVersionMappingRegister implements WebMvcRegistrations {
    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        return new ApiVersionHandleMapping();
    }
}

注入WebMvcRegistrations

package com.fast.alibaba.config;
import com.fast.alibaba.register.ApiVersionMappingRegister;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BaseConfiguration {
    @Bean
    public WebMvcRegistrations getWebMvcRegistrations(){
        return new ApiVersionMappingRegister();
    }
}

测试类

package com.fast.alibaba.controller;
import com.fast.alibaba.annotation.ApiVersion;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestHandlerMappingController {
    @GetMapping("/getInfo")
    @ApiVersion(1.0)
    public String getSomeInfoByV1(){
        return "version 1.0";
    }
    @GetMapping("/getInfo")
    @ApiVersion(2.0)
    public String getSomeInfoByV2(){
        return "version 2.0";
    }
    @GetMapping("/getInfo")
    @ApiVersion(3.0)
    public String getSomeInfoByV3(){
        return "version 3.0";
    }
}

到此这篇关于Spring扩展之基于HandlerMapping实现接口灰度发布实例的文章就介绍到这了,更多相关基于HandlerMapping实现接口灰度发布内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java递归以及根据节点取子集合方式

    Java递归以及根据节点取子集合方式

    文章介绍了Java中递归的使用方法,包括如何根据节点构建树形结构以及如何反向递归获取所有子节点,提供了递归方法的参数解释和示例代码,希望对大家有所帮助
    2024-12-12
  • 30w+数据使用RedisTemplate pipeline空指针NullPointerException异常分析

    30w+数据使用RedisTemplate pipeline空指针NullPointerException异常分析

    这篇文章主要为大家介绍了30w+数据使用RedisTemplate pipeline空指针NullPointerException异常分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • log4j中logger标签中additivity属性的用法说明

    log4j中logger标签中additivity属性的用法说明

    这篇文章主要介绍了log4j中logger标签中additivity属性的用法说明,基于很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 详解SpringBoot读取配置文件的N种方法

    详解SpringBoot读取配置文件的N种方法

    这篇文章主要介绍了详解SpringBoot读取配置文件的N种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • Java经典排序算法之希尔排序详解

    Java经典排序算法之希尔排序详解

    这篇文章主要为大家详细介绍了Java经典排序算法之希尔排序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • 从0到1学SpringCloud之SpringCloud gateway网关路由配置示例详解

    从0到1学SpringCloud之SpringCloud gateway网关路由配置示例详解

    Spring Cloud Gateway的目标提供统一的路由方式且基于Filter 链的方式提供了网关基本的功能, 例如:安全、监控、指标和限流 ,这篇文章主要介绍了从0到1学SpringCloud之SpringCloud gateway网关路由配置示例详解,需要的朋友可以参考下
    2023-04-04
  • SpringBoot查询数据库导出报表文件方式

    SpringBoot查询数据库导出报表文件方式

    这篇文章主要介绍了SpringBoot查询数据库导出报表文件方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • Spring中如何使用Comparator接口

    Spring中如何使用Comparator接口

    Comparator比较器接口可以将自身传递给排序方法(比如Collections.sort或Arrays.sort),以便对排序顺序进行精确控制。本文讲述Spring中如何使用Comparator接口
    2021-06-06
  • java调用接口返回乱码问题及解决

    java调用接口返回乱码问题及解决

    这篇文章主要介绍了java调用接口返回乱码问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • SpringMVC整合SSM实现异常处理器详解

    SpringMVC整合SSM实现异常处理器详解

    SpringMVC是一种基于Java,实现了Web MVC设计模式,请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦。基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,SpringMVC也是要简化我们日常Web开发
    2022-10-10

最新评论