【问题标题】:Storing java objects in server memory在服务器内存中存储 java 对象
【发布时间】:2009-11-25 02:41:30
【问题描述】:

我有一个处理多个对象的 java web 项目(同样包含 n 个 A 类型的对象(例如时间和值)和 m 个 B 类型的对象(例如时间和字符串数组))。 Web 项目本身包含几个用于可视化的 servlet/jsps 以及一些用于数据操作的逻辑,目前在 Apache Tomcat 上运行。

是否可以在服务器运行时将整个数据存储在服务器(或大部分时间:本地)内存中?如果 Tomcat 关闭,数据可以存储在一个简单的文件中,没有限制。在服务器启动时,我只想读入文件并将对象写入内存。如何启动 Tomcat 来执行此操作?

我不想使用额外数据库的原因是,我想提供一个包含 tomcat 的 zip 文件,其中包括已部署的 *.war 文件(因为我不希望我的教授被 tomcat 服务器设置卡住等等)

谢谢,克里斯

【问题讨论】:

    标签: java memory tomcat


    【解决方案1】:

    您可以实现ServletContextListener 并在contextInitialized()contextDestroyed() 方法中编写从文件加载和保存到文件的逻辑,这两个方法分别在webapp 的启动和关闭期间调用。

    你可以读写对象到磁盘,但是它们都需要先实现java.io.Serializable。这是带有代码示例的Serialization tutorial

    也就是说,您是否考虑过使用 嵌入式 数据库,这样您就不需要安装数据库服务器了?您可以为此使用 JDK6 的内置 JavaDB 或其竞争对手 HSQLDB。或者,如果它是纯键值对,那么您也可以为此使用java.util.Properties API (tutorial here)。只需将属性文件放在类路径中的某个位置并使用ClassLoader#getResourceAsStream() 来获取它的InputStream,或者将它放在WEB-INF 的某个位置并使用ServletContext#getResourceAsStream()

    【讨论】:

    • 这听起来不错。是否可以在服务器启动时(或类似的东西)而不是在第一个 servlet 调用时运行从文件加载逻辑?
    • 当然,您可以为此使用ServletContextListener。您只需要相应地实现该接口并在webapp的web.xml中将其注册为<listener>
    • 此外,如果您通过event.getServletContext().setAttribute("data", data) 将数据放在应用程序范围内,那么您可以通过getServletContext().getAttribute("data") 在servlet 中通过${data} 在JSP 中访问它。
    • 啊,完美。我想我现在可以使一切正常工作。特别是对于 JSP,这是访问数据的好方法!谢谢。
    【解决方案2】:

    我认为HSQLDB 正是您所需要的,它是一个小型数据库服务器,也是原生嵌入在 Apache Tomcat 中的。它将数据存储在内存中,还允许从文件中写入和读取内容。

    【讨论】:

    • 当然我假设您在谈论数据库对象,如果您在谈论没有任何映射到数据库的普通 Java 对象,您应该考虑序列化。
    • 如果没有必要,我不想“搞乱”数据库对象,只使用普通的 java 对象。
    • 所以序列化是最好的方法,你只需将对象写入文件然后返回。然而这种解决方案对于一个小问题(比如你的)是可以的,但是序列化并不像使用内存数据库那么简单,必须小心处理!
    • 好的,谢谢 :) 但如果我得到太多数据,我可能还得考虑嵌入式数据库(正如 BalusC 所说)。
    • 实际上拥有一个嵌入式数据库更简单、更安全:您只需进行查询,一切都由数据库处理。此外,如果您将 Java 对象映射到表(有许多框架允许您这样做),您真的不必关心任何事情。我建议您使用 DB 方法,但由于它需要更多的技术背景,我可以理解它可能很可怕 :)
    【解决方案3】:

    如果应用意外关闭,您将丢失所有数据,因为它没有时间将其写入磁盘。

    您可以使用 SQLite/derby/hsql 等数据库,将数据存储到文件系统中。

    如果您不想弄乱数据库,那么您可以将所有内容存储在内存中,并在每次修改时将其刷新到磁盘。这里有几个提示:

    • 序列化可以使这非常容易。让你的所有对象都实现 Serializable,并给它们一个序列版本 id
    • 在以下情况下使用 BufferedOutputStream 写入磁盘,这比直接 FileOutputStream 快
    • 不要直接覆盖旧数据文件!写入一个新文件,完成写入后,将完成的文件移动到旧文件的顶部。这样,如果服务器在您写入数据文件的过程中关闭,您仍然拥有之前写入的好文件。
    • 您应该在写入数据时获取数据的读锁。任何其他修改数据的代码都应该在数据上获得写入锁。

    【讨论】:

    • 我建议将旧文件复制到备份位置,然后重命名新写入的文件以提高安全性。 (您可以通过这种方式保留多个备份。)但我自己会选择数据库解决方案......
    【解决方案4】:

    如果您不关心您的应用程序可能会在您的数据文件上乱涂乱画,您的 Tomcat / JVM 可能会崩溃,或者您的机器可能会丢失所有内存中的对象而死机,那么按照您的建议管理持久性是一种选项。但是您将拥有相当多的基础设施来构建、测试和维护。而且您会错过大多数 RDBM 提供的“增值”工具;备份、查询工具、优化器、复制等。

    但是,如果您无法选择灾难性的数据丢失,您应该使用 RDBM、ODBM 等任何方式来实现持久性。

    【讨论】:

      猜你喜欢
      • 2016-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-21
      • 2021-12-04
      • 1970-01-01
      • 2011-07-04
      • 1970-01-01
      相关资源
      最近更新 更多