2012-03-16 3 views
32

У меня есть простой контроллер, который выглядит следующим образом: -Понимание того, как работает Spring MVC в @RequestMapping POST

@Controller 
@RequestMapping(value = "/groups") 
public class GroupsController { 
    // mapping #1 
    @RequestMapping(method = RequestMethod.GET) 
    public String main(@ModelAttribute GroupForm groupForm, Model model) { 
     ... 
    } 

    // mapping #2 
    @RequestMapping(value = "/{id}", method = RequestMethod.GET) 
    public String changeGroup(@PathVariable Long id, @ModelAttribute GroupForm groupForm, Model model) { 
     ... 
    } 

    // mapping #3 
    @RequestMapping(method = RequestMethod.POST) 
    public String save(@Valid @ModelAttribute GroupForm groupForm, BindingResult bindingResult, Model model) { 
     ... 
    } 
} 

В основном, эта страница имеет следующие функциональные возможности: -

  • пользователь посещает главную страницу (/groups GET).
  • Пользователь создает новую группу (/groups POST) или выбирает определенную группу (/groups/1 GET).
  • Пользователь редактирует существующую группу (/groups/1 POST).

Я понимаю, как оба GET-запроса отображаются здесь. Определяется сопоставление # 2, иначе (/groups/1 GET) приведет к исключению «Без сопоставления».

То, что я пытаюсь понять, вот почему отображение # 3 обрабатывает оба (/groups POST) и (/groups/1 POST)? Имеет смысл, что он должен обрабатывать (/groups POST) здесь, поскольку сопоставление запросов соответствует URI. Почему (/groups/1 POST) не вызывает исключение «Нет сопоставления найденных» здесь? На самом деле, почти похоже, что любой POST с URI, начинающийся с/groups (например: /groups/bla/1 POST), также будет обрабатываться путем сопоставления # 3.

Может кто-нибудь дать мне это ясное объяснение? Большое спасибо.

РАЗЪЯСНЕНИЕ

Я понимаю, тот факт, что я могу использовать более подходящие методы (например, GET, POST, PUT или DELETE) ... или я могу создать еще одно отображение запроса для обработки /groups/{id} POST.

Однако то, что я хочу, чтобы действительно знать ...

.... "Почему отображение # 3 ручки /groups/1 POST тоже?"

«Ближайшие совпадения» рассуждения кажутся недействительными, потому что если я удалю сопоставление # 2, то я думаю, что отображение # 1 будет обрабатывать /groups/1 GET, но это не так, и оно вызывает «Нет сопоставления найдено исключение.

Я просто немного здесь.

+0

Почему бы не использовать PUT для обновления ресурса? Это был бы правильный протокол HTTP. –

+0

Представление в виде веб-формы поддерживает только GET и POST, и я не звоню AJAX здесь, поэтому я не могу полагаться на PUT и DELETE на этом этапе. – limc

+0

@limc, на самом деле это не так, POST могут быть изменены (на стороне сервера) на другой тип запроса с помощью 'org.springframework.web.filter.HiddenHttpMethodFilter' – Ralph

ответ

19

Это сложно, я думаю, что лучше прочитать код.

Весной 3.0 Волшебство выполнено по методу public Method resolveHandlerMethod(HttpServletRequest request) внутреннего класса ServletHandlerMethodResolver из org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.

Экземпляр этого класса существует для каждого класса контроллера запросов и имеет поле handlerMethods, которое содержит список всех методов запроса.

Но позвольте мне подвести итог, как я понимаю

  • пружина сначала проверяет, если по крайней мере один метод обработчика соответствует (это может содержать ложные негативы)
  • Затем он создает карту всех действительно подходящие методов обработчиков
  • Затем он сортирует карту по запросу пути: RequestSpecificMappingInfoComparator
  • и занимает первое один

Сортировка работает следующим образом: RequestSpecificMappingInfoComparator сначала сравнивает путь с помощью AntPathMatcher, если в соответствии с этим два метода равны, тогда другие показатели (например, количество параметров, количество заголовков и т. Д.) Учитываются с помощью в отношении запроса.

+4

Wow ... Я просматриваю 'resolveHandlerMethod (...)', рассказываю о супервысокочастотном коде сложности, я потерялся после n-го вложенных if-операторов. Я прочитал javadoc в 'RequestSpecificMappingInfoComparator', который рассказывает о списке заказов. Мне любопытно, почему они не ведут себя одинаково для методов GET и POST. В другом слове, если я удаляю отображение # 2, почему отображение # 1 не обрабатывает '/ groups/1 GET', но вместо этого Spring выбрасывает исключение ... – limc

+0

@Ralph - хорошее объяснение внутренних элементов – raddykrish

2

Весна пытается найти карту, которая соответствует ближайшим.
Следовательно, в вашем случае любого запроса POST единственной картой, найденной для типа запроса, является Mapping # 3. Ни из сопоставления 1, ни для сопоставления 2 не соответствует типу вашего запроса и, следовательно, игнорируется. Может быть, вы можете попробовать удалить карту # 3 и увидеть, что Spring выдает ошибку времени выполнения, так как не находит соответствия!

+1

Я изначально думал тоже, что весна находит ближайший матч. Однако я понял, что это не совсем так, потому что, если это так, я должен уметь отображать сопоставление # 2, а '/ groups/1 GET' должно обрабатываться путем сопоставления # 1, так как оно является ближайшим совпадением. .. но я получаю исключение «Нет сопоставления найдено» здесь. Я не нашел никакой весенней документации, которая объясняет больше об этой ситуации. – limc

-2

добавить @PathVariable параметру Long ид в отображении # 2

1

Я хотел бы добавить отображение PUT для/групп/{ID}. Я думаю, что POST будет работать, но не строго корректно с точки зрения HTTP.

добавление @RequestMapping ("/ {id}", POST) должно покрывать его?

+0

Как отправить веб-форму с помощью PUT без использования вызовов AJAX? Мне все еще интересно узнать, почему Spring ведет себя так с моей нынешней ситуацией. – limc

+0

Возможно также проверить, как издеваться над PUT с spring.http: //stackoverflow.com/questions/4362791/can-spring-mvc-handle-requests-from-html-forms-other-then-post-and-get –

+0

У вас нет обработчика, определенного для отображения групп/{id}. Я также считаю это ошибкой, потому что мне будет трудно увидеть пример использования для поведения, которое вы видите. –

 Смежные вопросы

  • Нет связанных вопросов^_^