项目中需要兼顾老项目,同时提供新的接口,这时就需要实现多版本,小事安排:

 

 1 自定义注解:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiVersion {
    double value() default 0;
}

2 自定义一个RequestCondition

import org.springframework.web.servlet.mvc.condition.RequestCondition;

import javax.servlet.http.HttpServletRequest;


public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {

    private double version;

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

    public double getVersion() {
        return version;
    }

    /**
     * 和另外的请求匹配条件进行合并,具体合并逻辑由实现提供
     *
     * @param apiVersionCondition
     * @return
     */
    @Override
    public ApiVersionCondition combine(ApiVersionCondition apiVersionCondition) {
        return new ApiVersionCondition(apiVersionCondition.getVersion());
    }

    /**
     * 检查当前请求匹配条件和指定请求request是否匹配,如果不匹配返回null
     * 如果匹配,生成一个新的请求匹配条件,该新的请求匹配条件是当前请求匹配条件
     * 针对指定请求request的剪裁。
     * 举个例子来讲,如果当前请求匹配条件是一个路径匹配条件,包含多个路径匹配模板,
     * 并且其中有些模板和指定请求request匹配,那么返回的新建的请求匹配条件将仅仅
     * 包含和指定请求request匹配的那些路径模板。
     *
     * @param httpServletRequest
     * @return
     */
    @Override
    public ApiVersionCondition getMatchingCondition(HttpServletRequest httpServletRequest) {
        String requestURI = httpServletRequest.getRequestURI();
        return this;
    }

    /**
     * 针对指定的请求对象request比较两个请求匹配条件。
     * 该方法假定被比较的两个请求匹配条件都是针对该请求对象request调用了
     * #getMatchingCondition方法得到的,这样才能确保对它们的比较
     * 是针对同一个请求对象request,这样的比较才有意义(最终用来确定谁是
     * 更匹配的条件)。
     *
     * @param apiVersionCondition
     * @param httpServletRequest
     * @return
     */
    @Override
    public int compareTo(ApiVersionCondition apiVersionCondition, HttpServletRequest httpServletRequest) {
        return Double.compare(apiVersionCondition.getVersion(),this.getVersion());
    }
}

3 自定义RequestMappingHandlerMapping

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 VersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping {

    @Override
    protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        ApiVersion annotation = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);

        return createCondition(annotation);
    }

    @Override
    protected RequestCondition<?> getCustomMethodCondition(Method method) {
        ApiVersion annotation = AnnotationUtils.findAnnotation(method, ApiVersion.class);

        return createCondition(annotation);
    }

    private ApiVersionCondition createCondition(ApiVersion annotation) {
        return null == annotation ? null : new ApiVersionCondition(annotation.value());
    }
}

4 将自定义的RequestMappingHandlerMapping放入到spring中

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

@SpringBootConfiguration
public class ApiVersionWebMvcRegistrationsAdapter implements WebMvcRegistrations {

    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        return new VersionRequestMappingHandlerMapping();
    }
}

5 controller

@RestController
public class VersionController {

    @ApiVersion(1.0)
    @RequestMapping(value = "/get/version/{version}",method = RequestMethod.GET)
    public String getName() {
        return "this is version 1.0";
    }

    @ApiVersion(2.0)
    @RequestMapping(value = "/get/version12/{version}",method = RequestMethod.GET)
    public String getNameV1() {
        return "this is version 2.0";
    }
}

打完收工,搞定!

 

 

 

 

 

 

 

 

 

 

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐