应用程序启动时,Spring MVC RequestMappingHandlerMapping会发生两次

时间:2015-10-22 22:40:14

标签: java spring spring-mvc

我最近将我的Spring 4 MVC Web应用程序从XML配置转换为基于java的配置。执行此操作后,所有控制器都会映射两次。我觉得它与组件扫描有关,但我无法弄清楚原因。我可以发布旧的XML配置设置,如果这将有所帮助。应用程序运行正常,它只是在日志中打印两次控制器映射。

这里将它们加载到根上下文

...
INFO  RequestMappingHandlerMapping - Mapped "{[/user/changePassword],methods=[POST]}" onto public org.springframework.web.servlet.ModelAndView com.rapidtest.mvc.controller.UserController.changePasswordSubmit(com.rapidtest.mvc.form.user.ChangePasswordFormBean,org.springframework.validation.BindingResult) throws java.lang.Exception
INFO  SimpleUrlHandlerMapping - Mapped URL path [/pub/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
INFO  SimpleUrlHandlerMapping - Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler]
INFO  RequestMappingHandlerAdapter - Looking for @ControllerAdvice: Root WebApplicationContext: startup date [Thu Oct 22 16:16:24 MDT 2015]; root of context hierarchy

这里它们也被加载到消息调度程序上下文

...
INFO  RequestMappingHandlerMapping - Mapped "{[/user/changePassword],methods=[POST]}" onto public org.springframework.web.servlet.ModelAndView com.rapidtest.mvc.controller.UserController.changePasswordSubmit(com.rapidtest.mvc.form.user.ChangePasswordFormBean,org.springframework.validation.BindingResult) throws java.lang.Exception
INFO  SimpleUrlHandlerMapping - Mapped URL path [/pub/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
INFO  SimpleUrlHandlerMapping - Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler]
INFO  RequestMappingHandlerAdapter - Looking for @ControllerAdvice: WebApplicationContext for namespace 'website-servlet': startup date [Thu Oct 22 16:16:28 MDT 2015]; parent: Root WebApplicationContext

这是我的web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">

    <servlet>
        <servlet-name>website</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>com.rapidtest.config.mvc.MVCConfig</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

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

    <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.rapidtest.config.spring</param-value>
    </context-param>
    <context-param>
        <param-name>contextInitializerClasses</param-name>
        <param-value>com.rapidtest.util.properties.ArchaiusPropertyInitializer</param-value>
    </context-param>

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

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>

    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>com.rapidtest.web.filter.EncodingFilter</filter-class>
    </filter>

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

    <welcome-file-list>
        <welcome-file>/index.jsp</welcome-file>
    </welcome-file-list>

    <error-page>
        <error-code>404</error-code>
        <location>/error/404</location>
    </error-page>

    <error-page>
        <location>/error/general</location>
    </error-page>

</web-app>

这是我的java MVC配置

package com.rapidtest.config.mvc;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
@ComponentScan("com.rapidtest.mvc.controller")
public class MVCConfig extends WebMvcConfigurationSupport {

    // <mvc:resources mapping="/pub/**" location="/pub/" />
    @Override
    public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/pub/**").addResourceLocations("/pub/");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    //  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    //      <property name="prefix">
    //          <value>/WEB-INF/jsp/</value>
    //      </property>
    //      <property name="suffix">
    //          <value>.jsp</value>
    //      </property>
    //  </bean>
    @Bean
    public ViewResolver configureViewResolver() {
        InternalResourceViewResolver viewResolve = new InternalResourceViewResolver();
        viewResolve.setPrefix("/WEB-INF/jsp/");
        viewResolve.setSuffix(".jsp");

        return viewResolve;
    }

    // <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
    @Bean(name = "multipartResolver")
    public CommonsMultipartResolver getMultipartResolver() {
        return new CommonsMultipartResolver();
    }

}

这是我的RootConfig。我所有的其他@Configuration类都在同一个包中。

package com.rapidtest.config.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;

import com.rapidtest.util.properties.ArchaiusPropertyPlaceholderConfigurer;

@Configuration
//@ComponentScan(basePackages = {"com.rapidtest"}, useDefaultFilters=false, excludeFilters={
//        @ComponentScan.Filter(type=FilterType.ANNOTATION, value={Controller.class, ControllerAdvice.class})})
@ComponentScan(basePackages = {"com.rapidtest"} )
public class RootConfig {

    //<bean id="propertyConfigurer" class="com.rapidtest.util.properties.ArchaiusPropertyPlaceholderConfigurer" />
    @Bean(name = "propertyConfigurer")
    public static ArchaiusPropertyPlaceholderConfigurer getPropertyPlaceholder() {
        return new ArchaiusPropertyPlaceholderConfigurer();
    }
}

2 个答案:

答案 0 :(得分:1)

这个

@ComponentScan(basePackages = {"com.rapidtest"} )
RootConfig中的

会扫描前缀为com.rapidtest的所有包裹。

您的MVCConfig课程在com.rapidtest.config.mvc个包中。因此,它也会被RootConfig加载的ContextLoaderListener选中并初始化。

隔离您的包裹,以免发生这种情况。

答案 1 :(得分:0)

我能够通过忽略组件扫描中的所有@Configuration类来解决问题。

@ComponentScan(basePackages = { "com.rapidtest.*" }, excludeFilters = {
    @ComponentScan.Filter(type = FilterType.ANNOTATION, value = { Configuration.class }) 
})