移动终端和 Java 服务端数据传输封装类
移动互联时代,常常碰到的是移动终端和服务端数据交互。终端把某种形式的数据传递给服务端,服务端收到数据后,需要根据双方约定的数据格式,取值再做处理。
传递的数据有哪些形式?一般分成三种形式
1:JSON 的流形式
2:纯粹的键值对形式
3:键值对和文件流并存的形式
其实 2-3 可以合并成一种形式来处理,以下将以 Java 服务端情况说明一下,因为终端每次传递数据给服务端,都需要把数据转成约定好的数据结构,每次收到请求都用到,干脆封装了一个独立的工具类,Servlet 控制层把 HttpServletRequest 传递给封装好的方法,方法再解析成 JSON 字符串给逻辑层,(Java 有 fastJSON,jackSON 工具类在,很爽)逻辑层再按需取数据处理等等。
终端给服务端传递采用 POST 的方式,根据 HttpServletRequest 的 ContentType 区分终端 POST 过来什么形式的数据,比如 :
1:application/x-www-form-urlencoded 就是纯粹的键值对
2:multipart/form-data 就是键值对和文件流并存
3:application/json 就是 JSON 流
实际项目中,传递数据形式我们更倾向 JSON 流,但如果终端除了传递数据,还会有图片、文件的时候,JSON 流数据形式,怎么处理呢?这个问题当初自己也很纠结,当时就觉得第二种方式比较好,但本人并不喜欢混杂用,接口既接收 JSON 流,又接收 键值对和文件流,显然很混乱;让终端开发的兄弟无所适从,所以后来想到了一个办法, 使用 JSON 的某个值承载文件的字节数组,问题得到解决了。
比如以下的 JSON :
{"name":"photo1.jpg","file":file}
其中 file 是一个字节数组,把一个文件转成字节数组,Java 如:
byte[] file = FileUtil.file2Bytes("/home/path/photo1.jpg");
传递的数据有哪些形式?一般分成三种形式
1:JSON 的流形式
2:纯粹的键值对形式
3:键值对和文件流并存的形式
其实 2-3 可以合并成一种形式来处理,以下将以 Java 服务端情况说明一下,因为终端每次传递数据给服务端,都需要把数据转成约定好的数据结构,每次收到请求都用到,干脆封装了一个独立的工具类,Servlet 控制层把 HttpServletRequest 传递给封装好的方法,方法再解析成 JSON 字符串给逻辑层,(Java 有 fastJSON,jackSON 工具类在,很爽)逻辑层再按需取数据处理等等。
Java 代码:
import java.io.BufferedReader; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.lang3.StringUtils; import com.alibaba.fastjson.JSONObject; public class RequestUtil { /** * 把 request 参数转成 JSON 字符串格式的参数 * * @param request * @return */ public static String getReqJSON(HttpServletRequest request) { String contectType = StringUtils.isBlank(request.getContentType()) ? "": request.getContentType().toLowerCase(); if (StringUtils.contains(contectType, "application/x-www-form-urlencoded")) { return form2JSON(request); } else if (StringUtils.contains(contectType, "multipart/form-data")) { return formData2JSON(request); } else if (StringUtils.contains(contectType, "multipart/json")) { return stream2Json(request); } else { return formData2JSON(request); } } /** * 只传递 JSON 流的时候,把它们转成 JSON 字符串 * * @param request * @return */ private static String stream2Json(HttpServletRequest request) { try { StringBuilder sb = new StringBuilder(); InputStream is = request.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); String line; while (null != (line = reader.readLine())) { sb.append(line); } reader.close(); is.close(); return sb.toString(); } catch(Exception e) { e.printStackTrace(); return ""; } } /** * 只传递键值对的时候,把它们转成 JSON 字符串 * * @param request * @return */ private static String form2JSON(HttpServletRequest request) { JSONObject obj = new JSONObject(); Map < String, String[] > map = request.getParameterMap(); Iterator < String > itReq = map.keySet().iterator(); while (itReq.hasNext()) { String key = itReq.next(); String val = map.get(key).length > 0 ? map.get(key)[0] : ""; obj.put(key, val); } return obj.toJSONString(); } /** * 同时传递键值对和文件流的时候,把它们转成 JSON 字符串 * * @param request * @return */ private static String formData2JSON(HttpServletRequest request) { // 键值参数和文件字节流方式 try { JSONObject obj = new JSONObject(); DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory);@SuppressWarnings("unchecked") List < FileItem > items = upload.parseRequest(request); // 解析request请求 if (!items.isEmpty()) { Iterator < FileItem > iter = items.iterator(); while (iter.hasNext()) { FileItem item = iter.next(); if (item.isFormField()) { // 如果是表单域 ,就是非文件上传元素 String name = item.getFieldName(); // 获取name属性的值 String value = item.getString(); // 获取value属性的值 obj.put(name, value); } else { String fieldName = item.getFieldName(); // 文件域中name属性的值 String fileName = item.getName(); // 文件的全路径,绝对路径名加文件名 if (fileName != "" && fileName != null) { String tempPath = request.getServletContext().getRealPath("") + File.separator + "temp" + File.separator; File savefolder = new File(tempPath); if (!savefolder.exists()) { savefolder.mkdirs(); } File saveFile = new File(tempPath + fileName); // 定义一个file指向一个具体的文件 item.write(saveFile); // 把上传的内容写到一个文件中 obj.put(fieldName, tempPath + fileName); } } } items.clear(); } return obj.toJSONString(); } catch(Exception e) { e.printStackTrace(); return ""; } } }
终端给服务端传递采用 POST 的方式,根据 HttpServletRequest 的 ContentType 区分终端 POST 过来什么形式的数据,比如 :
1:application/x-www-form-urlencoded 就是纯粹的键值对
2:multipart/form-data 就是键值对和文件流并存
3:application/json 就是 JSON 流
实际项目中,传递数据形式我们更倾向 JSON 流,但如果终端除了传递数据,还会有图片、文件的时候,JSON 流数据形式,怎么处理呢?这个问题当初自己也很纠结,当时就觉得第二种方式比较好,但本人并不喜欢混杂用,接口既接收 JSON 流,又接收 键值对和文件流,显然很混乱;让终端开发的兄弟无所适从,所以后来想到了一个办法, 使用 JSON 的某个值承载文件的字节数组,问题得到解决了。
比如以下的 JSON :
{"name":"photo1.jpg","file":file}
其中 file 是一个字节数组,把一个文件转成字节数组,Java 如:
byte[] file = FileUtil.file2Bytes("/home/path/photo1.jpg");
iOS 也会有相应的办法,把文件转成字节数组,代码就不贴出来了。
(完)
哇~~~ 竟然还没有评论!