J'ai un simple contrôleur qui ressemble à ceci: -
@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) {
...
}
}
Fondamentalement, cette page a les fonctionnalités suivantes: -
/groups GET
)./groups POST
) Ou sélectionne un groupe spécifique (/groups/1 GET
)./groups/1 POST
).Je comprends comment les deux mappages de requêtes GET fonctionnent ici. Le mappage # 2 est défini, sinon (/groups/1 GET
) Provoquera une exception "Aucun mappage trouvé".
Ce que j'essaie de comprendre ici, c'est pourquoi le mappage # 3 gère à la fois (/groups POST
) Et (/groups/1 POST
)? Il est logique qu'il doive gérer (/groups POST
) Ici car le mappage de requête correspond à l'URI. Pourquoi (/groups/1 POST
) Ne provoque pas une exception "Aucun mappage trouvé" ici? En fait, il semble presque que tout POST avec URI commençant par/groups (ex: /groups/bla/1 POST
) Sera également géré par le mappage # 3.
Quelqu'un peut-il me l'expliquer clairement? Merci beaucoup.
CLARIFICATION
Je comprends le fait que je peux utiliser des méthodes plus appropriées (comme GET, POST, PUT ou DELETE) ... ou je peux créer un autre mappage de demande pour gérer /groups/{id} POST
.
Cependant, ce que je veux vraiment savoir, c'est ...
.... "Pourquoi le mappage # 3 gère-t-il aussi /groups/1 POST
?"
Le raisonnement de la "correspondance la plus proche" ne semble pas vrai, car si je supprime le mappage n ° 2, je pense que le mappage n ° 1 gérera /groups/1 GET
, Mais il ne le fait pas et provoque un "Aucun mappage trouvé "exception.
Je suis juste un peu perplexe ici.
C'est compliqué, je pense qu'il vaut mieux lire le code.
Au printemps 3.0 La magie se fait par la méthode public Method resolveHandlerMethod(HttpServletRequest request)
de la classe interne ServletHandlerMethodResolver
de org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
.
Une instance de cette classe existe pour chaque classe de contrôleur de demande et possède un champ handlerMethods
qui contient une liste de toutes les méthodes de demande.
Mais permettez-moi de résumer comment je le comprends
RequestSpecificMappingInfoComparator
Le tri fonctionne de cette façon: le RequestSpecificMappingInfoComparator
compare d'abord le chemin à l'aide d'un AntPathMatcher
, si deux méthodes sont égales selon cela, alors d'autres métriques (comme le nombre de paramètres, le nombre d'en-têtes , etc.) sont pris en compte pour la demande.
Spring essaie de trouver le mappage qui correspond le plus.
Par conséquent, dans le cas de toute demande POST, la seule carte trouvée pour le type de demande est Mappage n ° 3. Ni le mappage 1 ni le mappage 2 ne correspond à votre type de demande, et sont donc ignorés . Peut-être que vous pouvez essayer de supprimer le mappage # 3 et voir que Spring lance une erreur d'exécution car il ne trouve pas de correspondance!
J'ajouterais un mappage PUT pour/groups/{id}. Je suppose que POST fonctionnerait aussi mais pas strictement correct du point de vue HTTP.
l'ajout de @RequestMapping ("/ {id}", POST) devrait le couvrir?