线上问题记录

  1. 现象
    请求一个接口,post上来的数据保存到数据库中出现中文乱码
    这里写图片描述
  2. 原因
    2.1 做优雅停机时,增加了一个Filter,HttpRequestCounterFilter用来在记录机器当前正在处理的请求,在Filter的处理逻辑中调用了HttpRequest的getParameterMap()方法,第一次调用该方法时,request会去解析用户传入的参数,解析结果会被缓存下来,后续不会再重新解析。
    这里写图片描述
    从上图中可以看到,请求的参数只在第一次调用getParameterMap时被解析,解析结果保存在paramterMap中

    2.2 参数解析时的编码
    这里写图片描述
    解析时会去获取字符编码,如果没有设置,则使用默认ISO-8859-1编码格式。到这里可以猜到,应该是在新的filter调用getParamterMap()之前没有设置字符编码的问题。

    2.3 filter chain
    这里写图片描述
      tomcat初始化时,所有执行的filter链,HttpRequestCounterFilter是处于第二个filter,执行之前并没有设置编码,默认采用ISO-8859-1编码,所以HttpRequestCounterFilter中调用request.getParameterMap解析时出现乱码。
      为什么去掉HttpRequestCounterFilter就正常了?
       filter chain中有一个SetCharacterEncodingFilter会设置编码为UTF-8, 而在SetCharacterEncodingFilter之前是没有调用request.getParameterMap函数,所以并没有执行参数解析,参数解析是在Spring MVC中调用request.getParameterMap时完成。
      SetCharacterEncodingFilter是tomcat web.xml配置的编码设置filter,tomcat启动加载应用时,会优先加载应用的web.xml, 然后再加载tomcat的web.xml。

  3. 解决
    应该在所有filter执行前设置编码,

    <filter>
         <filter-name>CharacterEncodingFilter</filter-name>
         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
         <async-supported>true</async-supported>
         <init-param>
                 <param-name>encoding</param-name>
                 <param-value>utf-8</param-value>
         </init-param>
    </filter>
    <filter-mapping>
         <filter-name>CharacterEncodingFilter</filter-name>
         <url-pattern>/*</url-pattern>
    </filter-mapping>
  4. 总结
    (1). 在SpringMVC项目中应该首先在web.xml中配置CharacterEncodingFilter,处理编码问题
    (2). 在pom.xml中添加如下依赖,调试tomcat源码

       <dependency>
             <groupId>org.apache.tomcat</groupId> 
             <artifactId>tomcat-catalina</artifactId>
             <version>8.0.35</version>
      </dependency>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值