Java 如何处理 WebService/Restful 返回的数据
WebService/Restful返回的XML/Json属于多层数据,解析难度低,但计算难度高。传统方法是先用Dom4J/JsonPath之类的开源类库去解析,再用XPath/JsonPath计算,这种方法结构轻便好集成,但只能进行条件查询,其他计算都要硬编码。如果对计算要求高,也可以将数据先存到SQLite/MySQL之类的小型数据库,再用特殊的XML/Json函数进行解析,同时用常规SQL进行计算,但这种方法架构复杂,入库过程繁琐,耽误时间长,而且SQL只擅长计算结构化记录,计算多层数据的能力要差许多。
更好的方法是用开源类库集算器SPL,既有轻便的集成架构,能直接解析WebService/Restful返回的数据,又有丰富的计算函数,具备针对多层数据的强大计算能力。
SPL提供了JDBC接口,架构简单容易学习。比如JAVA主程序接收了来自Restful的Json串,集成SPL后,可用下面的代码解析成ResultSet以进一步处理:
… String jsonStr=… //Json串 Class.forName("com.esproc.jdbc.InternalDriver"); Connection connection =DriverManager.getConnection("jdbc:esproc:local://"); Statement statement = connection.createStatement(); String query="=json($["+jsonStr+"])"; ResultSet result = statement.executeQuery(query); …
事实上,SPL内置了多层结构的数据对象,能同时计算和生成json/XML,特别适合处理来自WebService/Restful的数据,毕竟解析不是目标,计算处理才是。比如,restful返回的Json有两层,上层是多条员工记录,每条员工记录的Orders字段是多条订单记录。解析Json并对所有订单进行条件查询,计算结果也转成json串,只需下面的SPL代码:
=json(json($["+jsonStr+"]).conj(Orders).select((Amount>1000 && Amount<=2000) && like@c(Client,"*business*")))
这里以json为例,XML也可以类似处理。
SPL还提供了简单易用的接收函数,可以直接从WebService/Restful获取数据,避免JAVA主代码里复杂的接收过程,减少第三方类库的使用,使集成架构更轻便。比如,用SPL接收restful返回的数据,再进行条件查询,并将结果再生成json返回:
=json(json(httpfile("http://127.0.0.1:6868/api/getData").read()).conj(Orders). select((Amount>1000 && Amount<=2000) && like@c(Client,"*business*")))
SPL也能访问有权限控制的服务器,详情可以参考相关文档,这里不细说了。
SPL支持算法外置,适合代码较长或频繁修改的计算,可显著降低耦合性。比如前面的条件查询可以先存为脚本文件:
A | B | |
1 | =json(parameter_jsonStr) | /多层json |
2 | =A1.conj(Orders) | /合并订单 |
3 | =A2.select((Amount>1000 && Amount<=2000) && like@c(Client,"*business*")) | /条件查询 |
4 | return json(A3) |
再在JDBC中以存储过程的形式调用脚本文件:
… String jsonStr=… //Json串 Class.forName("com.esproc.jdbc.InternalDriver"); Connection conn =DriverManager.getConnection("jdbc:esproc:local://"); CallableStatement statement = conn.prepareCall("{call getQuery(?)}"); statement.setObject(1, jsonStr); ResultSet result statement.execute(); result.next(); String jsonResult=result.getString(1); …
SPL提供了通用的计算语法,从不同来源取得的数据,可以用相同的语法进行计算。比如对来自WebService的员工-订单进行条件查询,计算结果以XML形式返回,XPath/JsonPath互不通用,SQLite只支持Json不支持XML计算,而SPL就可以用同样的计算语法:
A | B | |
1 | =ws_call(ws_client("http://.../entityWS.asmx?wsdl"),"entityWS ":" entityWSSoap":"getData") | /接收WebService |
2 | =A1.conj(Orders) | /合并订单 |
3 | =A2.select((Amount>1000 && Amount<=2000) && like@c(Client,"*business*")) | /条件查询 |
4 | return xml(A3) | /转为XML |
SPL支持数据库/各类NoSQL/CSV/Excel/Json文件/XML文件等多种数据源,可以用相同的语法计算这些数据源,这里就不展开说了。
SPL具有丰富的计算函数,提供了不低于SQL的计算能力,下面再几例:
A | B | |
1 | … | /解析多层数据 |
2 | =A1.conj(Orders).groups(Client;sum(Amount)) | /分组汇总 |
3 | =A1.groups(State,Gender;avg(Salary),count(1)) | /多字段分组汇总 |
4 | =A1.sort(Salary) | /排序 |
5 | =A1.id(State) | /去重 |
6 | =A1.new(Name,Gender,Dept,Orders.OrderID,Orders.Client,Orders.Client,Orders.SellerId,Orders.Amount,Orders.OrderDate) | /关联 |
SPL具有灵活的计算语法,可以大幅简化复杂的运算逻辑。很多计算SQL或存储过程都很难实现,而SPL解决起来就很轻松。比如,找出销售额累计占到一半的前n个大客户,并按销售额从大到小排序:
A | B | |
1 | … | /解析数据 |
2 | =A1.sort(amount:-1) | /销售额逆序排序 |
3 | =A2.cumulate(amount) | /计算累计序列 |
4 | =A3.m(-1)/2 | /最后的累计即总额 |
5 | =A3.pselect(~>=A4) | /超过一半的位置 |
6 | =A2(to(A5)) | /按位置取值 |
SPL提供了专业的IDE,不仅具备完整的调试功能,还能以表格的形式观察每一步的计算结果,可以进一步提高复杂运算逻辑的开发效率。
不难看出,SPL集成架构简单轻便,内置多层结构的数据对象,提供了丰富的函数和灵活的语法,特别适合处理WebService和Restful返回的数据。