一个简单的SpringMVC Hello World程序如下:
package com.xiya.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Created by N3verL4nd on 2017/5/19.
*/
@Controller
public class TestController {
@RequestMapping("/test1")
public String test1() {
return "/WEB-INF/views/hello.jsp";
}
@RequestMapping("/test2/test2")
public String test2() {
return "/WEB-INF/views/hello.jsp";
}
}
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.xiya.controller"/>
<!--<mvc:default-servlet-handler/>-->
<!--<mvc:annotation-driven/>-->
</beans>
项目结构如下:
但是当我们访问根目录下的abc.html,是不能访问的,因为我们在web.xml的url-pattern设置的是:
<url-pattern>/</url-pattern>
如上配置,DispatcherServlet不会拦截*.jsp,*.html等文件。而交由默认的Servlet处理器来进行处理。
conf/web.xml
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
我们在SpringMVC中的配置
<url-pattern>/</url-pattern>
覆盖掉了默认的DefaultServlet,所以导致静态文件无法被处理。而*.jsp文件则由JspServlet进行处理。
Spring MVC会将它们当成一个普通请求处理,因此找不到对应处理器将导致错误。
可以如下作验证:
@RequestMapping("/abc.html") public String test3() { return "/WEB-INF/views/hello.jsp"; }为了解决以上问题,我们可以在SpringMVC配置文件中作如下配置:
<mvc:default-servlet-handler/>但是问题又来了:原先可以访问的curl http://localhost:8080/SpringMVC/test1 现在不能访问了。
所以接着要配置:
<mvc:annotation-driven/>
我们通过debug来试着找找原因:
推荐IntelliJ IDEA的 IDEA Jetty Runner插件,比Tomcat在部署项目速度上快很多。
IntelliJ IDEA是我用过和VS一样牛逼的IDE。
我们在DispatcherServlet的
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
处下断点,debug走起:
我们分三种情况来展示:
1、<mvc:default-servlet-handler/>与<!--<mvc:annotation-driven/>都不配置
2、只写<mvc:default-servlet-handler/>
3、两个都配置。
Spring3.2以前由org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter来处理@RequestMapping,
3.2以后由org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter处理。
在SpringMVC spring-webmvc 源码里也可看出点端倪:org\springframework\web\servlet\DispatcherServlet.properties
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
这些都是SpringMVC默认加载的。
所以我们可以不配置视图解析器。
@RequestMapping("/test1") public String test1() { return "/WEB-INF/views/hello.jsp"; }
参考:
http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.html
http://www.cnblogs.com/hujingwei/p/5349983.html
http://www.cnblogs.com/fangqi/archive/2012/10/28/2743108.html