• 汉字传值奇数乱码问题解决策略


      这两天写一个项目遇到一个很怪异的现象,就是在url中汉字传值,如果是奇数个汉字则出现编码错误。先说下环境:前台页面试gb2312编码,后台的filter是gbk,web server是nginx+resin,nginx用的是操作系统编码,编码是gbk,在输入http://www.我的域名.com/search/searchByName.action?query=%C1%AC%C1%AC%BF%B4  (1) 时后台不需要做处理,

    返回字符串正常,再输入http://www.我的域名.com/search/searchByName.action?query=连连看                       (2) 时后台就显示乱码。

      我分别用chrome、firefox、ie8做了测试,结果虽然是乱码还各有特色。

      最初,在网上搜索解决方案,不过大部分都是一个来源,也就是让你在页面上先对汉字url encode一下然后再传值,但是这种情况不符合我的需求,我是要在浏览器中直接输入url,汉字传值。

      解决方案一,在nginx中配置,将传递过来的url进行重写,让参数以重叠的方式向后台传送,比如原来是"query=你好啊",重写为"query = 你好啊你好啊",这样可以避免奇数个乱码问题,不过这有一个问题,就是和web server的耦合性太高,只要有汉字传值,就得重写nginx配置文件,不可取。

      解决方案二,在后台发现,取出的parameter在utf8转换成gbk时,如果字符串.getbytes()是奇数个,最后一个byte会被吞掉,信息损失了,就没法转换回来了。很烦人,这时候在同事的启发下,发现request.getQueryString(),也可以得到参数,并且都是被转码过的,形如“query=%e7%be%8e%e5%a5%b3”,这个是没有被gbk过滤的,所以就通过处理这个字符串获取到了没有信息损失的编码。不过这时还有个问题,页面输入(1)(2)两个链接时后台要拿到相同的汉字,但是他们被编码后显示的编码值却不同,就是这个时候只要通过判断是否为utf8的url(此时有汉字传值),如下代码:

    String parameterString = request.getQueryString();  
    if(parameterString!=null&&!parameterString.equals("")){
    try {
    CharTools ct = new CharTools();
    if(ct.isUtf8Url(parameterString)){
    parameterString = URLDecoder.decode(parameterString, "utf-8");
    }else{
    parameterString = URLDecoder.decode(parameterString, "gbk");
    }
    } catch (UnsupportedEncodingException e) {
    logger.info("url解码出错", e);
    }
    String[] parameters = parameterString.split("&");
    for(String str : parameters){
    if(str.indexOf("query=")!=-1){
    query = str.substring(str.indexOf("=")+1);
    }
    }
    }

       其中对应的CharTools中的方法为:

    public boolean isUtf8Url(String text) {  
    text = text.toLowerCase();
    int p = text.indexOf("%");
    if (p != -1 && text.length() - p > 9) {
    text = text.substring(p, p + 9);
    }
    return Utf8codeCheck(text);
    }
    private boolean Utf8codeCheck(String text) {
    String sign = "";
    if (text.startsWith("%e"))
    for (int i = 0, p = 0; p != -1; i++) {
    p = text.indexOf("%", p);
    if (p != -1)
    p++;
    sign += p;
    }
    return sign.equals("147-1");
    }

    这样就可以将不同的编码传过来的url,进行不同的处置。

    接下来,这时候本以为完事大吉,没想又出了新的问题,即:在ie下汉字传值还是乱码,我通过后台检测发现,ie的request.getQueryString(),获取的是“query=????”,汉字没有以编码后的形式传送过来,然后再检查request.getParameter("query"),发现是正常的,这时候就可以通过对发送到后台的客户端就行判断,如下:

    String agent = request.getHeader("User-Agent");  
    if(agent.indexOf("MSIE")!=-1){//ie情况比较特殊,不过此时在parameters中是正常的
    query = request.getParameter("query");
    }

    这样在ie下拿到的汉字也就可以正常的显示了。

    解决方案三:觉得最好的解决方案还是写个filter,现在项目比较紧张,以后要写,这样就可以忽略掉具体的请求,从整体层次进行解决问题。大致思路就是将方案二的解决办法浓缩到filter中。以后再写

     

    还有一些感想,觉得chrome也不是那么完美,汉字传值不自动转码,给开发造成不少麻烦,还是firefox比较强大~




      

     

  • 相关阅读:
    ettercap 实施中间人攻击
    JS高级---逆推继承看原型
    JS高级---总结继承
    JS高级---拷贝继承:把一个对象中的属性或者方法直接复制到另一个对象中
    JS高级---借用构造函数
    JS高级---继承案例
    JS高级---继承
    JS高级---一个神奇的原型链
    JS高级---实例对象和属性重名问题
    JS高级---原型链最终的指向是Object的prototype, 而Object中的__proto__是null
  • 原文地址:https://www.cnblogs.com/seanvon/p/2323385.html
Copyright © 2020-2023  润新知