Implementing Spring MVC 3.0 controller
Trying to implement clean URLs (without .form, .do, etc.) with Spring MVC 3.0 (actually it's a basic example from Spring reference). The problem that it just don't work: http://localhost:8080/ct/helloWorld gives a 404 page.
Below are my sources, plese help to find an error.
HelloWorldController.java
package controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller()
public class HelloWorldController {
@RequestMapping("/helloWorld")
public ModelAndView helloWorld() {
ModelAndView mav = new ModelAndView();
mav.setViewName("helloWorld");
mav.addObject("message", "Hello World!");
return mav;
}
}
ct-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="controllers" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springfr开发者_JAVA百科amework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
</beans>
web.xml
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>
ct</display-name>
<servlet>
<servlet-name>ct</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ct</servlet-name>
<url-pattern>/ct/*</url-pattern>
</servlet-mapping>
</web-app>
console output
12.11.2009 0:49:25 org.apache.tomcat.util.digester.SetPropertiesRule begin
WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.j2ee.server:ct' did not find a matching property.
12.11.2009 0:49:25 org.apache.catalina.core.AprLifecycleListener init
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Program Files\Java\jre6\bin;.;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:/Program Files/Java/jre6/bin/client;C:/Program Files/Java/jre6/bin;C:\Program Files\PC Connectivity Solution\;C:\PROGRA~1\RATIONAL\RATION~1\NUTCROOT\bin;C:\PROGRA~1\RATIONAL\RATION~1\NUTCROOT\bin\x11;C:\PROGRA~1\RATIONAL\RATION~1\NUTCROOT\mksnt;C:\Program Files\Borland\Delphi7\Bin;C:\Program Files\Borland\Delphi7\Projects\Bpl\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\Microsoft SQL Server\80\Tools\Binn\;C:\Program Files\Microsoft SQL Server\90\DTS\Binn\;C:\Program Files\Microsoft SQL Server\90\Tools\binn\;C:\Program Files\Microsoft SQL Server\90\Tools\Binn\VSShell\Common7\IDE\;C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\;C:\Program Files\TortoiseSVN\bin;C:\Program Files\QuickTime\QTSystem\;e:\my downloads\develop tools\nant-0.86-beta1\bin\;C:\Program Files\Rational\common;C:\Program Files\Rational\ClearQuest;C:\Program Files\Rational\Rose\TopLink\;C:\Program Files\Rational\Rational Test;C:\Program Files\CodeGear\Delphi Prism\bin
12.11.2009 0:49:25 org.apache.coyote.http11.Http11Protocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
12.11.2009 0:49:25 org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 769 ms
12.11.2009 0:49:25 org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
12.11.2009 0:49:25 org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.20
12.11.2009 0:49:26 org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring FrameworkServlet 'ct'
12.11.2009 0:49:26 org.springframework.web.servlet.FrameworkServlet initServletBean
INFO: FrameworkServlet 'ct': initialization started
12.11.2009 0:49:26 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing WebApplicationContext for namespace 'ct-servlet': startup date [Thu Nov 12 00:49:26 MSK 2009]; root of context hierarchy
12.11.2009 0:49:26 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from ServletContext resource [/WEB-INF/ct-servlet.xml]
12.11.2009 0:49:27 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@197507c: defining beans [helloWorldController,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,viewResolver,org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#0]; root of factory hierarchy
12.11.2009 0:49:27 org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/helloWorld] onto handler [controllers.HelloWorldController@1c2fff0]
12.11.2009 0:49:27 org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/helloWorld.*] onto handler [controllers.HelloWorldController@1c2fff0]
12.11.2009 0:49:27 org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/helloWorld/] onto handler [controllers.HelloWorldController@1c2fff0]
12.11.2009 0:49:28 org.springframework.web.servlet.FrameworkServlet initServletBean
INFO: FrameworkServlet 'ct': initialization completed in 2641 ms
12.11.2009 0:49:28 org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
12.11.2009 0:49:28 org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
12.11.2009 0:49:28 org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/79 config=null
12.11.2009 0:49:28 org.apache.catalina.startup.Catalina start
INFO: Server startup in 3451 ms
Your web.xml is mapping the Spring DispatcherServlet to the url pattern /ct/* on top of the location your web application is being deployed to.
So if your web application is being deployed to /ct try going to http://localhost:8080/ct/ct/helloWorld
Chances are that you want the Spring DispatcherServlet to be mapped to all urls for your web application. Change the servlet-mapping to:
<servlet-mapping>
<servlet-name>ct</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
and your original url should work as expected.
OK, for now solution is:
web.xml
<servlet-mapping>
<servlet-name>ct</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
HelloWorldController.java
@Controller
public class HelloWorldController {
@RequestMapping("/helloWorld")
public String list() {
return "helloWorld";
}
}
ct-servlet.xml
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
The path in your RequestMapping should be the full path, not just the pathInfo (the stuff after the matched string in the web.xml). So your RequestMapping should specify @RequestMapping("/ct/HelloWorld")
Alternatively, your problem may be that you aren't running your app as the root app and is actually running at the path /ct. In that case, your web.xml isn't matching anything because the /ct which designates the application context is not used when comparing the url-patterns in order to determine the servlet context. In that case, you need to access the url /ct/ct/HelloWorld in order to send the request to your servlet. But you'll still need @RequestMapping("/ct/HelloWorld") in order for the controller to be mapped to that request (but it doesn't care about the initial /ct which designates the app).
Personally, I actually think it is clear to map based on a suffix, but to use a generic suffix. I map *.html to my servlet and controllers which respond to those requests send back html. Similarly, I use *.json and *.xml for json and xml requests. I handle static html and other static content at the load balancer, so tomcat never sees them.
Have you created your helloWorld.jsp page?
I tried out your code (NB: using 2.5.6), and saw a 404 on the browser, and the following error message in the server log:
File "/path/to/my/WEB-INF/helloWorld.jsp" not found
Where /path/to/my
will be different for your env.
Without helloWorld.jsp, the view resolver will fail. Adding this jsp, and all is well.
精彩评论