SpingMVC框架实现restfull接口的版本控制
2016-08-05 16:02
357 查看
互联网发展到今天,基于restfull开发的系统也越来越多,不再局限于jsp等脚本语言来实现动态数据的展示,而是通过后台提供的http接口给前端调用,但是当系统越做越大,同一个接口可能会不断的修改,一旦调用方式发生改变,后果是非常严重的,客户端将无法正常调用,除非强制客户端升级到最新版本,这个也是不太现实的,那怎么办呢?我们想到的就是通过版本来控制同一个接口,类似这样的一个地址:http://localhost:8080/api/v1,其中v1就是当前所用到的版本,那怎么来实现呢?直接上代码:
首先自定义一个注解:
这个注解标识当前接口所对应的版本
这样我们通过v1,v2这样的地址就能访问到对应的版本,但是这样会有一个问题,如果客户端传入v3,但是所定义的版本并没有定义v3,此时客户端肯定会报404错误,也就是没有这个页面,怎么办呢,相当的就是拦截器,如果传入的版本没有,则默认访问最新的版本,请看代码:
这样,当传入的版本没有则默认会访问最新的版本,还没有完,还需要注册这个拦截器:
如此就实现了最基本的对api的版本控制。
首先自定义一个注解:
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; @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface ApiVersion { /** * 标识版本号 * @return */ int value(); }
这个注解标识当前接口所对应的版本
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import cn.sunsharp.platform.annotation.ApiVersion; import cn.sunsharp.platform.web.BaseController; @RequestMapping("{version}") @RestController public class HelloController extends BaseController { @ApiVersion(1) @RequestMapping("hello") public String hello1(){ return "hello1"; } @ApiVersion(2) @RequestMapping("hello") public String hello2(){ return "hello2"; } }
这样我们通过v1,v2这样的地址就能访问到对应的版本,但是这样会有一个问题,如果客户端传入v3,但是所定义的版本并没有定义v3,此时客户端肯定会报404错误,也就是没有这个页面,怎么办呢,相当的就是拦截器,如果传入的版本没有,则默认访问最新的版本,请看代码:
import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import org.springframework.web.servlet.mvc.condition.RequestCondition; public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> { // 路径中版本的前缀, 这里用 /v[1-9]/的形式 private final static 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) { 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; } }
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; import cn.sunsharp.platform.annotation.ApiVersion; public class CustomRequestMappingHandlerMapping 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()); } }
这样,当传入的版本没有则默认会访问最新的版本,还没有完,还需要注册这个拦截器:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import cn.sunsharp.platform.version.CustomRequestMappingHandlerMapping; @Configuration public class WebConfig extends WebMvcConfigurationSupport { @Override @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { RequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandlerMapping(); handlerMapping.setOrder(0); handlerMapping.setInterceptors(getInterceptors()); return handlerMapping; } }
如此就实现了最基本的对api的版本控制。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序