【问题标题】:Spring 3 Annotated Configuration Picks up @Configuration and @Component but not @ControllerSpring 3 Annotated Configuration 选择 @Configuration 和 @Component 但不是 @Controller
【发布时间】:2011-03-19 18:08:22
【问题描述】:

所以我尝试在没有 XML 的情况下配置我的 Web 应用程序并走所有带注释的路线。我有几个用@Configuration 和@Component 注释的类,它们会被自动拾取,但由于某种原因,我的@Controller 注释没有被识别并映射到它们对应的@RequestMapping 值。

我的 web.xml 文件如下所示:

<?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>

我的主要@Configuration 类如下所示:

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;
    }
}

我的@Controller 和@Component 类都在同一个包下。例如,这是我的应用程序中的一个 @Controller 类:

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...
    }
}

重申一下,我的 @Controller 类没有映射到我指定的 URL。当应用程序在我的本地 tomcat 环境中启动或重新加载时,我看不到通常的“映射 URL”/render”到...”控制台输出。

谁能告诉我我缺少什么可能会阻止我的 @Controller 注释类找不到和注册?

【问题讨论】:

  • 你添加一个基本名称:messageSource.setBasename("/WEB-INF/resources/messages");如何使用 messageSource.setBasenames() 添加多个基本名称?它说的是基本名称数组,但我不确定如何将数组放入参数中。

标签: java spring spring-mvc controller annotations


【解决方案1】:

我猜这是因为@Controllers 应该由DispatcherServlet 从它自己的应用程序上下文中选择(默认情况下从&lt;servletname&gt;-servlet.xml 加载),当你的contextClasscontextConfigLocation 应用于根时上下文(ContextLoaderListener 的上下文,默认从applicationContext.xml 加载)。

要配置DispatcherServlets 应用程序上下文,您应该将contextClasscontextConfigLocation 设置为servlet 的init-params。

编辑: 此行为由DefaultAnnotationHandlerMapping 的属性detectHandlersInAncestorContexts 控制,因此另一种方法是在配置时将其设置为true

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

【讨论】:

  • 我将调度程序 servlet 的 contextClass 和 contextConfigLocation 参数设置为与 webapp 相同的值。一切似乎都很好,但我想现在我有点困惑。现在有两个上下文在运行吗?之前,当我进行所有 XML 配置时,URL 映射会在我启动或重新加载 Web 应用程序时注册。现在,在发出第一个传入请求之前,它们不会被映射。
  • 1) 是的,您有两个应用程序上下文 - 根上下文和 DispatcherServlets context, which is a child of the root one. This is typical for Spring MVC applications, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-servlet. However, it's not a good idea to make them load the annotation-based configuration from the same package - beans would be duplicated. 2) DispatcherServlet's context is initialized when servlet is loaded, so you can control in with `。 3)我添加了替代解决方案。
  • 啊啊啊……我想我现在终于明白了。非常感谢。
【解决方案2】:

我已解决此问题,但将以下代码添加到我的 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>

但是这样做我会告诉它在哪里寻找我的控制器

【讨论】:

    【解决方案3】:

    将此添加到您的 mvc 调度程序 servlet xml 文件中,该包应该是所有控制器的包,以便扫描 @controller 或 @Component。

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

    【讨论】:

    • 他特别说他想要 xml-less 配置
    猜你喜欢
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    • 2021-08-19
    • 1970-01-01
    • 2011-10-04
    • 2021-01-18
    • 1970-01-01
    相关资源
    最近更新 更多