一.通过头请求方式加版本号
- 1.自定义注解 ApiVersion
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <Description:> 自定义版本号注解<br>
*
* @author xx<br>
* @version 1.0 <br>
* @taskId <br>
* @CreateDate xx<br>
* @since <br>
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiVersion {
int value() default 1;
}
- 2.自定义条件筛选器 ApiVersionCondition
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
/**
* <Description:> 自定义一个条件筛选器,让SpringMVC在原有逻辑的基本上添加一个版本号匹配的规则<br>
*
* @author xx<br>
* @version 1.0 <br>
* @taskId <br>
* @CreateDate xx <br>
* @since <br>
*/
public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {
// 头请求中的版本号规则 这里用 v[1-9]/的形式
private static final Pattern VERSION_PREFIX_PATTERN = Pattern.compile("v(\\d+)");
private int apiVersion;
public ApiVersionCondition(int apiVersion) {
this.apiVersion = apiVersion;
}
public ApiVersionCondition combine(ApiVersionCondition other) {
// 采用最后定义优先原则,则方法上的定义覆盖类上面的定义
return new ApiVersionCondition(other.getApiVersion());
}
public ApiVersionCondition getMatchingCondition(HttpServletRequest request) {
// 获取头请求中的版本号;默认是v1;
String apiVersion = request.getHeader("ApiVersion");
if (apiVersion == null) {
apiVersion = "v1";
}
Matcher m = VERSION_PREFIX_PATTERN.matcher(apiVersion);
if (m.find()) {
Integer version = Integer.valueOf(m.group(1));
// 如果请求的版本号大于配置版本号, 则满足
if (version >= this.apiVersion) {
return this;
}
}
return null;
}
public int compareTo(ApiVersionCondition other, HttpServletRequest request) {
// 优先匹配最新的版本号
return other.getApiVersion() - this.apiVersion;
}
public int getApiVersion() {
return apiVersion;
}
}
- 配置条件筛选器规则 ApiVersioningRequestMappingHandlerMapping
import java.lang.reflect.Method;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
/**
* <Description:> 将自定义条件筛选器规则设置生效<br>
*
* @author xx<br>
* @version 1.0 <br>
* @taskId <br>
* @CreateDate xx<br>
* @since <br>
*/
public class ApiVersioningRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
@Override
protected RequestCondition<ApiVersionCondition> getCustomTypeCondition(Class<?> handlerType) {
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());
}
}
- ApiVersionConfig
import org.springframework.boot.autoconfigure.web.WebMvcRegistrationsAdapter;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
/**
* <Description:> <br>
*
* @author xx<br>
* @version 1.0 <br>
* @taskId <br>
* @CreateDate xx <br>
* @since <br>
*/
// 将SpringMVC加载我们定义的ApiVersioningRequestMappingHandlerMapping以覆盖原先的RequestMappingHandlerMapping
@Configuration
public class ApiVersionConfig extends WebMvcRegistrationsAdapter {
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new ApiVersioningRequestMappingHandlerMapping();
}
- 测试类 VersionTestController
public class VersionTestController {
private static final ZSmartLogger LOGGER = ZSmartLogger.getLogger(VersionTestController.class);
@RequestMapping(value = {"/hello"}, method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
@ApiVersion(1)
@ResponseBody
public String helloV1(@RequestBody User user) {
LOGGER.info("start helloV1().......... ");
return "hello from version:1";
}
@RequestMapping(value = "/hello", method = RequestMethod.POST)
@ApiVersion(2)
@ResponseBody
public String helloV2(@RequestBody User user) {
LOGGER.info("start helloV2().......... ");
return "hello from version:2";
}
@RequestMapping(value = "/hello", method = RequestMethod.POST)
@ApiVersion(5)
@ResponseBody
public String helloV5(@RequestBody User user) {
LOGGER.info("start helloV5().......... ");
return "hello from version:5";
}
}
二. 通过URL加版本号
方法都是一样的,只需调整上面的ApiVersionCondition类
- 2.自定义条件筛选器 ApiVersionCondition
public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {
// 路径中版本的前缀, 这里用 /v[1-9]/的形式 (细微差异)
private static final Pattern VERSION_PREFIX_PATTERN = Pattern.compile("/v(\\d+)");
private int apiVersion;
public ApiVersionCondition(int apiVersion) {
this.apiVersion = apiVersion;
}
public ApiVersionCondition combine(ApiVersionCondition other) {
// 采用最后定义优先原则,则方法上的定义覆盖类上面的定义
return new ApiVersionCondition(other.getApiVersion());
}
public ApiVersionCondition getMatchingCondition(HttpServletRequest request) {
// 获取请求的url
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;
}
public int compareTo(ApiVersionCondition other, HttpServletRequest request) {
// 优先匹配最新的版本号
return other.getApiVersion() - this.apiVersion;
}
public int getApiVersion() {
return apiVersion;
}
}
- 测试类 VersionTestController
public class VersionTestController {
private static final ZSmartLogger LOGGER = ZSmartLogger.getLogger(VersionTestController.class);
@RequestMapping(value = "/hello/{version}", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
@ApiVersion(1)
@ResponseBody
public String helloV1(@RequestBody User user) {
LOGGER.info("start helloV1().......... ");
return "hello from version:1";
}
@RequestMapping(value = "/hello/{version}", method = RequestMethod.POST)
@ApiVersion(2)
@ResponseBody
public String helloV2(@RequestBody User user) {
LOGGER.info("start helloV2().......... ");
return "hello from version:2";
}
@RequestMapping(value = "/hello/{version}", method = RequestMethod.POST)
@ApiVersion(5)
@ResponseBody
public String helloV5(@RequestBody User user) {
LOGGER.info("start helloV5().......... ");
return "hello from version:5";
}
}
可通过url直接访问对应的接口;如:http://localhost:8080/hello/v1,如果版本不存在,会进小于它的最新版本;比如 http://localhost:8080/hello/v4会进v2版本
三. 通过入参加版本号
通过入参就不介绍了,无非就是写一些业务逻辑,分不同的分支。