springmvc实现webapi接口版本兼容

来源:互联网 发布:淘宝钻展图 编辑:程序博客网 时间:2024/05/07 00:17

文章出处: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@Mappingpublic @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,代码如下:

@Configurationpublic class WebConfig extends WebMvcConfigurationSupport{    @Override    @Bean    public RequestMappingHandlerMapping requestMappingHandlerMapping() {        RequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandlerMapping();        handlerMapping.setOrder(0);        handlerMapping.setInterceptors(getInterceptors());        return handlerMapping;    }}
0 0
原创粉丝点击