使用 mvc:default-servlet-handler 中的一个bug


[java]  view plain  copy
  1. package com.xiya.controller;  
  2.   
  3. import org.springframework.stereotype.Controller;  
  4. import org.springframework.web.bind.annotation.RequestMapping;  
  5.   
  6. /** 
  7.  * Created by N3verL4nd on 2017/5/19. 
  8.  */  
  9. @Controller  
  10. public class TestController {  
  11.   
  12.     @RequestMapping("/test1")  
  13.     public String test1() {  
  14.         return "/WEB-INF/views/hello.jsp";  
  15.     }  
  16.   
  17.     @RequestMapping("/test2/test2")  
  18.     public String test2() {  
  19.         return "/WEB-INF/views/hello.jsp";  
  20.     }  
  21. }  
[java]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:context="http://www.springframework.org/schema/context"  
  5.        xmlns:mvc="http://www.springframework.org/schema/mvc"  
  6.        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">  
  7.   
  8.     <context:component-scan base-package="com.xiya.controller"/>  
  9.   
  10.     <!--<mvc:default-servlet-handler/>-->  
  11.   
  12.     <!--<mvc:annotation-driven/>-->  
  13.   
  14. </beans>  

项目结构如下:


当我们访问:curl http://localhost:8080/SpringMVC/test1,是可以正常访问的。

但是当我们访问根目录下的abc.html,是不能访问的,因为我们在web.xml的url-pattern设置的是:

<url-pattern>/</url-pattern>

如上配置,DispatcherServlet不会拦截*.jsp,*.html等文件。而交由默认的Servlet处理器来进行处理。

conf/web.xml

[html]  view plain  copy
  1. <servlet>  
  2.         <servlet-name>default</servlet-name>  
  3.         <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>  
  4.         <init-param>  
  5.             <param-name>debug</param-name>  
  6.             <param-value>0</param-value>  
  7.         </init-param>  
  8.         <init-param>  
  9.             <param-name>listings</param-name>  
  10.             <param-value>false</param-value>  
  11.         </init-param>  
  12.         <load-on-startup>1</load-on-startup>  
  13. </servlet>  
  14. <servlet-mapping>  
  15.         <servlet-name>default</servlet-name>  
  16.         <url-pattern>/</url-pattern>  
  17. </servlet-mapping>  
  18. <servlet>  
  19.         <servlet-name>jsp</servlet-name>  
  20.         <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>  
  21.         <init-param>  
  22.             <param-name>fork</param-name>  
  23.             <param-value>false</param-value>  
  24.         </init-param>  
  25.         <init-param>  
  26.             <param-name>xpoweredBy</param-name>  
  27.             <param-value>false</param-value>  
  28.         </init-param>  
  29.         <load-on-startup>3</load-on-startup>  
  30. </servlet>  
[html]  view plain  copy
  1. <servlet-mapping>  
  2.         <servlet-name>jsp</servlet-name>  
  3.         <url-pattern>*.jsp</url-pattern>  
  4.         <url-pattern>*.jspx</url-pattern>  
  5.     </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

[java]  view plain  copy
  1. # Default implementation classes for DispatcherServlet's strategy interfaces.  
  2. # Used as fallback when no matching beans are found in the DispatcherServlet context.  
  3. # Not meant to be customized by application developers.  
  4.   
  5. org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver  
  6.   
  7. org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver  
  8.   
  9. org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\  
  10.     org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping  
  11.   
  12. org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\  
  13.     org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\  
  14.     org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter  
  15.   
  16. org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\  
  17.     org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\  
  18.     org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver  
  19.   
  20. org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator  
  21.   
  22. org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver  
  23.   
  24. 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值