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,只有慢慢分析代码打日志排查了!

  • 相关阅读:
    gradle阿里云镜像配置
    tomcat相关
    Oracle通过SQL语句查看table所引用的对象(View/Function/Procedure/Trigger)
    C# 调用NPOI 修改Excel 完成实时更新公式结果
    SpringBoot2.1.6 整合CXF 实现Webservice
    SpringBoot中FreeMarker创建
    git回滚到指定commit
    idea push reject:push mater to origin/master was rejected by remote
    python读取文件
    python获取当前文件路径以及父文件路径
  • 原文地址:https://www.cnblogs.com/zhaosq/p/13723428.html
Copyright © 2011-2022 走看看