2010-07-22 3 views
7

Also versuche ich, meine Web-App ohne XML zu konfigurieren und die alle kommentierte Route zu gehen. Ich habe einige Klassen mit @Configuration und @Component versehen, die automatisch aufgenommen werden, aber aus irgendeinem Grund werden meine @Controller-Annotationen nicht erkannt und ihren entsprechenden @RequestMapping-Werten zugeordnet.Spring 3 Annotated Configuration Ruft @Configuration und @Component, aber nicht @Controller auf

Meine web.xml-Datei sieht so aus:

<?xml version="1.0" encoding="UTF-8"?> 
<web-app id="com-timbuk2-webapp-compositor" 
     version="3.0" 
     xmlns="http://java.sun.com/xml/ns/javaee" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" > 

    <display-name>timbuk2-webapp-Compositor</display-name> 

    <!-- Context Parameters --> 
    <context-param> 
     <param-name>log4jConfigLocation</param-name> 
     <param-value>/WEB-INF/conf/log4j-config.xml</param-value> 
    </context-param> 

    <context-param> 
     <param-name>contextClass</param-name> 
     <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> 
    </context-param> 

    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>com.company.webapp</param-value> 
    </context-param> 

    <!-- Listeners --> 
    <listener> 
     <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> 
    </listener> 

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

    <!-- Filters --> 
    <filter> 
     <filter-name>characterEncodingFilter</filter-name> 
     <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 
     <init-param> 
      <param-name>encoding</param-name> 
      <param-value>UTF-8</param-value> 
     </init-param> 
     <init-param> 
      <param-name>forceEncoding</param-name> 
      <param-value>true</param-value> 
     </init-param> 
    </filter> 

    <filter> 
     <filter-name>urlRewriteFilter</filter-name> 
     <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class> 
     <init-param> 
      <param-name>logLevel</param-name> 
      <param-value>commons</param-value> 
     </init-param> 
     <init-param> 
      <param-name>confPath</param-name> 
      <param-value>/WEB-INF/conf/urlrewrite-config.xml</param-value> 
     </init-param> 
    </filter> 

    <!-- Filter Mappings --> 
    <filter-mapping> 
     <filter-name>characterEncodingFilter</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

    <filter-mapping> 
     <filter-name>urlRewriteFilter</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

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

    <!-- Servlet mappings --> 
    <servlet-mapping> 
     <servlet-name>dispatcher</servlet-name> 
     <url-pattern>/app/*</url-pattern> 
    </servlet-mapping> 


</web-app> 

Meine Haupt @Configuration Klasse sieht so aus:

package com.company.webapp.config; 

import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.support.ReloadableResourceBundleMessageSource; 
import org.springframework.web.servlet.view.InternalResourceViewResolver; 
import org.springframework.web.servlet.view.JstlView; 

@Configuration 
public class ApplicationConfiguration 
{  
    @Bean 
    public ReloadableResourceBundleMessageSource messageSource() 
    { 
     ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); 
     messageSource.setBasename("/WEB-INF/resources/messages"); 
     messageSource.setCacheSeconds(0); 
     return messageSource; 
    } 

    @Bean 
    public InternalResourceViewResolver viewResolver() 
    { 
     InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); 
     viewResolver.setViewClass(JstlView.class); 
     viewResolver.setPrefix("/WEB-INF/views/"); 
     viewResolver.setSuffix(".jsp"); 
     return viewResolver; 
    } 
} 

Meine @Controller und @Component Klassen alle unter dem gleichen Paket leben. Zum Beispiel, hier ist eine @Controller Klasse von meiner App:

package com.company.webapp.controller; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.stereotype.Controller; 
import org.springframework.validation.BindingResult; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.servlet.ModelAndView; 

@Controller 
@RequestMapping(value = "/render") 
public class RenderController 
{ 
    private final Logger logger = LoggerFactory.getLogger(getClass()); 

    @RequestMapping(method = RequestMethod.GET) 
    public ModelAndView handleGet(BindingResult bindingResult) 
    { 
     ... eventually return a ModelAndView object... 
    } 
} 

So zu wiederholen, meine @Controller Klassen nicht auf die URLs abgebildet wird, ich angeben. Wenn die App in meiner lokalen Tomcat-Umgebung gestartet oder neu geladen wird, sehe ich nicht die übliche "Mapped URL"/render "to ..." Konsolenausgabe.

Kann mir jemand sagen, was ich vermisse, was verhindern könnte, dass meine mit @Controller annotierten Klassen nicht gefunden und registriert werden?

+0

Sie eine einzelne Basisname hinzufügen: messageSource.setBasename ("/ WEB-INF/resources/messages"); Wie man mehrere Basisnamen mit messageSource.setBasesnames() hinzufügt? Es sagt Array von Basisnamen, aber ich bin mir nicht sicher, wie man ein Array in param setzt. – Rihards

Antwort

5

Ich denke, dies geschieht, weil @Controller s durch DispatcherServlet aus dem eigenen Anwendungskontext (die von <servletname>-servlet.xml standardmäßig geladen wird) abgeholt werden soll, wenn Ihre contextClass und contextConfigLocation an den Root-Kontext angewandt werden (die ContextLoaderListener ‚einem s, die wird standardmäßig von applicationContext.xml geladen).

DispatcherServlet s Anwendungskontext zu konfigurieren, Sie contextClass und contextConfigLocation als die des Servlets init-param s setzen soll.

EDIT: Dieses Verhalten wird von der Unterkunft detectHandlersInAncestorContexts von DefaultAnnotationHandlerMapping gesteuert wird, so dass der alternative Ansatz ist es true bei der Konfiguration einstellen:

@Bean 
public DefaultAnnotationHandlerMapping mapping() { 
    DefaultAnnotationHandlerMapping m = new DefaultAnnotationHandlerMapping(); 
    m.setDetectHandlersInAncestorContexts(true); 
    return m; 
} 
+0

Ich habe die contextClass- und contextConfigLocation-Parameter des Dispatcher-Servlets auf dieselben Werte wie die Webanwendung gesetzt. Alles scheint gut, ich denke jetzt bin ich ein wenig verwirrt. Laufen jetzt zwei Kontexte? Vorher, als ich die gesamte XML-Konfiguration durchführte, wurden die URL-Mappings registriert, wenn ich die Web-App starten oder neu laden würde. Jetzt werden sie erst zugeordnet, wenn die erste eingehende Anforderung erfolgt ist. –

+0

1) Ja, Sie haben zwei Anwendungskontext - den Stammkontext und den DispatcherServlet-Kontext, der ein Kind des Stammkontextes ist. Dies ist typisch für Spring MVC-Anwendungen, siehe http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-servlet. Es ist jedoch keine gute Idee, sie die Annotation-basierte Konfiguration aus dem gleichen Paket zu laden - Bohnen würden dupliziert werden. 2) Der DispatcherServlet-Kontext wird initialisiert, wenn das Servlet geladen wird, so dass Sie mit '' steuern können. 3) Ich habe die alternative Lösung hinzugefügt. – axtavt

+0

Ahhhh ... Ich denke ich verstehe es jetzt endlich. Danke vielmals. –

1

Fügen Sie diese in Ihrer mvc Dispatcher Servlet XML-Datei, in Das Paket sollte für alle Controller sein, die nach @controller oder @Component gescannt werden sollen.

<context:component-scan 
     base-package="packagesseperatedbycomma" /> 
+0

er sagte ausdrücklich, er will Xml-less-Konfiguration – Levancho

1

ich dieses Problem behoben, aber das Hinzufügen des folgenden Code zu meinem web.xml:

<servlet> 
     <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
     <init-param> 
      <param-name>contextClass</param-name> 
      <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> 
     </init-param> 
     <init-param> 
      <param-name>contextConfigLocation</param-name> 
      <param-value>org.xxxx.inquiry.config, org.xxxx.inquiry.controller</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

Aber dies zu tun ich ihm sagen, wo meinem Controller suchen