记录一次中文乱码问题解决过程

每次遇到编码问题大概都要去找一找代码中中文的处理是否妥当,这次找了半天没找到,甚至更换了功能实现方式,发现问题不在编码而是在服务器设置。回头想来,走在自以为正确的道路上真的是一件很恐怖的事情,你会沿着条路走很远,到最后发现依然没有解决问题,好在这是在学习实践的路上,任何尝试都可以放在以后作为积累重新再回馈回来。放在当下,这就是一条道走到黑,不撞南墙不回头。

问题原因
还是很久之前的微信公众号网页项目,在复制详情做为新表单跳转到显示页面时候出现中文乱码问题。

解决办法
http访问转为https,Tomcat配置443端口时,编码也需要同步设置上 URIEncoding="UTF-8"

<Connector port="80" protocol="HTTP/1.1" URIEncoding="UTF-8"
  connectionTimeout="20000" redirectPort="443" />
               
 <Connector port="443" protocol="org.apache.coyote.http11.Http11Protocol" URIEncoding="UTF-8"
  maxThreads="150"  SSLEnabled="true" scheme="https" secure="true"
  clientAuth="false" sslProtocol="TLS"   keystoreFile="/tomcat/conf/cert/xxx.pfx" keystoreType="PKCS12"  keystorePass="xxx"/>
    

问题解决了,但这次解决问题的过程以及考虑过程可以拿出来警醒下自己。

这次编码问题第一个想到的就是说中文乱码嘛,找到乱码的那个参数给统一utf-8就行了如下:

new String(pmap.get("namexx").getBytes("ISO-8859-1"),"utf-8")

尝试过后,结果就是换了一种乱码。。。

鉴于上一次中文乱码问题加了个过滤器解决了,这次也上一个过滤器试试呢,如下:

/**
* ClassName: CharacterEncodingFilter
* @Description: 处理请求参数乱码问题
*/
public class CharacterEncodingFilter implements Filter {

   protected String encoding = null;

   protected FilterConfig filterConfig = null;

   protected boolean ignore = true;

    @Override
   public void destroy() {
       this.encoding = null;
       this.filterConfig = null;
    }

    @Override
   public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain)throws IOException, ServletException {
       if (ignore || (request.getCharacterEncoding() == null)) {
            String encoding= selectEncoding(request);
           if (encoding != null)
                request.setCharacterEncoding(encoding);
        }
        chain.doFilter(request, response);
    }

    @Override
   public void init(FilterConfig filterConfig) throws ServletException {
       this.filterConfig = filterConfig;
       // 获取初始化参数
        this.encoding = filterConfig.getInitParameter("encoding");
        String value= filterConfig.getInitParameter("ignore");
       if (value == null) {
           this.ignore = true;
        }else if (value.equalsIgnoreCase("true")) {
           this.ignore = true;
        }else if (value.equalsIgnoreCase("yes")) {
           this.ignore = true;
        }else
            this.ignore = false;

    }

   protected String selectEncoding(ServletRequest request) {
       return (this.encoding);
    }

web.xml

<filter>
   <filter-name>Character Encoding</filter-name>
   <filter-class>com.filter.CharacterEncodingFilter</filter-class>
   <init-param>
       <param-name>encoding</param-name>
       <param-value>UTF-8</param-value>
   </init-param>
</filter>
<filter-mapping>
   <filter-name>Character Encoding</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

结果显而易见,从前端竟然获取不到中文的参数了,感觉解决问题的路上越走越远了…

于是重新回顾整个请求流程:
(1)浏览器发送数据时,前端页面用了chatset=utf-8使用的utf-8。
(2)服务器解析浏览器发送的数据时,post提交已经通过过滤器设置为utf-8。
(3)服务器在返回数据时,前端整个文件编码以及内部编码设置的都是utf-8,

response.setContentType("text/html;charset=utf-8");
<%@page contentType="text/html;charset=gbk" pageEncoding="utf-8"%>

(4)最后是浏览器解析服务器返回的数据时,使用的也是utf-8

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

从请求到返回都使用了统一的UTF-8的编码,没道理这样了还是乱码。

于是换一种思路想,这次想着是不是参数返回格式不对呢,于是,把返回参数改成了JSON格式试了试,map转json倒也可以。但这就跟前端参数接收冲突了,如果再改前端获取的方式,那么多展示项,内心真的十分抗拒,太麻烦,懒的改,最后这个方式也Pass了(幸好有点懒)。

那是不是微信内置浏览器的锅呢?

于是打开微信web开发者工具,模拟本地请求。显示请求竟然丢失中文参数,于是重新给url请求参数做了编码处理,参数拆分开来,每个参数进行encode编码尝试 (这次并没有觉得麻烦,直觉这就是解决方案),如下:

URLEncoder.encode(pmap.get("namexx"),"utf-8")

再次请求,竟然成功了。
部署到服务器上,测试跑一跑发现问题竟然还在…。项目毕竟要线上用,本地再好使也没用。

于是重新定位到问题不在后台前端编码设置上,在服务器上。

连上服务器看看设置,原来的http请求设置了URIEncoding=“UTF-8”,但是当前使用已经更改为https,但是在服务器上的Tomcat配置并没有设置URIEncoding编码。

回看这次解决问题的过程,一开始轻视问题,之后盲目的经验主义定位问题,最后转换角度才找到问题原因。
如果最开始直接微信开发者工具跑一下,区分两种请求的不同,要能省下许多时间。
不过,这个过程中又把Unicode编码原理过一遍也算温故知新了吧。。。

以上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值