2013-03-13 3 views
1

Я работаю над весенними API-интерфейсами REST. В требованиях есть 2 запроса POST с одинаковым URL-адресом, но с другим телом запроса. Поскольку Spring MVC должен иметь уникальные сопоставления между контроллерами, я должен предварительно обработать тело запроса для сопоставления с определенным POJO.Корпус запроса предварительного запроса Spring MVC

На основе session_type в теле запроса я должен сопоставить запрос с конкретным POJO (JSON -> JAVA POJO).

Например, если «session_type» в теле запроса «typeX», то запрос должен отображаться в ClassX POJO. Если «session_type» в теле запроса «typeY», то запрос должен отображаться в ClassY POJO.

Если есть способ сделать это, используя аннотацию какого-либо запроса?

+1

Почему вы не изменяете свои URI на '/ context/resources/typex' и'/context/resources/typey'? –

+0

Требование о том, что URL-адреса должны быть одинаковыми, поскольку существует разница только в SessionType. –

+0

Вы получите лучший ответ, если вы объясните, что означает «тип сеанса». –

ответ

4

Если вы хотите связать typeX и typeY, то вам обязательно нужно 2 обработчика. Но, почему бы не мы используем param вариант @RequestMapping:

@RequestMapping(method = RequestMethod.POST, 
     value = "/url", params = "session_type=typeX") 
public String handleTypeX(@RequestBody @ModelAttribute TypeX typeX){ 
    //TODO implement 
} 

@RequestMapping(method = RequestMethod.POST, 
     value = "/url", params = "session_type=typeY") 
public String handleTypeY(@RequestBody @ModelAttribute TypeY typeY){ 
    //TODO implement 
} 

Если вам нужны какие-то препараты (ФЭ нормализовать Params или выполнить модель связывания вручную), то подход выше, вы можете комбинировать вместе с @InitBinder, но обратите внимание, , что @InitBinder нуждается в точных правилах ULR вместе с параметрами @ModelAttribute в обработчиках.

РЕДАКТИРОВАТЬ: В Spring MVC нет никакой возможности использовать 2 обработчик для точного URL, то есть когда метод/URL/PARAMS/потребляет типа являются одинаковыми.

Таким образом, я предлагаю использовать унифицированный обработчик, в котором вы должны проверить необходимый параметр, а затем вручную преобразовать в соответствующий класс. Для нахождения необходимого класса я полагаю, было бы лучше использовать Strategy pattern:

//class resolver according "session_type" parameter 
//note, that you can use Spring autowiring capabilities 
private final Map<String, Class> TYPES_CONTEXT = new HashMap<String, Class>(){ 
    { 
     this.put("x", TypeX.class); 
     this.put("y", TypeY.class); 
     //TODO probably other classes 
    } 
} 


@RequestMapping(method = RequestMethod.POST, 
     value = "/url") 
public @ResponseBody String handleAnyType(@RequestBody Map<String, String> body){ 
    String sessionType = body.get("session_type"); 

    //TODO handle case if sessionType is NULL 

    Class convertedClass = TYPES_CONTEXT.get(sessionType); 

    //TODO handle case if class is not found 

    Object actualObject = objectMapper.convertValue(body, convertedClass); 

    //now we use reflection for actual handlers, but you may refactor this in the way you want, f.e. again with Strategy pattern 
    //note that current approach there should be contract for methods names 
    Method actualHandler = this.getClass().getMethod("handle" + actualObject.getClass().getSimpleName()); 

    return (String)actualHandler.invoke(this, actualObject); 
} 

public String handleTypeX(TypeX typeX){ 
    //TODO implement 
} 

public String handleTypeY(TypeY typeY){ 
    //TODO implement 
} 

//TODO probably other methods 

Этот подход не обрабатывает проверки и некоторые вещи, которые были опущены, но я считаю, что это может быть полезным.

+0

Я мог бы использовать параметр param, если этот тип был передан как параметр в URL for.eg. POST/v1/sessions? SessionType = TypeX. Но, к сожалению, в моем случае sessionType передается в тело запроса. Напр. вот мой запрос тело: { "session_type": "typeX", "first_name": "а", .... и т.д ... } Просто на "session_type" Я должен решить запрос-тело для сопоставления POJO. –

+0

@RP Пожалуйста, найдите обновленный ответ. – n1ckolas

+0

Большое спасибо ... Это кажется лучшим решением для меня. Ценю вашу помощь! –

0

Я думаю, что вы должны создать контроллер с одним методом для обоих типов и вызвать требуемый компонент \ метод в нем в зависимости от typeX или typeY.

+0

Это означает, что изменение URL и имеющим конкретный URL для конкретной сессии тип. Это НЕ требование. В нем говорится, что я должен создать объекты сеанса для клиента на основе SESSION_TYPE, переданного в REQUEST BODY. Поэтому я вроде (не совсем) нуждаюсь в перехватчике, прежде чем перенаправлять входящий запрос на конкретный POJO. В зависимости от поля session_type в теле запроса (JSON) мне придется сопоставить его с определенным POJO. –

0

У GET не должно быть органов запроса или, по крайней мере, если они это делают, the server side isn't required to do anything with them. Как вы описали, этот API не RESTful.

Предполагая, что вы не заботитесь о том, что, попробуйте создать метод контроллера, который принимает родительский класс TypeX и -типа, или интерфейса, как TypeX и -типа осуществления, аннотировать его с @SomethingMeaningfulToYou, а затем использовать web argument method resolver для конкретизации класс ребенка, который вы хотите.

Это взломанный сломанный API.

+0

Извини, мой плохой. Фактически это запрос POST. Я редактировал вопрос. –

+0

А, ок. Если это произойдет через JSON, сделайте метод принимающим параметр родительского класса, а затем каким-то образом сконфигурируйте Jackman ObjectMapper, используемый MappingJacksonHttpMessageConverter, чтобы различать в зависимости от типа sessionType. Взгляните на http://wiki.fasterxml.com/JacksonPolymorphicDeserialization для получения более подробной информации. –

+0

И если это работает, напишите подробности как ответ, чтобы люди могли ссылаться на него в будущем. –

0

есть 2 POST запросов с таким же URL, но другого телом

запроса За RESTful интерфейса, тот же URL должен всегда указывать один и тот же ресурс . Тело запроса может содержать различные изображения этого ресурса. Вы можете создать различные классы HttpMessageContverter для двух разных видов представления.