版本控制出现的需求
每一个项目完成上线之后它的需求逻辑等都不是一成不变的(尤其是那种追求完美的客户)!!那么接口在调用的过程中也会发生很多的变化。因此我们为了新老客户的操作体验感接口需要不断的完善不断的更新!这个时候我们就需要提供不同的需求调用不同的接口版本来实现。
第一步
自定义注解
第二步
ApiVersionCondition
作用:自定义实现RequestCondition接口 实现版本条件处理
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import javax.servlet.http.HttpServletRequest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Administrator
* @创建人 duo
* @创建时间 2020-11-24
* @邮箱 928970622@qq.com
* @作用 版本条件处理
*/
public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {
// 用于匹配request中的版本号 v1 v2
// 路径中版本的前缀, 这里用 /v[1-9]/的形式
private final static Pattern VERSION_PREFIX_PATTERN = Pattern.compile("v(\\d+)/");
// 保存当前的版本号
private int apiVersion;
// 保存所有接口的最大版本号
private static int maxVersion = 1;
public int getApiVersion() {
return apiVersion;
}
public ApiVersionCondition(int apiVersion) {
this.apiVersion = apiVersion;
}
@Override
public ApiVersionCondition getMatchingCondition(HttpServletRequest request) {
// 正则匹配请求的uri,看是否有版本号 v1
Matcher m = VERSION_PREFIX_PATTERN.matcher(request.getRequestURI());
if (m.find()) {
// 超过当前最大版本号或者低于最低的版本号均返回不匹配
Integer version = Integer.valueOf(m.group(1));
if (version >= this.apiVersion) {
return this;
}
}
return null;
}
@Override
public int compareTo(ApiVersionCondition other, HttpServletRequest httpServletRequest) {
// 优先匹配最新的版本号
return other.getApiVersion() - this.apiVersion;
}
@Override
public ApiVersionCondition combine(ApiVersionCondition other) {
// 采用最后定义优先原则,则方法上的定义覆盖类上面的定义
return new ApiVersionCondition(other.getApiVersion());
}
}
第三步
自定义CustomRequestMappingHandlerMapping
作用:获得注解标注的接口路径,然后返回自定义的实现类。
/**
* @author Administrator
* @创建人 duo
* @创建时间 2020-11-24
* @邮箱 928970622@qq.com
* @作用 处理器
*/
public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
@Override
protected RequestCondition<ApiVersionCondition> getCustomTypeCondition(Class<?> handlerType) {
// 判断是否有@ApiVersion注解,构建基于@ApiVersion的RequestCondition
ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
return createCondition(apiVersion);
}
@Override
protected RequestCondition<ApiVersionCondition> getCustomMethodCondition(Method method) {
ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class);
return createCondition(apiVersion);
}
private RequestCondition<ApiVersionCondition> createCondition(ApiVersion apiVersion) {
return apiVersion == null ? null : new ApiVersionCondition(apiVersion.value());
}
}
第四步
WebConfig
springboot中的WebMvcConfigurationSupport可以配置多个路由 放到一个配置类中(必不可少的一步)相信小伙伴都明白
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
/**
* @author Administrator
* @创建人 duo
* @创建时间 2020-11-24
* @邮箱 928970622@qq.com
* @作用 多个路由的配置
*/
@SpringBootConfiguration
public class WebConfig extends WebMvcConfigurationSupport {
@Override
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandlerMapping();
handlerMapping.setOrder(0);
handlerMapping.setInterceptors(getInterceptors());
return handlerMapping;
}
}
测试
既然前缀已配置完毕那么我们就来看一下效果 也就是测试一下
这边也不新建测试类了直接在现有类上走起
@GetMapping("{version}/api")
@ApiVersion(1)
public H ceshi1(){
return new H(200,"版本1");
}
@GetMapping("{version}/api")
@ApiVersion(2)
public H ceshi2(){
return new H(200,"版本2");
}
还有个小问题我这个项目集成了Spring Security 所以去放开一下权限否则会401的呦
放开之后在进行测试效果如下
下期再见