web-dev-qa-db-fra.com

Spring MVC: différence entre les balises <context: scanning-composant> et <indexées />?

Il y a quelques jours, j'ai commencé à étudier ce tutoriel Spring Hello World: http://viralpatel.net/blogs/spring-3-mvc-create-hello-world-application-spring-3-mvc/

Dans ce tutoriel, Spring DispatcherServlet est configuré à l'aide du fichier spring-servlet.xml, celui-ci:

<?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package="net.viralpatel.spring3.controller" />

<bean id="viewResolver"
    class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass"
        value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>

Dans ce fichier, j'utilise la balise contextuelle : composant-scan pour indiquer que Spring doit analyser mon fichier en recherchant l'annotation. Ainsi, par exemple, lorsque la classe du contrôleur détecte qu'une méthode est annoté par @ RequestMapping ("/ hello") L'annotation sait que cette méthode gère la requête HTTP vers l'URL se terminant par "/ hello". C'est simple ...

Maintenant, mon doute est lié au projet de modèle Spring MVC que je pourrais construire automatiquement dans STS\Eclipse.

Lorsque je crée un nouveau projet Spring MVC dans STS, mon DispatcherServlet est configuré par un fichier nommé servlet-context.xml qui en contient configuration similaire à l'exemple de fichier précédent.

Dans ce fichier, j'ai toujours la balise d'analyse du composant:

<context:component-scan base-package="com.mycompany.maventestwebapp" />

mais j'ai aussi une autre balise (qui ressemble à une tâche similaire), celle-ci:

<annotation-driven />

Quelle est la différence entre ces deux balises?
Une autre chose "étrange" est que l'exemple précédent (qui n'utilise pas la balise pilotée par une annotation) est très similaire au projet créé par STS à l'aide du projet de modèle Spring MVC, mais si je supprime l'annotation- balise pilotée à partir de son fichier de configuration, le projet ne s'exécute pas et me donne l'erreur suivante: Statut HTTP 404 -

Et dans le stacktrace j'ai:

WARN: org.springframework.web.servlet.PageNotFound - Aucun mappage trouvé pour la requête HTTP avec l'URI [/ maventestwebapp /] dans DispatcherServlet avec le nom 'appServlet'

Mais pourquoi? L'exemple précédent fonctionne bien sans balise pilotée par annotation, et cette classe de contrôleur est très similaire. En fait, il n’existe qu’une méthode qui gère la requête HTTP vers le chemin "/"

C'est le code de ma classe de contrôleur:

package com.mycompany.maventestwebapp;

import Java.text.DateFormat;
import Java.util.Date;
import Java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
*/
@Controller
public class HomeController {

private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

/**
 * Simply selects the home view to render by returning its name.
 */
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
    logger.info("Welcome home! The client locale is {}.", locale);

    Date date = new Date();
    DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

    String formattedDate = dateFormat.format(date);

    model.addAttribute("serverTime", formattedDate );

    return "home";
}

Est-ce que quelqu'un peut m'aider à comprendre cette chose?

Merci beaucoup!

64
AndreaNobili

<mvc:annotation-driven /> signifie que vous pouvez définir des dépendances Spring beans sans avoir à spécifier un groupe d’éléments dans XML, à implémenter une interface ou à étendre une classe de base. Par exemple @Repository _ dire au printemps qu'une classe est un Dao sans avoir à étendre JpaDaoSupport ou une autre sous-classe de DaoSupport. De même @Controller indique à Spring que la classe spécifiée contient des méthodes qui gèrent les requêtes HTTP sans que vous ayez à implémenter l'interface Controller ni à étendre une sous-classe implémentant le contrôleur.

Lorsque spring démarre, il lit son fichier de configuration XML et cherche <bean éléments qu’il contient s’il voit quelque chose comme <bean class="com.example.Foo" /> et Foo a été marqué avec @Controller _ il sait que la classe est un contrôleur et la traite comme telle. Par défaut, Spring suppose que toutes les classes qu'il doit gérer sont explicitement définies dans le fichier beans.XML.

Analyse de composant avec <context:component-scan base-package="com.mycompany.maventestwebapp" /> indique à spring qu'il doit rechercher dans le chemin de classe toutes les classes de com.mycompany.maventestweapp et examiner chaque classe pour voir si elle a un @Controller, ou @Repository, ou @Service, ou @Component et si c'est le cas, Spring enregistre la classe avec la fabrique de haricots comme si vous aviez tapé <bean class="..." /> dans les fichiers de configuration XML.

Dans une application MVC printanière typique, vous constaterez qu'il existe deux fichiers de configuration Spring, un fichier qui configure le contexte de l'application démarré généralement avec l'écouteur de contexte Spring.

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Et un fichier de configuration Spring MVC généralement démarré avec le servlet Spring Dispatcher. Par exemple.

<servlet>
        <servlet-name>main</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>main</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

Spring prend en charge les usines de beans hiérarchiques. Ainsi, dans le cas de Spring MVC, le contexte de servlet de répartiteur est un enfant du contexte d'application principal. Si le contexte de servlet a été demandé pour un bean appelé "abc", il recherchera d'abord dans le contexte de servlet. S'il ne le trouve pas, il recherchera dans le contexte parent, qui est le contexte d'application.

Les beans communs tels que les sources de données, la configuration JPA, les services métier sont définis dans le contexte de l'application, tandis que la configuration spécifique à MVC n'entre pas dans le fichier de configuration associé au servlet.

J'espère que cela t'aides.

83
ams
<context:component-scan base-package="" /> 

indique à Spring d'analyser ces packages à la recherche d'annotations.

<mvc:annotation-driven> 

inscrit un RequestMappingHanderMapping, un RequestMappingHandlerAdapter et un ExceptionHandlerExceptionResolver pour prendre en charge les méthodes de contrôleur annotées telles que @RequestMapping, @ExceptionHandler, etc. fournies avec MVC.

Cela active également un service de conversion prenant en charge le formatage des sorties piloté par les annotations ainsi que la validation des entrées pilotée par les annotations. Il active également la prise en charge de @ResponseBody que vous pouvez utiliser pour renvoyer des données JSON.

Vous pouvez accomplir les mêmes choses en utilisant une configuration basée sur Java en utilisant @ComponentScan (basePackages = {"...",} et @EnableWebMvc dans une classe @Configuration.

Consultez la documentation 3.1 pour en savoir plus.

http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-config

26
Dennis S

Annotation-driven indique à Spring qu'il doit rechercher les beans annotés et ne pas se fier uniquement à la configuration de bean XML. Component-scan indique où chercher ces haricots.

Voici quelques doc: http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-config-enable

12
atrain