Nah bagaimana jika kita ingin menggunakan versioning pada Rest APInya. Misalnya ada kasus seperti ini :
Kita sudah punya Rest Api : /person. Tetapi pada suatu saat ada pengembangan baru di Api tersebut dan Api yang lama tidak boleh dihilangkan dulu karena masih ada pihak yang menggunakannya. Maka kita perlu memberikan version pada Rest api tersebut. Rest api yg lama akan dibiarkan. Kemudian dibuat rest api yang baru dengan nama /v2/person.
Cara yang paling sederhana yakni kita buat method controller baru dan diberi RequestMapping("/v2/person").
Tapi cara ini sebenarnya membuat code menjadi tidak clean dan tidak konsisten dalam penamaan.
Pada tulisan saya berikut ini akan saja coba cara untuk melakukan versioning menggunakan @Annotation dan custom RequestMapping.
1. Kita buat dulu class ApiVersion annotation
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiVersion {
int[] value();
}
2. Buat class custom RequestMapping handler
public class ApiVersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
private final String prefix;
public ApiVersionRequestMappingHandlerMapping(String prefix) {
this.prefix = prefix;
}
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = super.getMappingForMethod(method, handlerType);
ApiVersion methodAnnotation = AnnotationUtils.findAnnotation(method, ApiVersion.class);
if(methodAnnotation != null) {
RequestCondition<?> methodCondition = getCustomMethodCondition(method);
// Concatenate our ApiVersion with the usual request mapping
if(info != null)
info = createApiVersionInfo(methodAnnotation, methodCondition).combine(info);
} else {
ApiVersion typeAnnotation = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
if(typeAnnotation != null) {
RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
// Concatenate our ApiVersion with the usual request mapping
if(info != null)
info = createApiVersionInfo(typeAnnotation, typeCondition).combine(info);
}
}
return info;
}
private RequestMappingInfo createApiVersionInfo(ApiVersion annotation, RequestCondition<?> customCondition) {
int[] values = annotation.value();
String[] patterns = new String[values.length];
for(int i=0; i<values.length; i++) {
// Build the URL prefix
patterns[i] = prefix+values[i];
}
return new RequestMappingInfo(
new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(), useSuffixPatternMatch(), useTrailingSlashMatch(), getFileExtensions()),
new RequestMethodsRequestCondition(),
new ParamsRequestCondition(),
new HeadersRequestCondition(),
new ConsumesRequestCondition(),
new ProducesRequestCondition(),
customCondition);
}
}
Annotation @ApiVersion akan dibaca valuenya berapa kemudian akan digabungkan dengan value @RequestMapping, sehingga bisa menjadi /v2/person /v1/person saat diload pertama kali oleh Spring. Jika controller tanpa menggunakan annotation akan tetap dibaca /person
3. Buat class WebMvcConfig
@Component
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Bean
@Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return new ApiVersionRequestMappingHandlerMapping("v");
}
}
Semua RequestMapping yang menggunakan ApiVersion otomatis akan diawali dengan ''v''.
4. Hilangkan tag annotation-driven diServletContext.xml, gantikan dengan class WebMvcConfig yang sudah dibuat tadi.
<!--
<annotation-driven />
-->
<beans:bean class="com.andri.sample.version.WebMvcConfig" />
5. Buat controller person
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@RequestMapping(value = "/person", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<String> getPerson(){
String result = "this is rest person api version 1";
return getJsonResponse(result, HttpStatus.OK);
}
@RequestMapping(value = "/person", method = RequestMethod.GET)
@ResponseBody
@ApiVersion(2)
public ResponseEntity<String> getPersonV2(){
String result = "this is rest person api version 2";
return getJsonResponse(result, HttpStatus.OK);
}
public static <T> ResponseEntity<T> getJsonResponse(T src, HttpStatus status) {
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", MediaType.APPLICATION_JSON_VALUE);
return new ResponseEntity<T>(src, headers, status);
}
}
6. Start spring application menggunakan jetty atau tomcat, atau application server lain.
Sekarang coba akses url rest nya : /person dan /v2/person
http://localhost:8080/sample/person
http://localhost:8080/sample/v2/person
referensi : http://stackoverflow.com/questions/20198275/how-to-manage-rest-api-versioning-with-spring
source-code : https://andri_khrisharyadi@bitbucket.org/andri_khrisharyadi/spring-rest-versioning.git
Selamat Mencoba.
No comments:
Post a Comment