Я шукав, як керувати версіями REST API, використовуючи Spring 3.2.x, але не знайшов нічого, що було б просто в обслуговуванні. Я поясню спершу проблему, яку я маю, а потім вирішення ... але мені цікаво, чи я не буду винаходити колесо тут.
Я хочу керувати версією на основі заголовка Accept, і, наприклад, якщо запит має заголовок Accept application/vnd.company.app-1.1+json
, я хочу, щоб весняний MVC пересилав це методу, який обробляє цю версію. А оскільки не всі методи в API змінюються в одному випуску, я не хочу переходити до кожного свого контролера і нічого не змінювати для обробника, який не змінився між версіями. Я також не хочу мати логіку, щоб визначити, яку версію використовувати в самому контролері (використовуючи сервісні локатори), оскільки Spring вже виявляє, який метод викликати.
Отже, взявши API з версіями 1.0, до 1.8, де обробник був представлений у версії 1.0 та модифікований у v1.7, я хотів би обробити це наступним чином. Уявіть, що код знаходиться в контролері, і що існує якийсь код, який може витягнути версію з заголовка. (Навесні недійсні навесні)
@RequestMapping(...)
@VersionRange(1.0,1.6)
@ResponseBody
public Object method1() {
// so something
return object;
}
@RequestMapping(...) //same Request mapping annotation
@VersionRange(1.7)
@ResponseBody
public Object method2() {
// so something
return object;
}
Це неможливо навесні, оскільки два способи мають однакову RequestMapping
анотацію, і Spring не вдається завантажити. Ідея полягає в тому, що в VersionRange
анотації можна визначити відкритий або закритий діапазон версій. Перший метод діє від версій 1.0 до 1.6, а другий для версії 1.7 і далі (включаючи останню версію 1.8). Я знаю, що такий підхід порушується, якщо хтось вирішить передати версію 99,99, але це те, з чим я в нормі жити.
Тепер, оскільки вищезазначене неможливо без серйозної переробки того, як працює весна, я думав подумати про те, як обробники відповідатимуть запитам, зокрема написати власний ProducesRequestCondition
, і мати діапазон версій там. Наприклад
Код:
@RequestMapping(..., produces = "application/vnd.company.app-[1.0-1.6]+json)
@ResponseBody
public Object method1() {
// so something
return object;
}
@RequestMapping(..., produces = "application/vnd.company.app-[1.7-]+json)
@ResponseBody
public Object method2() {
// so something
return object;
}
Таким чином, я можу мати закриті або відкриті діапазони версій, визначені в частині продукту примітки. Я працюю над цим рішенням зараз, з цією проблемою , що я все ще повинен був замінити деякі класи ядра Spring MVC ( RequestMappingInfoHandlerMapping
, RequestMappingHandlerMapping
і RequestMappingInfo
), що мені не подобається, тому що це означає додаткову роботу , коли я вирішив перейти на новішу версію весна.
Буду вдячний за будь-які думки ... і, особливо, будь-яку пропозицію зробити це більш простим, легшим у обслуговуванні способом.
Редагувати
Додавання щедрості. Щоб отримати винагороду, будь ласка, дайте відповідь на вищезазначене питання, не пропонуючи мати цю логіку в контролері. У Spring вже є багато логіки, щоб вибрати метод контролера, який потрібно викликати, і я хочу зробити це.
Редагувати 2
Я поділився оригінальним POC (з деякими вдосконаленнями) в github: https://github.com/augusto/restVersioning
produces={"application/json-1.0", "application/json-1.1"}
тощо