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

一个简单的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>

项目结构如下:


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

但是当我们访问根目录下的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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

N3verL4nd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值