zoukankan      html  css  js  c++  java
  • 一个因为URLEncoder和URLDecoder引发的bug

    引言

          最近公司项目遇到项目之间的项目调用,通过HttpURLConnection实现的,不过在此过程中,遇到了中文和特殊字符的问题,结果最后排查半天是因为中文和特殊字符(%)导致的接口调不通或是调通接口后,解析数据出现异常,问题很隐蔽难排查,不过好在最后还是功夫不负有心人,只是耽误了点时间!

    1:调用URL中出现中文参数的问题

    //删除VBD-IIS大数据违法记录
        public boolean delVehicleBigData(String  vehicleBigDataUrl,String plateNo,String passTime){
            boolean flag=false;
            StringBuffer strURLCount = new StringBuffer();
    //vehicleBigDataUrl请求路径 如:http://10.30.27.153:8090 strURLCount.append(vehicleBigDataUrl
    + "/VBD/illegal/deleteIllegalData?"); try { strURLCount.append("plateNo="+URLEncoder.encode(plateNo,"utf-8")); //鄂AK7259 strURLCount.append("&passTime="+URLEncoder.encode(passTime,"utf-8")); JSONObject jsonObject = Tools.insert(strURLCount.toString()); if(jsonObject.isNullObject()){ LogUtil.error("jsonObject = null"); flag=false; } int ret = jsonObject.getInt("ret"); if(0 != ret){ LogUtil.error("ret = " + ret); flag=true; }else{ flag=false; } }catch(UnsupportedEncodingException e1) { e1.printStackTrace(); } return flag; }

    Tools帮助类

         /**
         * 方法说明: 调用URL返回结果
         *
         * @param Url
         * @return 
         * @作者及日期:zhaosqing    2020-09-21
         * @修改人及日期:zhaosqing  2020-09-21
         * @修改描述:
         * @其他:
         */
        public static JSONObject insert(String Url){
            if(null == Url){
                return null;
            }
            StringBuffer strBuffer = new StringBuffer();
            BufferedReader brd =null;
            HttpURLConnection connet = null;
            try {
                URL url = new URL(Url);
                  //实例一个HTTP CONNECT
                  connet = (HttpURLConnection) url.openConnection();
                  connet.setRequestMethod("GET");
                  connet.setDoOutput(true);
                  connet.setDoInput(true);
                  connet.setUseCaches(false);
                  connet.setConnectTimeout(300000);
                  connet.setReadTimeout(300000);
                  connet.connect();
                  if(connet.getResponseCode() != 200){
                      throw new IOException(connet.getResponseMessage());
                  }
                  //将返回的值存入到String中
                  brd = new BufferedReader(new InputStreamReader(connet.getInputStream(),"utf8"));
                  String line=brd.readLine();
                  while(line != null){
                      line = java.net.URLDecoder.decode(line, "UTF-8");
                      strBuffer.append(line);
                      line = brd.readLine();
                  }
            } catch (MalformedURLException e) {
                    LogUtil.error("insert MalformedURLException:" + e.getMessage());
                return null;
            } catch (IOException e) {
                    LogUtil.error("insert IOException:" + e.getMessage());
                return null;
            }finally{
                if(brd !=null){
                     try {
                         brd.close();
                     } catch (IOException e) {
                     }
                }
                if(connet!=null){
                    connet.disconnect();
                }
            }
            return JSONObject.fromObject(strBuffer.toString());
        }

    因为调用URL的里边包含车牌号plateNo和同行时间passTime,车牌号必要会带中文参数的,如鄂AK7259,这就会导致调用http请求的时候,请求失败,只有先将plateNo通过URLEncoder.encode(plateNo,"utf-8"))编码后,然后再拼接到url中,最后接收请求的时候,在通过解码的方式,将其还原成中文,如:String plaeteNo= URLDecoder.decode(illegal .getPlateNo(),"utf-8"); 

    2:调用URL返回结果中包含特殊字符如(%)

        /**
         * 获取大数据违法类型列表
         * @param vehicleBigDataUrl
         * @return
         * @throws Exception 
         */
        public List<ItsCodewfdm> getAllwfdmCodeList() throws Exception{
            List<ItsCodewfdm> list=new ArrayList<ItsCodewfdm>();
            String vehicleBigDataUrl=this.vehicleBigDataUrl();//获取大数据服务器的ip和端口
            StringBuffer strURLCount = new StringBuffer();
             try {
    //vehicleBigDataUrl 请求的url 如 http://10.30.27.153:8090 strURLCount.append(vehicleBigDataUrl
    + "/VBD/illegal/queryAllwfdmCodeList"); JSONObject jsonObject = Tools.getWfdmCodeListByVBD(strURLCount.toString()); if(jsonObject.isNullObject()){ LogUtil.error("jsonObject = null"); return list; } String content=jsonObject.getString("content"); JSONArray array= JSONArray.fromObject(content); if(array!=null && array.size()>0){ for(int i=0;i<array.size();i++){ ItsCodewfdm wfdm =new ItsCodewfdm(); wfdm.setDm(array.getJSONObject(i).getString("dm")); wfdm.setWfxw(array.getJSONObject(i).getString("wfxw")); list.add(wfdm); } } } catch (Exception e) { e.printStackTrace(); } return list; }

     Tools帮助类

    /**
         * 方法说明: 调用URL返回结果
         * 返回vbd违法类型数据
         * @param Url
         * @return 
         * @作者及日期:zhaosqing    2020-09-20
         * @修改描述:
         * @其他:
         */
        public static JSONObject getWfdmCodeListByVBD(String Url){
            if(null == Url){
                return null;
            }
            StringBuffer strBuffer = new StringBuffer();
            BufferedReader brd =null;
            HttpURLConnection connet = null;
            try {
                URL url = new URL(Url);
                  //实例一个HTTP CONNECT
                  connet = (HttpURLConnection) url.openConnection();
                  connet.setRequestMethod("GET");
                  connet.setDoOutput(true);
                  connet.setDoInput(true);
                  connet.setUseCaches(false);
                  connet.setConnectTimeout(300000);
                  connet.setReadTimeout(300000);
                  connet.connect();
                  if(connet.getResponseCode() != 200){
                      throw new IOException(connet.getResponseMessage());
                  }
                  //将返回的值存入到String中
                  brd = new BufferedReader(new InputStreamReader(connet.getInputStream(),"utf8"));
                  String line=brd.readLine();
                  //处理返回结果中包含%的问题 (如:超速20%-50%)
                  if(line.contains("%")){
                      line=URLEncoder.encode(line,"UTF-8");
                  }
                  while(line != null){
                      line = java.net.URLDecoder.decode(line, "UTF-8");
                      strBuffer.append(line);
                      line = brd.readLine();
                  }
            } catch (MalformedURLException e) {
                    LogUtil.error("insert MalformedURLException:" + e.getMessage());
                return null;
            } catch (IOException e) {
                    LogUtil.error("insert IOException:" + e.getMessage());
                return null;
            }finally{
                if(brd !=null){
                     try {
                         brd.close();
                     } catch (IOException e) {
                     }
                }
                if(connet!=null){
                    connet.disconnect();
                }
            }
            return JSONObject.fromObject(strBuffer.toString());
        }

    因为请求url后通过IO流的方式获取查询到的结果然后解析,在返回的line结果中包含特殊字符,然后通过URLDecoder.decode(line, "UTF-8");进行解码后就出现异常了,所以得判断一下,时候包含特殊字符,如果包含就先将其URLEncoder.encode(line,"UTF-8");编码再解码就不会出现问题。

    至此,问题排查分析完了,不过在当初项目中你排查的时候,可是费了一番功夫排查的,因为项目部署在服务器Linux系统上,不能远程debug,只有慢慢分析代码打日志排查了!

  • 相关阅读:
    在UITableView顶部制作简单的UISegmentControl实例方法
    iOS9 适配网络请求,适配分享失败,适配无法正常跳转到客户端
    iOS页面切换动画实现方式。
    Springboot-Dockerfile指令
    Springboot-Docker-Dockerfile
    Springboot-Docker-1
    SpringBoot-Security
    SpringBoot-MongoDB
    SpringBoot-RabbitMQ
    SpringBoot-Memcached
  • 原文地址:https://www.cnblogs.com/zhaosq/p/13723428.html
Copyright © 2011-2022 走看看