SpringMVC多版本实现

自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ApiVersion {
    /**
     * 版本号
     * @return
     */
    double version();
}

自定义RequestCondition

@Data
public class ApiVersionRequestCondition implements RequestCondition<ApiVersionRequestCondition> {

    /**
     * 版本号
     */
    private double version;

    public ApiVersionRequestCondition(double version) {
        this.version = version;
    }

    /**
     * 参数
     */
    private static final String HEADER_VERSION_PARAM = "version";

    /**
     * 先进行方法上的注解,然后是类上的注解
     * 以方法上的注解为准
     * @param other
     * @return
     */
    @Override
    public ApiVersionRequestCondition combine(ApiVersionRequestCondition other) {
        return other;
    }

    /**
     * 如果此请求匹配这个条件就返会此实例,否则返回null
     * @param request
     * @return
     */
    @Override
    public ApiVersionRequestCondition getMatchingCondition(HttpServletRequest request) {
        //将version字段放置在header中,区分版本号
        double v = getHeaderVersion(request);
        if (this.version > v) {
            return null;
        }
        return this;
    }

    /**
     * 当前实例比较其他实例,返回最优解
     * @param other
     * @param request
     * @return
     */
    @Override
    public int compareTo(ApiVersionRequestCondition other, HttpServletRequest request) {
        if (other.version <= this.version) {
            return -1;
        }
        return 1;
    }

    public double getHeaderVersion(HttpServletRequest request) {
        String version = request.getHeader(HEADER_VERSION_PARAM);
        if (StringUtils.isEmpty(version)) {
            return 1.0;
        }
        try {
            return Double.parseDouble(version);
        } catch (Exception e) {
            //ignore
            return 1.0;
        }
    }

修改RequestMappingHandlerMapping

将自定义的RequestCondition添加到HandlerMapping映射处理器中

public class ApiVersionHandlerMapping extends RequestMappingHandlerMapping {

    private static final ApiVersionRequestCondition DEFAULT_API_VERSION = new ApiVersionRequestCondition(1.0);

    /**
     * 处理类上的注解
     * @param handlerType
     * @return
     */
    @Override
    protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        //获取类上的注解
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
        return createApiVersionRequestCondition(apiVersion);
    }

    /**
     * 处理方法上的注解
     * @param method
     * @return
     */
    @Override
    protected RequestCondition<?> getCustomMethodCondition(Method method) {
        //首先获取方法上注解,如果方法上无注解再获取类上的注解
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class);
        if (apiVersion == null) {
            apiVersion = AnnotationUtils.findAnnotation(method.getDeclaringClass(), ApiVersion.class);
        }
        return createApiVersionRequestCondition(apiVersion);
    }

    private ApiVersionRequestCondition createApiVersionRequestCondition(ApiVersion apiVersion) {
        if (apiVersion == null) {
            return DEFAULT_API_VERSION;
        }
        return new ApiVersionRequestCondition(apiVersion.version());
    }

替换Spring容器默认的RequestMappingHandlerMapping

public class ApiVersionWebConfiguration implements WebMvcRegistrations {
    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        return new ApiVersionHandlerMapping();
    }
}

通过注解的方式启动

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(ApiVersionWebConfiguration.class)
public @interface EnableWebApiVersion {
}
posted @ 2021-11-20 11:32  往事随雨  阅读(47)  评论(0)    收藏  举报