python html 展示json html转json python_htmlunit 接收json数据


一、介绍

首先说一下为什么需要让数据在Html Java Python之间流通。

前端Html使用的thymeleaf[1]模板,Java用Spring Boot[2],Python采用FastAPI[3]框架。

目前有一个数据分析的功能,要求从html前端接受数据,后台进行处理。但是Java直接做数据分析是不太方便的,所以这里想接入Python来做。

接入Python调查到有两种方式,但是都有其局限性,[4][5]

  1. Java调用Python脚本。直接写好Python脚本,然后用Java执行该脚本。参数以args的形式传给python脚本,用python用print来返回数据。但是该方法对参数的传输不太友好,功能很局限。无法传输复杂的数据类型。
  2. 通过Jython。Jython是Python用Java的实现,所以可以很自然的用Java调Jython。但是Jython对第三方模块支持很少,无法满足这里需要用到的数据分析第三方模块。

由于这些局限性,所以上面这两种方式都被否定。采用了以下方式:

  1. 前端Html传一个form表单数据,发送请求到Java。
  2. Spring框架的Controller对该数据进行封装,整理成json,发送请求到Python服务。
  3. Python中的服务接受该json数据,对json进行解析得到结果。
  4. 结果再交由数据分析的功能模块进行处理。
  5. 处理后将最终结果组装成json返回给Spring。
  6. Spring再将结果放到Model中返回给Html。

后面就从代码上描述如何完成以上步骤。

二、Html提交form

定义了两个input框,用来输入字符串数据。

为form设定post请求,发送给 Spring的 /data 服务。

代码和结果图如下


<


python html 展示json html转json python_java接收json数据_02

html界面图


当点击了Submit按钮,两个input框中的数据就会传输到Controller。


python html 展示json html转json python_controller接收json数据_03

F12 Network查看数据传输

三、Spring Controller接受并转发给Python

1. Controller接受数据

Controller设定好RequestMapping("/data"),直接在形参列表中加入 List<String> coordinates即可,数据会自动封装到coordinates中,接收该数据很轻松。

2. 传递Json

已经获取到了List<String> coordinates对象,要把该对象封装好,以合适的形式发送给Python。

显然,不同服务之间传输数据的最好方式是将数据转成Json传输。

这里采用Jackon工具类将对象转换成json,使用writeValueAsString方法将对象转成String,极其简单。


ObjectMapper objectMapper = new ObjectMapper();
String paramString = objectMapper.writeValueAsString(任意对象);


这里先将coordinates装载到Map中,然后转换成Json字符串。


MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
paramMap.add("coordinates",coordinates);
System.out.println(paramMap);
String paramString = objectMapper.writeValueAsString(paramMap);


这里有一个MultiValueMap,我理解的是,HashMap的key value,本来是一一对应的,但是这里使用MultiValue,就使得一个key可以对应多个value,多个value组成一个数组(Java)或者列表(Python)。网上有提到一个错误,我暂时没有遇到,但还是记录下来。[6]

3. 使用RestTemplate发送请求

RestTemplate是Spring提供的一个可以访问其他服务(url)的一个类,更专业的解释在官方文档[7]。简而言之就是,通过该类,可以给其他服务发送请求。

单独使用起来也非常简单,如下代码:


RestTemplate


运行该代码,可以得到如下输出


python html 展示json html转json python_htmlunit 接收json数据_04


该类提供了很多方法,其中就包括传递参数的post方法。


public


只需使用该方法,就可以传递参数给python服务器。


String content = restTemplate.postForObject(pythonServerUrl+"/data",paramString,String.class);


在content中,就是python返回的结果。

使用Model将结果保存,就可以返回给前端。

4. 完整代码


@RequestMapping("/data")
    public String dataToPython(@RequestParam("coordinate") List<String> coordinates) throws JsonProcessingException {
        System.out.println(coordinates.get(0));
        System.out.println(coordinates.get(0).length());
//        HashMap<String,Object> paramMap = new HashMap<>();
//        paramMap.put("coordinates",coordinates);
        MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
        paramMap.add("coordinates",coordinates);
        System.out.println(paramMap);
        String paramString = objectMapper.writeValueAsString(paramMap);
        String content = restTemplate.postForObject(pythonServerUrl+"/data",paramString,String.class);
        System.out.println("返回值为: "+content);
        return "redirect:/";
    }


四、python接受数据并返回结果

Python部分,使用FastAPI搭建一个微服务非常简单,参考这个文章[8]

贴出我的代码,再给出解释。


from


一开始引入了几个包,FastAPI是python web框架,包含了一些基本路由的功能。

BaseModel用来接收上游传过来的参数。PointList继承了该类,就可以在服务中接受并自动装载参数。

在PointList类中,使用了一个List,是用来接收数组。因为上游传过来的是List。

@app.post("data")相当于Spring中的RequestMapping功能。

data函数形参列表中的x就可以接受到上游的参数,函数体中用print输出x可以看到结果,然后return一个字符串就返回结果给Java。

uvicorn是一个微型服务器,类似于Tomcat,可以设置需要启动的服务,host,port等参数。

五、总结

先展示整套流程的结果图。


python html 展示json html转json python_java接收json数据_05


然后总结一下在该数据传递过程中需要用的技术。


python html 展示json html转json python_java接收json数据_06


  • Html
  • thymeleaf
  • form发送请求
  • Java
  • Spring Boot
  • Controller接收参数
  • MultiValueMap包装数据
  • Jackson工具类转json
  • RestTemplate发请求
  • Python
  • FastAPI
  • BaseModel接收参数
  • uvicorn

改进方向

目前是手写了一个请求转发,后续看有没有什么中间件,rpc,微服务的东西能用的。以便更好的扩展。

参考

  1. ^Thymeleaf官网 https://www.thymeleaf.org/documentation.html
  2. ^Spring Boot官网 https://spring.io/projects/spring-boot
  3. ^FastAPI官网 https://fastapi.tiangolo.com/
  4. ^Java调用python 
  5. ^Java调用python 
  6. ^为什么用MultiValueMap代替HashMap 
  7. ^Spring RestTemplate官方文档 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html
  8. ^Python迅速搭建http接口服务