Java序列化对象的一个使用案例-使用Http发送对象

2023-10-29

        《 Effective Java 》中序列化一节关于java的序列化存在如下说法:对象序列化(object serialization)API,它提供了一个框架,用来将对象编码成字节流(serializing),并从字节流编码中重新构建对象(deserializing)。一旦对象被序列化后,它的编码就可以从一台正在运行的jvm传到另一台jvm上,或者被存储在磁盘上,供以后反序列化时用(如tomcat的session的可持久化)。序列化技术为 远程通信 提供了标准的线路级对象表示法,也为JavaBeans组件结构提供了标准的 持久化 数据格式。

       关于java序列化,看过不少资料,正好最近在重读Effective Java,然后加上这两天碰到一个需求,能很好的诠释序列化,所以在这边小结下。

        需求:系统中自己写了个内存缓存cache,然后集群内每个节点都单独维护自己各自的内存缓存(ps:有人肯定该说艾斯比,怎么不用Memcached或者Redis,么法,leader的要求…… ),这个内存缓存其实就是基于Map的,key=String,value=Object对象。cache需要提供这样一个方法,要能够刷新集群内所有节点的map中单个KV。

        分析如上需求,map中value保存的是Object,这个Object并不是一般的String之类的,而恰恰就是一个真正名符其实的JavaBean对象,刷新时,需要将新的bean发送各节点,由各节点再各自操作内存中的map。这样,就出现了雏形,各节点需要提供一个http接口,刷新时,将bean对象发到到http上,这样就形成了上述Effective Java说到的场景,为远程通信 提供标准的线路级对象表示法,也即 将Object bean以stream的形式post到http接口,http接口接到stream后,将stream反序列化成bean对象。

       代码实现如下:

       javabean就不列了,是一个很纯粹的bean类,只不过该类一定是序列化后的(关于序列化的高级进阶请参考Effective Java),笔者这里只 implements Serializable 即可满足需求。

       java:HttpPost工具类

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;


/**
 * Http 请求访问工具类
 * 
 * @author will_awoke
 * @version 2014-6-26
 * @see HttpAccessUtil
 * @since
 */
public class HttpAccessUtil
{

  /**
   * 日志 
   */
  private static Logger log = Logger.getLogger(HttpAccessUtil.class);

   
  /**
   * 采取post方式提交序列化后的object对象 </br>
   * 另请参考:java.io.ObjectInputStream/ObjectOutputStream
   * @param requestUrl 请求地址
   * @param connTimeoutMills 设置连接主机超时,单位:毫秒
   * @param readTimeoutMills 设置从主机读取数据超时,单位:毫秒
   * @param serializedObject 序列化后的object对象
   * 
   * @return remoteHttp返回的结果
   */
  public static String httpPostSerialObject(String requestUrl, int connTimeoutMills,
                        int readTimeoutMills, Object serializedObject) throws Exception	 
  {
    HttpURLConnection httpUrlConn = null;
    InputStream inputStream = null;
    InputStreamReader inputStreamReader = null;
    BufferedReader bufferedReader = null;
    ObjectOutputStream oos = null;
    StringBuffer buffer = new StringBuffer();
    try
    {
      URL url = new URL(requestUrl);
      httpUrlConn = (HttpURLConnection)url.openConnection();
      // 设置content_type=SERIALIZED_OBJECT
      // 如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException
      httpUrlConn.setRequestProperty("Content-Type","application/x-java-serialized-object");
      httpUrlConn.setConnectTimeout(connTimeoutMills);
      httpUrlConn.setReadTimeout(readTimeoutMills);
      // 设置是否向httpUrlConn输出,因为是post请求,参数要放在http正文内,因此需要设为true, 默认情况下是false
      httpUrlConn.setDoOutput(true);
      // 设置是否从httpUrlConn读入,默认情况下是true
      httpUrlConn.setDoInput(true);
      // 不使用缓存   
      httpUrlConn.setUseCaches(false);

      // 设置请求方式,默认是GET
      httpUrlConn.setRequestMethod("POST");
      httpUrlConn.connect();

      if (serializedObject != null)
      {
        // 此处getOutputStream会隐含的进行connect,即:如同调用上面的connect()方法,   
        // 所以在开发中不调用上述的connect()也可以,不过建议最好显式调用
        // write object(impl Serializable) using ObjectOutputStream
        oos = new ObjectOutputStream(httpUrlConn.getOutputStream());
        oos.writeObject(serializedObject);
        oos.flush();
        // outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络, 
        // 而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。所以这里的close是必须的
        oos.close();
      }
      // 将返回的输入流转换成字符串
      // 无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去
      inputStream = httpUrlConn.getInputStream();//注意,实际发送请求的代码段就在这里 
      inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
      bufferedReader = new BufferedReader(inputStreamReader);

      String str = null;
      while ((str = bufferedReader.readLine()) != null)
      {
        buffer.append(str);
      }
    }
    catch (Exception e)
    {
      log.error(requestUrl + " error ", e);
      throw e;
    }
    finally
    {
      try
      {
        IOUtils.closeQuietly(bufferedReader);
        IOUtils.closeQuietly(inputStreamReader);
        IOUtils.closeQuietly(inputStream);
        IOUtils.closeQuietly(oos);
        if (httpUrlConn != null)
        {
          httpUrlConn.disconnect();
        }
      }
      catch (Exception e)
      {
        log.error(e);
      }
    }
    return buffer.toString();
  }


}



         这里有点要着重说明下,httpConnect的Content-Type的一定要设置为 application/x-java-serialized-object ,否则http接口处在接收stream的时候会出现java.io.EOFException 。另外:输出对象使用的是ObjectOutputStream的writeObject方法。
         http接口接收stream,并反序列化为Object bean即可:

//read object from stream 反序列化将stream生成Object对象
ObjectInputStream ois = new ObjectInputStream(req.getInputStream());//HttpServletRequest req对象
Object value = ois.readObject();

          后面就是replace map了,不再赘述。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java序列化对象的一个使用案例-使用Http发送对象 的相关文章

随机推荐

  • Python的datetime包中的strptime和strftime的理解辨析

    strptime与strftime的辨别 strptime 即 str parse 解析 time 理解成 parse string into time format 解析字符串成datetime格式 strftime 即 str form
  • 【1day】复现LiveBOS ShowImage.do 接口存在任意文件读取漏洞

    注 该文章来自作者日常学习笔记 请勿利用文章内的相关技术从事非法测试 如因此产生的一切不良后果与作者无关 目录 一 漏洞描述 二 影响版本 三 资产测绘 四 漏洞复现 一 漏洞描述 LiveBOS 简称LiveBOS 是
  • JDBC连接mysql数据库

    jdbc连接mysql数据库代码 package com study jdbctest import java sql Connection import java sql DriverManager import java sql Res
  • 你尚未连接--代理服务器可能有问题,或地址不正确。

    这种情况可能是你装了梯子之后 自动开启了代理服务器 解决方法 1 控制面板 gt 网络和Internet 2 网络和共享中心 gt internet选项 3 连接 gt 局域网设置 4 把代理服务器的沟沟取消 这样就解决了
  • Django model select获取数据详细讲解

    基本操作 获取所有数据 对应SQL select from User User objects all 匹配 对应SQL select from User where name Pala User objects filter name P
  • 越伟大的事物越不带个人因素

    很多事物都带上个人因素 例如带有某些人的印记 但是越伟大的事物越不带个人因素 因为这时个人因素对于事物的发展已经不重要了 例如一位伟大的君主建立的王朝 会带上他的个人印记 例如他定的国号等 并且他的个人喜好 观点会影响民众 他的个人魅力和魄
  • JavaScript数据结构之队列

    JavaScript 数据结构之队列思维导图 JavaScript 数据结构之队列源码
  • Mock&Mockito使用手册

    基础概念 mock 测试就是在测试过程中 对于某些不容易构造或者不容易获取的对象 用一个虚拟的对象来创建以便测试的测试方法 这个虚拟的对象就是mock对象 mock对象就是真实对象在调试期间的代替品 Mock 对象 模拟对象的概念就是我们想
  • 关于从平台借用数据集的想法

    大家都知道 深度学习算法需要大量的数据 但是获取有标记的数据太难了 往往要花费大量的精力 一些比赛平台往往会发布任务相关的数据集 但是这些数据集是储存在云端不可获取的 如果我们能够借用这些与我们任务相关的数据的话 可以帮我们节约很长的时间
  • template elasticsearch6备注

    install sh脚本 ES TEMPLATE DIR home xlj elasticsearch 6 2 3 config template event json if test f ES TEMPLATE DIR then echo
  • ESP32 之 ESP-IDF 教学(十)—— 电机控制器(MCPWM)

    本文章 来自原创专栏 ESP32教学专栏 基于ESP IDF 讲解如何使用 ESP IDF 构建 ESP32 程序 发布文章并会持续为已发布文章添加新内容 每篇文章都经过了精打细磨 通过下方对话框进入专栏目录页 CSDN 请求进入目录 O
  • 【满分】【华为OD机试真题2023 JS】找出通过车辆最多颜色

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 找出通过车辆最多颜色 知识点滑窗 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 在一个狭小的路口 每秒只能通过一辆车 假如车辆的颜色只有3种 找出N秒内经过的最
  • OSG第三方库编译之三十八:hdf5编译(Windows、Linux、Macos环境下编译)

    目录 1 hdf5介绍 2 hdf5下载 3 Windows下编译 4 Linux下编译 5 MacOS下编译 1 hdf5介绍 HDF5 Hierarchical Data Format 是一种跨平台传输的文件格式 存储图像和数据 HDF
  • android wifi信号显示,如何获得可用的wifi网络并将其显示在android中的列表中

    朋友们 我想找到所有可用的WiFi网络并将其显示在我尝试过的列表中 如下所示 但它不起作用 我已经编辑了我的代码 现在我得到了结果但是得到了我不需要的所有结果 我只需要列表中的wifi网络名称 public class MainActivi
  • leetcode402——Remove K Digits

    题目大意 字符串num代表一个非负整数 删除其中k位使得数字变得最小 输出不能出现前导零和空串 分析 单调栈 贪心 贪心策略 从左往右删 如果左邻居 gt 当前位 就应该删掉左邻居 这样才能使数字变最小 栈 遍历字符串 当前位小于栈顶元素时
  • java线程异常_java线程异常处理方法

    工作中常发现有些程序发生异常但却没有错误日志 原因就是一些开发线程异常处理错误 导致程序报错但异常信息打印到堆栈上 不好在生产环境中定位问题 在java多线程程序中 所有线程都不允许抛出未捕获的checked exception 比如sle
  • bios无法识别usb键盘问题解决备忘

    戴尔的T3600工作站bios中无法使用usb键盘 参考 USB 3 0 和 USB 2 0 在 Precision T3600 T5600 或 T7600 系统上出现故障 Dell 中国https www dell com support
  • 禁止ubuntu系统弹出报错界面

    永远禁用掉Apport这一特性 可以远离在每次重启时出现错误提示的纷扰 编辑apport文件 etc default apport sudonano etc default apport 找到 enabled 1 这一行 并改变到0 zer
  • 什么是MES生产制造执行系统?实施系统有哪些好处?

    制造企业关心三个问题 生产什么 生产多少 如何生产 企业的生产计划回答了前两个问题 如何生产 由生产现场的过程控制系统SFC 掌握 ERP CRM等系统只为生产计划的编制提供数据信息 APS系统是提供详细的生产计划 为了使 计划 到达 生产
  • Java序列化对象的一个使用案例-使用Http发送对象

    Effective Java 中序列化一节关于java的序列化存在如下说法 对象序列化 object serialization API 它提供了一个框架 用来将对象编码成字节流 serializing 并从字节流编码中重新构建对象 des