基于CustomCondition实现spring mvc的版本号路由插件

本文介绍了如何使用CustomCondition实现Spring MVC的版本号路由插件,允许不同版本的接口在同一URL下通过请求头进行路由和隔离。支持快速接入,可自定义版本号规则,并详细阐述了实现过程和核心逻辑。
摘要由CSDN通过智能技术生成

基于CustomCondition实现spring mvc的版本号路由插件

需求

先描述下我实现的个人需求, 项目中有对接客户端, 客户端的版本号是多样且并存的.
有些时候提供给客户端的某个接口, 在不同的版本号下逻辑不同, 且不能做成兼容. 需要不同版本的接口并存. 此时一般方案可能需要修改url地址, 开一个新接口给新版本.
所以这里期望有一种办法可以使不同版本的接口并存在同一个url下, 只通过 header请求头来实现路由和隔离.

提出以下几点效果预设

  1. 支持快速接入
  2. 针对不同项目中的版本号规则能自主切换, 支持扩展
  3. 不影响不需要版本控制的接口(有些接口所有版本客户端都一致那种)

实现后效果

快速接入

  1. 导入依赖(没上传官方仓库, 只能通过down源码先打包到本地或者私有仓库之类的)
  2. 在springBoot启动类上加注解 @EnableWebVersionControl
  3. (可选)在application.yml/application.xml中配置参数,
    提供了两个参数
    webmvc.version.mapping.header-key
    表示请求中的版本号字段放在哪个key里, 默认值为version
    webmvc.version.mapping.clazz
    表示启用的版本判断逻辑是什么, 目前提供了两种判断, 一种是int型, IntegerVersionRequestCondition
    另一种是String型, StringVersionRequestCondition, 默认是型
    int型和string型的区别:
    int型对 数字编号类型的版本号生效
    string型对 形如 2.1.2 类型的版本号生效, 不限制.的位数
  4. 对需要版本号控制的接口替换注释 @PostMappingWithVersion(目前只对POST做了支持), 在minVersion, maxVersion属性上加上版本号上下限, 可选加order排序, 数字越小优先级越高
  5. 客户端请求接口测试, 通过请求头实现路由, 若版本号不在匹配规则里, 则会返回404.版本号规则左右都为闭区间

效果

  1. 不影响不加控制的接口
  2. 加控制的接口支持版本号匹配
  3. 某个请求匹配到多个适配的接口时, 支持通过order参数排序, 数字越小优先级越高, 注: 排序只在除版本号外的属性完全相同的情况下才生效

实现方案

大概的流程思路如下:

  1. 先写一个自己的注解, 类似@RequestMapping这种, 让版本规则能作为参数写入注解
  2. 通过spring mvc代码中预留的customCondition实现版本号匹配和校验规则, 主要是实现getMatchingCondition和compareTo方法, 为了便于扩展, 这里实现一个抽象层的版本号控制器. 具体的匹配规则和校验等规则预留接口供子类实现.
  3. 通过实现RequestMappingHandlerMapping中的getCustomMethodCondition方法, 将实现好的CustomCondition注入到HandlerMapping., 为了便于扩展, 具体注入哪种类型的customCondition支持动态扩展. 通过获取class的方式反射注入.
  4. 通过WebMvcRegistrations注入自实现的RequestMappingHandlerMapping,
  5. 通过@Import编写注解开关类实现类似@EnableXxx功能的注解
  6. 编写一个抽象的VersionRequestCondition类, 支持扩展和切换version匹配规则.

源码

代码比较多, 直接上传github了
https://github.com/sunwenjieIT/spring-boot-webmvc-version-mapping
后面讲下比较核心的几个点

重要逻辑点

  1. 怎么避免相同的url在注入容器时不报错?
    其实只需要实现RequestCondition接口, 把版本号信息放入

正常情况下 两个完全相同的url(所有的其他http参数都一致, 如是否post/get, 对应的请求头等等), 在启动时就会报错, 提示你重复了. 这个重复的校验是在注入过程中校验的.
AbstractHandlerMethodMapping.MappingRegistry.assertUniqueMethodMapping(HandlerMethod newHandlerMethod, T mapping)
这个方法负责实际的校验工作. 做两件事.
1. 先查注册的url是否有之前已经注册的HandlerMethod
2. 如果发现之前已经注册了一个HandlerMethod, 那比对一下两者是否一致.
3. 步骤2中结果若比对一致, 报错, 提示mapping重复注册.
有两个部分的代码要重点看
第一个是T的这个mapping, 作为map的key, 他的hash方法是被重写过的. T的类型根据接口的种类来区分, 种类说的是接入的方式, 比如xml配置的, 从@Controller来的等等, 通常接口通过@Controller来的则T类型为 RequestMappingInfo. 他的hash被重写成了如下形式

	@Override
	public int hashCode() {
   
		return (this.patternsCondition.hashCode() * 31 +  // primary differentiation
				this<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值