PHP、JAVA关于post请求数据接收的处理

背景

最近在做项目时遇到这样一个问题,一个客户公司的智能柜管理系统想集成我们公司开发的电子锁系统,我负责相关接口的对接及开发,在一切准备工作就绪之后,进行接口联调时遇到传参问题的困扰。对方系统是采用PHP语言开发,我方系统是采用JAVA语言开发,接口约定采用post请求方式,以json格式传输数据,但是在实际接口联调中,PHP端使用curl请求JAVA接口时的传参JAVA端接口始终无法获取到,对方经过检查json数据格式没问题,但是我采用ajax请求JAVA端接口时可以获取到参数,于是推断是不同语言传输和接受参数的方式问题!

分析

JAVA接受post请求数据方式

Java的servlet中接收Post请求数据主要采用两种方式:

(1) request.getParameter();
(2) request.getInputStream();

Content-Type仅在取值为application/x-www-data-urlencoded和multipart/form-data两种情况下,request.getParameter()才能获取到值,否则返回空。Content-Type为其他类型时,一般采用request.getInputStream()方式获取,如下:

1
2
String json = org.apache.commons.io.IOUtils.toString(request.getInputStream());
System.out.println(json);

于是改用request.getInputStream()方式,问题得到解决,该方式返回request请求内容的字节流,转为字符串之后对取到的值进行处理,如果需要改变请求参数的值或者改变获取参数的方式满足Controller层的需求,可以通过使用HttpServletRequestWrapper重写Request请求参数来达到目的。

request的Content-Type小结

application/x- www-form-urlencoded是Post请求默认的请求体内容类型,也是form表单默认的类型。Servlet API规范中对该类型的请求内容提供了request.getParameter()方法来获取请求参数值。但当请求内容不是该类型时,需要调用request.getInputStream()或request.getReader()方法来获取请求内容值。
当请求体内容(注意:get请求没有请求体)类型是application/x- www-form-urlencoded时也可以直接调用request.getInputStream()或request.getReader()方法获取到请求内容再解析出具体都参数,但前提是还没调用request.getParameter()方法。此时当request.getInputStream()或request.getReader()获取到请求内容后,无法再调request.getParameter()获取请求内容。即对该类型的请求,三个方法互斥,只能调其中一个。今天遇到一个Controller请求经过Spring MVC 的RequestMapping处理后,只能通过request.getParameter()获取到参数、无法通过request.getInputStream()和request.getReader()读取内容很可能就是因为在请求经过Spring MVC时已调用过request.getParameter()方法的原因。

注意:在一个请求链中,请求对象被前面对象方法中调用request.getInputStream()或request.getReader()获取过内容后,后面的对象方法里再调用这两个方法也无法获取到客户端请求的内容,但是调用request.getParameter()方法获取过内容后,后面的对象方法里依然可以调用它获取到参数的内容。

当请求体内容是其它类型时,比如 multipart/form-data或application/json时,无法通过request.getParameter()获取到请求内容,此时只能通过request.getInputStream()和request.getReader()方法获取请求内容,此时调用request.getParameter()也不会影响第一次调用request.getInputStream()或request.getReader()获取到请求内容。request.getInputStream()返回请求内容字节流,多用于文件上传,request.getReader()是对前者返回内容的封装,可以让调用者更方便字符内容的处理(不用自己先获取字节流再做字符流的转换操作)。

普及PHP知识

PHP接收post请求数据方式

PHP接收post请求数据主要采用两种方式:

(1) $_POST[index]方式
(2) $data = file_get_contents(“php://input”);

Content-Type仅在取值为application/x-www-data-urlencoded和multipart/form-data两种情况下,PHP才会将http请求数据包中相应的数据填入全局变量POST。因此,如果使用_POST。因此,如果使用_POST来获取post过来的数据时,需要注意Content-Type类型,如果不是application/x-www-data-urlencoded和multipart/form-data,则采用file_get_contents(“php://input”);进行获取。
php://input 可以读取http entity body中指定长度的值,由Content-Length指定长度,不管是POST方式或者GET方法提交过来的数据。但是,一般GET方法提交数据 时,http request entity body部分都为空。例如在传递json串的时候,通过file_get_contents(“php://input”);获取原始串,然后通过json_decode()进行解析。