简体   繁体   中英

Added component-scan to a legacy Spring application

I have a legacy Spring application whether the context is configured entirely with XML. I would like to add a new controller to the application using the @Controller annotation so I begin to migrate to using annotations.

As a test I have added the following controller to the application

package uk.co.onevisionconsulting.engineermanager.webapp.controller2;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {

     @RequestMapping("/hello")
     public String hello(){
          return "Hello";
     }
}

I have also added the context:component-scan tag to my spring context

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans” xmlns:context="http://www.springframework.org/schema/context"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance”
             xsi:schemaLocation="http://www.springframework.org/schema/beans
             http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
             http://www.springframework.org/schema/context
             http://www.springframework.org/schema/context/spring-context-2.5.xsd">

     <context:component-scan base-package="uk.co.onevisionconsulting.engineermanager" />

     <bean name="jsonView"
          class="uk.co.onevisionconsulting.engineermanager.webapp.view.JsonView" />

     <bean name="csvView"
          class="uk.co.onevisionconsulting.engineermanager.webapp.view.CsvView" />

     <bean name="ajaxView"
          class="uk.co.onevisionconsulting.engineermanager.webapp.view.AjaxView" />

     <bean name="dataTablesView"
          class="uk.co.onevisionconsulting.engineermanager.webapp.view.DataTablesView" />

     <bean id="exceptionResolver"
          class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
          <property name="exceptionMappings">
               <props>
                    <prop key="org.springframework.dao.DataAccessException">
                         dataAccessFailure
                    </prop>
               </props>
          </property>
     </bean>

     <bean id=“someController"
          class="uk.co.onevisionconsulting.engineermanager.webapp.controller.SomeController" >
          <property name=“someManager" ref=“someManager" />
     </bean>

     <!-- Loads more controllers -->

     <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
          <property name="maxUploadSize" value="2097152" />
     </bean>

     <bean id="messageSource"
          class="org.springframework.context.support.ResourceBundleMessageSource">
          <property name="basename" value="ApplicationResources" />
          <property name="useCodeAsDefaultMessage" value="true" />
     </bean>

     <bean id="urlMapping"
          class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
          <property name="mappings">
               <value>
                    <!— Some URLs —>
               </value>
          </property>
          <property name="order" value="0" />
     </bean>

     <bean
          class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
          <property name="order" value="1" />
     </bean>

     <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
          <property name="order" value="2" />
     </bean>

     <!-- View Resolver for JSPs -->
     <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
          <property name="requestContextAttribute" value="rc" />
          <property name="viewClass"
               value="org.springframework.web.servlet.view.JstlView" />
          <property name="prefix" value="/WEB-INF/pages/" />
          <property name="suffix" value=".jsp" />
     </bean>
</beans>

All though the classpath scanner (ClassPathScanningCandidateComponentProvider) picks up the HelloController I get a 404 when I try and navigate to localhost:8080/hello

Can anyone see what else I need to do? Here is my web.xml

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

    <display-name>Engineer Manager</display-name>

    <!-- Define the default CSS Theme -->
    <context-param>
        <param-name>csstheme</param-name>
        <param-value>engineermanager</param-value>
    </context-param>

    <!-- Define the basename for a resource bundle for I18N -->
    <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
        <param-value>ApplicationResources</param-value>
    </context-param>

    <!-- Fallback locale if no bundles found for browser's preferred locale -->
    <!-- Force a single locale using param-name 'javax.servlet.jsp.jstl.fmt.locale' -->
    <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.fallbackLocale</param-name>
        <param-value>en</param-value>
    </context-param>

    <!-- Context Configuration locations for Spring XML files -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:/applicationContext-resources.xml
            classpath:/applicationContext-dao.xml
            classpath:/applicationContext-service.xml
            classpath*:/applicationContext.xml
            /WEB-INF/applicationContext*.xml
            /WEB-INF/security.xml
        </param-value>
    </context-param>

    <filter>
        <filter-name>localeFilter</filter-name>
        <filter-class>org.appfuse.webapp.filter.LocaleFilter</filter-class>
    </filter>
    <filter>
        <filter-name>securityFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetBeanName</param-name>
            <param-value>springSecurityFilterChain</param-value>
        </init-param>
    </filter>
    <filter>
        <filter-name>sitemesh</filter-name>
        <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
    </filter>
    <filter>
        <filter-name>staticFilter</filter-name>
        <filter-class>org.appfuse.webapp.filter.StaticFilter</filter-class>
        <init-param>
            <param-name>servletName</param-name>
            <param-value>dispatcher</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>securityFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>localeFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>sitemesh</filter-name>
        <url-pattern>*.html</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
    <filter-mapping>
        <filter-name>sitemesh</filter-name>
        <url-pattern>*.jsp</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
    <filter-mapping>
        <filter-name>staticFilter</filter-name>
        <url-pattern>*.html</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.appfuse.webapp.listener.StartupListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.appfuse.webapp.listener.UserCounterListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.json</url-pattern>
    </servlet-mapping>

    <session-config>
        <session-timeout>3600</session-timeout>
    </session-config>

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

    <error-page>
        <error-code>500</error-code>
        <location>/error.jsp</location>
    </error-page>
    <error-page>
        <error-code>400</error-code>
        <location>/index.jsp</location>
    </error-page>
    <error-page>
        <error-code>403</error-code>
        <location>/403.jsp</location>
    </error-page>
    <error-page>
        <error-code>404</error-code>
        <location>/404.jsp</location>
    </error-page>
</web-app>

Your DispatcherServlet doesn't pick the /hello url-pattern.

So change the web.xml configuration as shown below to pick the multiple url-pattern values:

<servlet-mapping>
     <servlet-name>dispatcher</servlet-name>
      <url-pattern>*.json</url-pattern> <!-- serves all .json requests -->
      <url-pattern>/hello</url-pattern> <!-- serves /hello request -->
</servlet-mapping>

Since you have mentioned that this is a legacy application, I believe it is working with the existing configuration.

Also, since your are trying to migrate using annotation for new Controllers, it is to do with annotation processing.

You will need to add the annotation mentioned below along with the mvc namespace configuraton in the root beans tag of your spring context xml file.

<mvc:annotation-driven/>

A partial code snippet for the configuration is as below

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd"
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:component-scan base-package="uk.co.onevisionconsulting.engineermanager" />
    <mvc:annotation-driven/>

    ...

</beans>

A detailed explanation for the reason can be found at Spring MVC: difference between <context:component-scan> and <annotation-driven /> tags?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM