【noHandlerFound(DispatcherServlet.java:1278)和No mapping for GET】SpringMVC 404和中文乱码问题和解决方案记录

2 篇文章 0 订阅
1 篇文章 0 订阅

前言

刚开始学习springmvc,却被404乱码搞得晕头转向,为此还没学多少springmvc的其他知识,就开始调试它的源码查找问题了,还花了一天的时间,这里先记录一下。如有错误,可以指出。

demo项目概述

项目结构

picture 2

tomcat服务器配置

picture 3

相关java代码

package com.wcj.springmvc.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @description: UserController
 * @date: *****
 * @author: ******
 */
public class UserController implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return new ModelAndView("/WEB-INF/templates/index.html");
    }
}

相关配置文件

  • springmvc-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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean name="/" class="com.wcj.springmvc.controller.UserController"/>

</beans>

  • web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!--设置编码格式-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!--设置编码格式的生效范围-->
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>


    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-context.xml</param-value>
    </context-param>


</web-app>

出现的问题

404问题

按上述配置后访问会出现404问题

picture 1
控制台输出

[WARN ] org.springframework.web.servlet.DispatcherServlet.noHandlerFound(DispatcherServlet.java:1278) - No mapping for GET /my_springmvc/WEB-INF/templates/index.html

由于刚刚学习,对于springmvc的处理机制还没熟悉,
不确定是否按下面的方式返回ModelAndView对象是否正确

  return new ModelAndView("/WEB-INF/templates/index.html");

于是,我尝试了将index.html改为index.jsp,在/WEB-INF/templates目录下新建一个index.jsp,发现访问正常,这个可以说明这样配置是可以访问的

其实是因为我们访问/这个路径会被配置为 <url-pattern>/</url-pattern>dispatcherServlet处理,dispatcherServlet会调用我们配置了路径为/的处理方法,即UserControllerspringmvc获取ModelAndView,将请求转发到能处理/WEB-INF/templates/index.jspservlet上,这个请求实际上会转发给tomcat处理jspservlet,所以可以正确响应

picture 4

404问题尝试解决方案

如果对tomcat的路径匹配感兴趣可以看一下我之前写的
搞懂tomcat中web.xml配置servlet的url-pattern为"/“和”/*"的区别

配置默认映射(失败)


我在网上查了一下,发现有些是说配置如下映射可以解决html访问的问题


 <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.html</url-pattern>
</servlet-mapping>

然而这个配置并没有生效,这个配置看似可以匹配/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映射(成功)


接着,我又看到一个配置

    <servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>

picture 5

html拓展名的请求交给处理jspservlet,显然,这个是可以的,这个就和处理jsp的情况一样了,不过这样把html的请求交给处理jsp的,感觉怪怪的

springmvc配置<mvc:default-servlet-handler/>标签(成功)


所以再接着,我看到一个说在springmvc的配置文件中加入<mvc:default-servlet-handler/>,这个配置后也是可以正确访问到的

这个配置会在springmvc的上下文中定义一个DefaultServletHttpRequestHandler,这个会在没有其他更具体的映射(即到控制器)可以匹配时会执行,这个程序会转发请求到默认Servlet


注意

默认情况下,springmvc会默认读取DispatcherServlet.properties文件列举的HandlerMapping
picture 3
picture 1
picture 2
但是配置了<mvc:default-servlet-handler/>会导致默认配置失效,但是这个配置也会自动注册一些HandlerMapping;除了会注册DefaultServletHttpRequestHandler 还将注册一个SimpleUrlHandlerMapping用于映射资源请求,以及一个HttpRequestHandlerAdapter ,此外还会注册如下组件
picture 4
所以如果只配置<mvc:default-servlet-handler/>,则只会有SimpleUrlHandlerMappingBeanNameUrlHandlerMapping这两个HandlerMapping,没有RequestMappingHandlerMapping,会导致使用@RequestMapping之类注解的配置失效,无法映射。

  • 解决这个问题可以在springmvc配置文件中配置<mvc:annotation-driven/>,这个会自动注入RequestMappingHandlerMappingBeanNameUrlHandlerMapping

    picture 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文件内容

picture 7

  • 浏览器结果

picture 6

  • 响应头

picture 14

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

图片1

解决过程

在web项目中出现了乱码,一般可以通过过滤器来解决,springmvc中提供了一个处理编码得过滤器CharacterEncodingFilter
,在web.xml中配置如下过滤器即可

<filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!--设置编码格式-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!--设置编码格式的生效范围-->
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

然而这个配置并没有解决index.html中文乱码得问题,而且,我一开始就配置了这个过滤器的。但是,这个配置确实是设置了编码的了,不过为什么没作用呢?

在java中我知道的可以影响编码的属性有encodingfile.encoding,于是我想到打印一下file.encoding属性的值是否是utf-8

picture 8

输出如下

picture 9

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

picture 10

最后发现,乱码问题解决

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

picture 11

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

总结

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

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值