Spring 3 带注释的配置选择@Configuration和@Component,但不选择@Controller

发布于 2024-09-10 16:24:45 字数 5870 浏览 5 评论 0原文

因此,我尝试在没有 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 带注释的类不被找到和注册?

So I'm trying to configure my web app without XML and go the all annotated route. I have a few classes annotated with @Configuration and @Component that are getting picked up automatically, but for some reason my @Controller annotations aren't being recognized and mapped to their corresponding @RequestMapping values.

My web.xml file looks like so:

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

My main @Configuration class looks like so:

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

My @Controller and @Component classes all live under the same package. For instance, here's a @Controller class from my 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 to reiterate, my @Controller classes aren't being mapped to the URLs I'm specifying. When the app starts up or reloads in my local tomcat environment I'm not seeing the usual "Mapped URL "/render" to..." console output.

Can anyone tell me what I'm missing that might prevent my @Controller annotated classes not to be found and registered?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

ゝ偶尔ゞ 2024-09-17 16:24:45

我猜发生这种情况是因为 @Controller 应该由 DispatcherServlet 从它自己的应用程序上下文中选取(从 -servlet.xml 加载) code> 默认情况下),当您的 contextClasscontextConfigLocation 应用于根上下文(ContextLoaderListener 的,它从 <默认情况下为代码>applicationContext.xml)。

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

编辑:
此行为由 DefaultAnnotationHandlerMapping 的属性 detectHandlersInAncestorContexts 控制,因此替代方法是在配置期间将其设置为 true

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

I guess this happens because @Controllers should be picked by DispatcherServlet from its own application context (which is loaded from <servletname>-servlet.xml by default), when your contextClass and contextConfigLocation are applied to the root context (the ContextLoaderListener's one, which is loaded from applicationContext.xml by default).

To configure DispatcherServlets application context, you should set contextClass and contextConfigLocation as the servlet's init-params.

EDIT:
This behaviour is controlled by the property detectHandlersInAncestorContexts of DefaultAnnotationHandlerMapping, so the alternative approach is to set it to true during configuration:

@Bean
public DefaultAnnotationHandlerMapping mapping() {
    DefaultAnnotationHandlerMapping m = new DefaultAnnotationHandlerMapping();
    m.setDetectHandlersInAncestorContexts(true);
    return m;
}
离去的眼神 2024-09-17 16:24:45

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

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

I fixed this issue but adding the following code to my 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>

But doing this I tell it where to look for my controllers

爱的那么颓废 2024-09-17 16:24:45

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

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

Add this in your mvc dispatcher servlet xml file where the package should be for all the controllers to be scanned for @controller or @Component.

<context:component-scan
        base-package="packagesseperatedbycomma" />
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文