请求路径中增加版本号
1、定义注解:@ApiVersion
@Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface ApiVersion { /** * 标识版本号 * @return */ int value(); //描述 String describe(); }
2、重写RequestMappingHandlerMapping一些方法
public class CustomRequestMappingHandlerMapping 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()); } }
3、匹配规则版本号
public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> { // 路径中版本的前缀, 这里用 /v[1-9]/的形式 private final static Pattern VERSION_PREFIX_PATTERN = Pattern.compile("v(\d+)/"); /** * api的版本 */ private int apiVersion; public ApiVersionCondition(int apiVersion) { this.apiVersion = apiVersion; } @Override public ApiVersionCondition combine(ApiVersionCondition apiVersionCondition) { // 采用最后定义优先原则,则方法上的定义覆盖类上面的定义 return new ApiVersionCondition(apiVersionCondition.getApiVersion()); } /** * 根据request查找匹配到的筛选条件 */ @Override public ApiVersionCondition getMatchingCondition(HttpServletRequest httpServletRequest) { Matcher m = VERSION_PREFIX_PATTERN.matcher(httpServletRequest.getRequestURI()); if(m.find()){ Integer version = Integer.valueOf(m.group(1)); if(version >= this.apiVersion) { return this; } } return null; } /** * 不同筛选条件比较,用于排序 * @param apiVersionCondition * @param httpServletRequest * @return */ @Override public int compareTo(ApiVersionCondition apiVersionCondition, HttpServletRequest httpServletRequest) { // 优先匹配最新的版本号 return apiVersionCondition.getApiVersion() - this.apiVersion; } public int getApiVersion() { return apiVersion; } }
4、增加相应注解
@RequestMapping("{version}") public class BaseApi1 { @ApiVersion(value=1,describe="当前版本控制为v1") @RequestMapping("/demo") public String demoVersion1(){ return "version1"; } @ApiVersion(value=2,describe="当前版本控制为v2") @RequestMapping("/demo") public String demoVersion2(){ return "version2"; } }
5、请求路径:http://localhost:8080/v1/xxxx
统一接口前缀
@Controller @RequestMapping("/v1") public class FunctionControllerA{ @RequestMapping("/functionA") public void functionA(){ //Some thing to do... } } @Controller @RequestMapping("/v1") public class FunctionControllerB{ @RequestMapping("/functionB") public void functionB(){ //Some thing to do... } }
当存在多个/v1开头的controller且后续需要统一更改v1为v2这种,则需要改动点多,可修改为:
声明一个统一api请求路径接口
@RequestMapping("/v1") public interface VersionPathAware{}
实现此接口
@Controller public class FunctionControllerA implements VersionPathAware { @RequestMapping("/functionA") public void functionA(){ //Some thing to do... } } @Controller public class FunctionControllerB implements VersionPathAware { @RequestMapping("/functionB") public void functionB(){ //Some thing to do... } }