Restful版本控制(版本号)

一.通过头请求方式加版本号

  • 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版本

三. 通过入参加版本号

通过入参就不介绍了,无非就是写一些业务逻辑,分不同的分支。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值