传统Spring Mvc配置和Spring boot类似。
- 定义版本注解
import org.springframework.web.bind.annotation.Mapping;
import java.lang.annotation.*;
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface ApiVersion {
/**
* 版本号
* @return
*/
int value() default 1;
}
- 版本uri解析规则
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import javax.servlet.http.HttpServletRequest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ApiVesrsionCondition implements RequestCondition<ApiVesrsionCondition> {
// 路径中版本的前缀, 这里用 /v[1-9]/的形式
private final static Pattern VERSION_PREFIX_PATTERN = Pattern.compile("v(\\d+)/");
private int apiVersion;
public ApiVesrsionCondition(int apiVersion) {
this.apiVersion = apiVersion;
}
@Override
public ApiVesrsionCondition combine(ApiVesrsionCondition other) {
// 采用最后定义优先原则,则方法上的定义覆盖类上面的定义
return new ApiVesrsionCondition(other.getApiVersion());
}
@Override
public int compareTo(ApiVesrsionCondition other, HttpServletRequest request) {
// 优先匹配最新的版本号
return other.getApiVersion() - this.apiVersion;
}
public int getApiVersion() {
return apiVersion;
}
@Override
public ApiVesrsionCondition getMatchingCondition(HttpServletRequest request) {
Matcher m = VERSION_PREFIX_PATTERN.matcher(request.getServletPath());
if (m.find()) {
Integer version = Integer.valueOf(m.group(1));
if (version >= this.apiVersion)
return this;
} else {
return this;
}
return null;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + apiVersion;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ApiVesrsionCondition other = (ApiVesrsionCondition) obj;
if (apiVersion != other.apiVersion)
return false;
return true;
}
}
- 继承重写请求处理
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 CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
@Override
protected RequestCondition<ApiVesrsionCondition> getCustomTypeCondition(Class<?> handlerType) {
ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
return createCondition(apiVersion);
}
@Override
protected RequestCondition<ApiVesrsionCondition> getCustomMethodCondition(Method method) {
ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class);
return createCondition(apiVersion);
}
private RequestCondition<ApiVesrsionCondition> createCondition(ApiVersion apiVersion) {
return apiVersion == null ? null : new ApiVesrsionCondition(apiVersion.value());
}
}
- 版本控制使用
@RestController
@RequestMapping("api/{version}/test")
public class TestRest1 {
@ApiVersion(1)
@GetMapping
public String test1() {
return "Ok";
}
@ApiVersion(2)
@GetMapping
public String test2() {
return "Ok";
}
}
@RestController
@RequestMapping("api")
public class TestRest1 {
@ApiVersion(1)
@GetMapping("{version}/test")
public String test1() {
return "Ok";
}
@ApiVersion(2)
@GetMapping("{version}/test")
public String test2() {
return "Ok";
}
}
集成配置
- Spring Boot 配置
public class DefaultMvcConfig extends WebMvcConfigurationSupport {
@Override
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandlerMapping();
handlerMapping.setOrder(0);
handlerMapping.setInterceptors(getInterceptors());
return handlerMapping;
}
// ...
}
- 传统Spring Mvc项目配置
// spring-mvc.xml,增加配置
<bean class="com.xxx.CustomRequestMappingHandlerMapping">
<property name="order" value="0" />
</bean>