【noHandlerFound(DispatcherServlet.java:1278)和No mapping for GET】SpringMVC 404和中文乱码问题和解决方案记录
前言
刚开始学习springmvc,却被404和乱码搞得晕头转向,为此还没学多少springmvc的其他知识,就开始调试它的源码查找问题了,还花了一天的时间,这里先记录一下。如有错误,可以指出。
demo项目概述
项目结构

tomcat服务器配置

相关java代码
| |
相关配置文件
- springmvc-servlet.xml
| |
- web.xml
| |
出现的问题
404问题
按上述配置后访问会出现404问题
控制台输出
| |
由于刚刚学习,对于springmvc的处理机制还没熟悉,
不确定是否按下面的方式返回ModelAndView对象是否正确
| |
于是,我尝试了将index.html改为index.jsp,在/WEB-INF/templates目录下新建一个index.jsp,发现访问正常,这个可以说明这样配置是可以访问的
其实是因为我们访问
/这个路径会被配置为<url-pattern>/</url-pattern>的dispatcherServlet处理,dispatcherServlet会调用我们配置了路径为/的处理方法,即UserController。springmvc获取ModelAndView,将请求转发到能处理/WEB-INF/templates/index.jsp的servlet上,这个请求实际上会转发给tomcat处理jsp的servlet,所以可以正确响应

404问题尝试解决方案
如果对tomcat的路径匹配感兴趣可以看一下我之前写的
搞懂tomcat中web.xml配置servlet的url-pattern为"/"和"/*"的区别
配置默认映射(失败)
我在网上查了一下,发现有些是说配置如下映射可以解决html访问的问题
| |
然而这个配置并没有生效,这个配置看似可以匹配/WEB-INF/templates/index.html这个路径。但是,我们一开始访问的路径是/,而且这个并不会匹配到配置为 <url-pattern>/</url-pattern>的dispatcherServlet,而是匹配到tomcat默认的DefaultServlet,这个和tomcat的路径匹配规则有关,因为我们配置了上面的*.html拓展名映射,这个就会导致/匹配到了DefaultServlet,它实际会访问/index.html,但是我并没有在根目录下放置index.html这个文件,所以会出现404的问题。
看来这个配置只是解决访问根目录下的index.html的问题。但是,我要访问的是在/WEB-INF/templates/index.html这个路径下的
配置jsp映射(成功)
接着,我又看到一个配置
| |

将html拓展名的请求交给处理jsp的servlet,显然,这个是可以的,这个就和处理jsp的情况一样了,不过这样把html的请求交给处理jsp的,感觉怪怪的
springmvc配置<mvc:default-servlet-handler/>标签(成功)
所以再接着,我看到一个说在springmvc的配置文件中加入<mvc:default-servlet-handler/>,这个配置后也是可以正确访问到的
这个配置会在
springmvc的上下文中定义一个DefaultServletHttpRequestHandler,这个会在没有其他更具体的映射(即到控制器)可以匹配时会执行,这个程序会转发请求到默认Servlet
注意
默认情况下,springmvc会默认读取
DispatcherServlet.properties文件列举的HandlerMapping


但是配置了<mvc:default-servlet-handler/>会导致默认配置失效,但是这个配置也会自动注册一些HandlerMapping;除了会注册DefaultServletHttpRequestHandler 还将注册一个SimpleUrlHandlerMapping用于映射资源请求,以及一个HttpRequestHandlerAdapter ,此外还会注册如下组件
所以如果只配置<mvc:default-servlet-handler/>,则只会有SimpleUrlHandlerMapping和BeanNameUrlHandlerMapping这两个HandlerMapping,没有RequestMappingHandlerMapping,会导致使用@RequestMapping之类注解的配置失效,无法映射。
- 解决这个问题可以在
springmvc配置文件中配置<mvc:annotation-driven/>,这个会自动注入RequestMappingHandlerMapping和BeanNameUrlHandlerMapping
当然我们也可以手动注册
1 2 3 4 5<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> <property name="order" value="0"/> </bean> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
乱码问题
在处理完404问题后,还有一个初学者经常见到的问题,那就是中文乱码了
index.html文件内容

- 浏览器结果

- 响应头

我使用的是idea编辑器,我设置了文件编码都是utf-8

解决过程
在web项目中出现了乱码,一般可以通过过滤器来解决,springmvc中提供了一个处理编码得过滤器CharacterEncodingFilter
,在web.xml中配置如下过滤器即可
| |
然而这个配置并没有解决index.html中文乱码得问题,而且,我一开始就配置了这个过滤器的。但是,这个配置确实是设置了编码的了,不过为什么没作用呢?
在java中我知道的可以影响编码的属性有encoding和file.encoding,于是我想到打印一下file.encoding属性的值是否是utf-8

输出如下

发现他的值是GBK,于是我在vm options中加入
-Dfile.encoding=utf-8,重启服务器

最后发现,乱码问题解决
file.encoding在这里影响的是什么呢?,既然response已经设置编码为utf-8,那么说明这个响应到浏览器的编码是没有问题的,还有一个就是读取本地的index.html文件时所使用的编码,如果以GBK读取index.html文件,再以UTF-8响应文件给浏览器,那么就会出现问题了,可见这个file.encoding在这里影响的是读取本地文件的编码

浏览器可能会缓存,导致页面没有变化,可以禁用缓存,多刷新几次

总结
遇到问题,我们除了利用好搜索引擎,合理debug查找问题也是一种锻炼,这样可以更好理解代码的流程,提高自己的调式和排错能力
当然我们也可以手动注册