如何从EJB 3访问文件系统?

26

我想知道如何从EJB 3 bean中访问文件系统?

我在互联网上搜索了相关内容,但没有找到好的答案。

有些人建议使用java.io/java.nio,尽管规范禁止这种用法。大多数应用服务器似乎仍允许访问此API。

另一个想法是使用JCA连接器来访问文件系统或LDAP目录。

我想要做的是避免在数据库中使用BLOB,而是使用简单的文件作为更好的性能和资源利用解决方案。

您会如何解决这个问题?


1
你不必在数据库中使用BLOB。SQL Server 2008支持filestream存储,它将文件转储到DB服务器上的文件夹中,但通过数据库公开它。http://blogs.msdn.com/rdoherty/archive/2007/10/12/getting-traction-with-sql-server-2008-filestream.aspx - pjp
4个回答

10

如果您知道您永远不会对应用程序进行集群化(或者您将能够将驱动器映射到网络),那么只需使用java.io.*。

请确保引入适当的配置,关于文件存储的根位置。


+1 这个答案只是“常识”。如果文件被另一个程序(不符合 EJB)填充,那么没有比这更快速和“清晰”的方法了。 - ATorras
3
如果编写的应用程序不遵循Java EE规范,您无法确保它具有可移植性和可维护性。例如,在12个月后,您可能已经离开了这个项目,而给负责集群化您的应用程序或将其移植到不同容器的人留下了一个难题。 - oxbow_lakes
8
"如果你知道你永远不会对你的应用程序进行群集化" - 如果你觉得自己能预测未来,那么你可能认为赌博行业会有更具吸引力的职业机会。 - oxbow_lakes
1
+1 我认为这取决于需求。顺便说一下,我已经发送了很多份简历 ;) - ATorras
9
“@oxbow_lakes 设计未来你今天或明天不需要的东西也是一种糟糕的做法。我见过有些人完全过于复杂化他们的设计,以便在“未来具备灵活性”,但所有这些所谓的灵活性在使用10年后从未被使用过。这段时间里,它确实使各种任务变慢了。像往常一样,要运用常识。” - Mike Braun
2
经常情况下,这些复杂的现在为未来设计的技术最终可能并不适合未来的需求,并且最终被废弃,转而采用全新的重写方式。 - le3th4x0rbot

10

在EJB中,您被禁止访问文件系统的原因是您无法控制应用程序在(Java EE)容器中的运行方式。例如,您的应用程序可能在服务器群集上运行,在这种情况下,将某个对象保存到一个服务器的目录中可能没有什么用处。当然,您可能有网络文件系统,因此该限制可能不适用。

一种选择是使用您的Container附带的实现。你可能可以在某个JNDI位置保存一个原始的byte[]数组,所以你总是可以保存序列化形式的对象:

ByteArrayOutputStream baos= new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(myObj);

//Now save into JNDI
new InitialContext().bind("path/to/myobject", baos.toByteArray());

这个后面可以查找并重新转换为你的对象:

byte[] bs = (byte[]) new InitialContext().lookup("path/to/myobject");
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bs));
MyObj myObj = (MyObj) ois.readObject();

或者您可以使用java.beans持久化XML(即XMLDecoderXMLEncoder)将实例编码为XML字符串,并将其保存到JNDI中。


这是从EJB编写文件的推荐方式吗?文件将对集群中的每个节点都可用(我认为JNDI确实是集群化的,所以可能是)?最后一次读取(或写入)JNDI是否具有事务性? - Mike Argyriou
你已被禁止 - 你不再被禁止访问文件系统,而且从来没有打算仅适用于EJB规范。当时写这个规定的人认为EJB将成为Java EE的基础,因此几乎等同于Java EE。 - dexter meyers

5

封装文件数据的访问。然后您可以使用上述任何方法。甚至使用数据库。测量系统的性能。如果符合要求,则完成。如果不符合要求,则文件访问仅限于一个地方,您可以替换为其他解决方案。同样的好处,如果软件必须移植到另一个容器和/或由其他人维护。


1

普通文件访问本质上不具备事务性。除非您构建支持事务操作的支持(我对如何做这个工作一无所知 - 这是资源管理器的工作),否则您将不得不担心正在执行的操作的事务语义。如果您确实构建了事务支持,那么您在性能方面几乎没有获得任何好处(数据库中性能损失的一部分是由于资源管理器执行的所有簿记)。

不要忘记事务管理的近亲 - 并发。除非您为每个请求编写一个新文件,否则并发问题或多或少会困扰您。

您将在Sun Blueprint's FAQ on EJB restrictions中找到更多信息。

除非您有充分的技术理由,否则不应尝试从EJB访问文件系统。一个很好的例子是日志记录(而不是审计)框架 - 访问文件系统以写入日志文件相对较少有害,因为日志记录不必是事务操作,即您不需要回滚对日志文件的写入;但是部分写入是不可接受的。


通过使用 Singleton/定时器将文件缓存到本地是另一个几乎总是安全的操作示例。 - Mike Braun
1
除非有特定的原因,否则不应尝试从EJB访问文件系统。在从任何类型的bean(而不仅仅是EJB bean)进行IO时都应该小心谨慎。 - dexter meyers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接