问题现象
问题源自于使用tiger进行图查询时,要用到一个get请求,参数是复杂的json字符串,含有空格,逻辑运算符等若干字符。
当服务器端接收时,总是无法正常解析。
神奇的是使用httpclient原生的方式没有这个问题,使用postman也没问题。但是使用spring的restTemplate就偏偏有这问题。
反复调试也没有完全搞清楚。困扰了两三天。
具体问题
下面便是我要传入的json字符串:
http://192.168.1.101:9000/query/work_graph/graphKExpand?gdbQuery={"debug":true,"direction":"ANY","edgeTables":["all_to_skill","company_person"],"endVertices":[{"objectKey":"p2","schema":"persons"},{"objectKey":"222222222222222222","schema":"company"}],"filterExpression":"((t.type=="company" AND (t.city=="sayan" OR t.city=="dongguan")) OR (e.type=="all_to_skill" AND ((e.quadrant>1 AND e.quadrant<=800) OR (e.quadrant>=1000 AND e.quadrant<=3000))) OR ((t.type=="persons" AND (t.quadrant=="4" OR t.quadrant=="5")) AND (t.type=="persons" AND (t.quadrant=="10" OR t.quadrant=="20"))))","graph":"work_graph","internalOption":{"debug":true},"maxDepth":10,"maxSize":100,"offset":44,"size":100,"startVertices":[{"objectKey":"c4","schema":"company"},{"objectKey":"p3","schema":"persons"},{"objectKey":"c1","schema":"company"}],"type":"K_EXPAND","vertexTables":["persons","skill","company"]}
展开后的json是这样的:
{ "debug": true, "direction": "ANY", "edgeTables": [ "all_to_skill", "company_person" ], "endVertices": [ { "objectKey": "p2", "schema": "persons" }, { "objectKey": "222222222222222222", "schema": "company" } ], "filterExpression": "t.type=="company" AND (t.city=="sayan" OR t.city=="dongguan"", "graph": "work_graph", "internalOption": { "debug": true }, "maxDepth": 10, "maxSize": 100, "offset": 44, "size": 100, "startVertices": [ { "objectKey": "c4", "schema": "company" }, { "objectKey": "p3", "schema": "persons" }, { "objectKey": "c1", "schema": "company" } ], "type": "K_EXPAND", "vertexTables": [ "persons", "skill", "company" ] }
测试用例:
import org.junit.Test; import java.net.URLDecoder; import java.net.URLEncoder; /** * Created by HaiyangHome on 2019/3/23. */ public class UrlEncodeTest { /** * urlencode转码不能随便用,因为她会把空格转换成+号,而不是标准的%20字符 * 所以urlencode只适用于服务端支持的协议是RFC1738 * 如果服务端只支持RFC 2396标准,那么服务端解码时,会把加号+当成保留字符,而不转码 * */ @Test public void test()throws Exception{ String charset = "UTF-8"; String str = "aabb ccddfff++++111"; System.out.println(URLEncoder.encode(str, charset)); String decodeStr = "aabb+ccddfff%2B%2B%2B%2B111"; System.out.println(URLDecoder.decode(decodeStr, charset)); String decodeStr2 = "aabb%20ccddfff%2B%2B%2B%2B111"; System.out.println(URLDecoder.decode(decodeStr, charset)); } }
结论
根本原因是urlencode这个工具类不太完善。它在转码时不时按照最新的转码标准实现。
具体原因:
urlencode转码不能随便用,因为她会把空格转换成+号,而不是标准的%20字符
所以urlencode只适用于服务端支持的协议是RFC1738
如果服务端只支持RFC 2396标准,那么服务端解码时,会把加号+当成保留字符,而不转码。这会导致数据破坏,程序bug。