springmvc实现webapi接口版本兼容

文章出处:http://www.cnblogs.com/jcli/p/springmvc_restful_version.html

主要实现webapi版本兼容和降级,比如访问api/v3/hello但是服务端没有这个版本只有api/v2/hello可以默认降级到该版本

下面贴部分代码:
1.ApiVersion.java 定义版本注解

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;

import org.springframework.web.bind.annotation.Mapping;

/**
 * 
 * @author wszhang
 *
 * @create 2017年4月9日 上午12:57:04

 * @version 1.0

 * @description 接口版本标识注解
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface ApiVersion {
    int value();
}

2.ApiVesrsionCondition 版本筛选,注意request.getPathInfo()和request.getPathInfo()区别否则会有空指针,在原作者基础上加了一个case使错误版本号默认返回最新版本

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.servlet.mvc.condition.RequestCondition;

/**
 * 
 * @author wszhang
 *
 * @create 2017年4月9日 上午12:57:39

 * @version 1.0

 * @description 版本号匹配筛选器
 */
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) {
        //request.getPathInfo()
        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;
    }

}

2.CustomRequestMappingHandlerMapping自定义RequestMappingHandlerMapping

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.servlet.mvc.condition.RequestCondition;

/**
 * 
 * @author wszhang
 *
 * @create 2017年4月9日 上午12:57:39

 * @version 1.0

 * @description 版本号匹配筛选器
 */
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) {
        //request.getPathInfo()
        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;
    }

}

4.配置文件及小结,原作者已经说明采用这种方式会导致mvc:annotation-driven不能使用,做过不少尝试避免此问题,但是均没有好的解决方案,主要是不设置ByteArrayHttpMessageConverter会导致接口返回数据乱码,遂重新注入了RequestMappingHandlerAdapter

<!--自定义requestMapping解析器 -->
<bean class="com.demo.util.version.CustomRequestMappingHandlerMapping">
        <property name="order" value="0" />
    </bean>

<!-- 解决乱码问题 -->
<bean       class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean               class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
                <bean           class="org.springframework.http.converter.StringHttpMessageConverter">
                    <property name="supportedMediaTypes">
                        <list>
                <value>text/plain;charset=UTF-8</value>
                        </list>
                    </property>
                </bean> 
            </list>
        </property>
    </bean>

原作者采用JavaConfig的方式注入CustomRequestMappingHandlerMapping,代码如下:

@Configuration
public class WebConfig extends WebMvcConfigurationSupport{

    @Override
    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandlerMapping();
        handlerMapping.setOrder(0);
        handlerMapping.setInterceptors(getInterceptors());
        return handlerMapping;
    }
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值