applicationContext ne trouve pas de contrôleurs pour le contexte de Servlet

J'ai une application Web Spring avec un applicationContext.xml et un répartiteur-servlet.de configuration xml. J'ai défini le <context:component-scan /> dans applicationContext.xml, mais quand j'exécute mon application, les contrôleurs ne sont pas trouvés sauf si j'ajoute également <context:component-scan /> au dispatcher-servlet.XML. J'utilise le même paquet de base dans les deux, donc ce n'est pas le problème.

Je suis confus, parce que je pensais {[14] } que l'applicationContext.xml était un parent de dispatcher-servlet.XML. Je ne mettrais pas <context:component-scan /> dans applicationContext.xml suffit-il?

Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>

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

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

</web-app>

EDIT: j'utilise également mvc: annotation-driven dans le dispatcher-servlet.xml, qui est censé ramasser les Contrôleurs (je pensais?).

EDIT 2: Voici les fichiers de configuration. J'ai supprimé un tas de paramètres Spring Security et OAuth de applicationContext.xml (pour des raisons de sécurité et étant qu'ils ne sont probablement pas pertinents de toute façon).

ApplicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
      http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
      http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

<context:component-scan base-package="bar.foo"/>
<context:property-placeholder location="classpath:my.properties" />
<bean class="bar.foo.ServicesConfig" />

</beans>

Répartiteur-servlet.xml

<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:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
      http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

<context:component-scan base-package="bar.foo.controller" />
<mvc:annotation-driven/>
<mvc:default-servlet-handler />

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

<bean id="contentViewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json" />
        </map>
    </property>
    <property name="defaultViews">
        <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
    </property>
    <property name="order" value="1" />
</bean>

</beans>

EDIT 3: OK, c'est intéressant. Mes services et les classes dao sont dans un projet différent (JAR) que je référence du projet web. J'utilise la configuration basée sur java et le référencer à partir de applicationContext.xml:

<bean class="bar.foo.config.ServicesConfig" />

Donc, cela signifie qu'il n'y a que des annotations de contrôleur dans mon projet web (où applicationContext.xml est situé). Rétrospectivement, enlever contexte: component-scan à partir de mon applicationContext.xml ne devrait pas avoir d'effet, car il n'y a pas d'annotations à l'exception de celles de @Controller (correction à modifier: il y a des annotations @Autowired). Mais, quand je supprime le contexte: component-scan de applicationContext.xml, il dit que les contrôleurs (trouvés à partir de dispatcher servlet scan) ne peuvent pas trouver mes classes de Service. La référence à ServicesConfig ne devrait-elle pas suffire? Voici la classe ServicesConfig pour les références-elle a sa propre analyse des composants pour les Services, qui sont un paquet différent de ce que l'applicationContext.xml a été la numérisation.

@Configuration
@ComponentScan({ "some.other.package", "another.package" })
@ImportResource({ "classpath:commonBeans.xml" })
@PropertySource({ "classpath:services.properties",
"classpath:misc.properties" })
public class ServicesConfig {
  // Bean definitions //
}

SOLUTION:

Lorsque j'ai supprimé context: component-scan de mon contexte racine, les contrôleurs ne récupéraient pas les beans de services autowired. C'est parce que le contexte racine fait référence à mon Bean de configuration basé sur java des services, mais je n'avais pas la configuration du contexte racine pour rechercher les composants. Par conséquent, lorsque j'ajoute l'analyse des composants au contexte racine (applicationContext.xml) tout fonctionne. Voici ce que j'ai maintenant:

ApplicationContext.xml:

<bean class="bar.foo.config.ServicesConfig" />
<context:component-scan base-package="bar.foo.config" />

Répartiteur-servlet.xml:

<context:component-scan base-package="bar.foo.controller" />

J'ai la configuration du contexte web pour pickup Controller, Autowired et toutes les autres annotations dans le package controller - Je ne suis pas sûr que ce soit la meilleure pratique ou non.

21
demandé sur acvcu 2012-07-12 18:01:32

3 réponses

Vous avez raison-il y a deux contextes d'application différents, le contexte d'application racine chargé par ContextLoaderListener (au moment où le ServletContext est initialisé), et le contexte Web (chargé par DispatcherServlet), le contexte d'application racine est le parent du contexte Web.

Maintenant, puisque ce sont deux contextes d'application différents, ils sont agis différemment - si vous définissez component-scan pour vos services dans le contexte de l'application, alors tous les beans pour le les services sont créés ici.

Lorsque votre servlet Dispatcher se charge, il commencera à créer le contexte Web, à un moment donné (piloté par <mvc:annotation-driven/> il créera un mappage pour les méthodes de votre uri vers le Gestionnaire, il obtiendra la liste des beans dans le contexte de l'application (qui sera le contexte de l'application web, pas le contexte de l'application racine) et puisque vous doivent également définir une analyse de composant dans le contexte des servlets du répartiteur.

Une bonne pratique consiste à exclure les beans liés au contrôleur dans le contexte de L'Application racine:

<context:component-scan base-package="package">
    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>

Et seul le contrôleur est lié au contexte de L'Application Web:

<context:component-scan base-package="package" use-default-filters="false">
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation" />
</context:component-scan>
33
répondu Biju Kunjummen 2012-07-13 13:34:39

Dans nos applications, nous définissons dans le répartiteur de servlet.xml

Je crois que c'est là qu'il est censé être plutôt que dans applicationContext.xml

Cette section de la documentation de printemps devrait fournir plus d'informations:

Http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html

Comme vous pouvez le voir sur l'un des diagrammes de la section 16.2, le dispatcher-servlet se trouve au-dessus de applicationContext dans le hiérarchie de contexte.

1
répondu James Thomas 2012-07-12 14:23:57

J'ai eu le même problème et après avoir comparé mon code web.xml avec ce tutoriel Je l'ai changé et cela a fonctionné. voici mon fichier web.xml:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:mvc="http://www.springframework.org/schema/mvc"
     xsi:schemaLocation="
    http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
     version="3.0">
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/business-config.xml</param-value>
</context-param>

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

<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

context-param et listener étaient ce que j'ai manqué.

J'espère que ça vous aidera.

0
répondu Seyed Jalal Hosseini 2015-10-30 05:55:51