在 Spring 服务器上的 Java Applet 中初始化 AWS

Initialising AWS in a Java Applet on a Spring server

我正在尝试使用 Amazon 的 SDK 从 Java 小程序将文件上传到 Amazon S3。该小程序位于网络服务器 运行 Spring.

问题是在尝试上传文件之前,我需要初始化 Amazon S3 客户端。这通常很简单:

AWSCredentials credentials = new BasicAWSCredentials(AWS_ACCESS_KEY, AWS_SECRET_KEY);
AmazonS3Client s3Client = new AmazonS3Client(credentials);

但是当我这样做时,第二行会触发此错误消息(无论凭据是否正确):

java.lang.ClassFormatError: Incompatible magic value 1008813135 in class file <!DOCTYPE html>
    at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_66]
    at java.lang.ClassLoader.defineClass(Unknown Source) ~[na:1.8.0_66]
    at java.security.SecureClassLoader.defineClass(Unknown Source) ~[na:1.8.0_66]
    at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source) ~[na:na]
    at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source) ~[na:na]
    at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source) ~[na:na]
    at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source) ~[na:na]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_66]
    at org.apache.commons.logging.LogFactory.createFactory(LogFactory.java:1131) ~[upload.jar:na]
    at org.apache.commons.logging.LogFactory.run(LogFactory.java:1065) ~[upload.jar:na]
    at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_66]
    at org.apache.commons.logging.LogFactory.newFactory(LogFactory.java:1062) ~[upload.jar:na]
    at org.apache.commons.logging.LogFactory.getFactory(LogFactory.java:569) ~[upload.jar:na]
    at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:685) ~[upload.jar:na]
    at com.amazonaws.AmazonWebServiceClient.<clinit>(AmazonWebServiceClient.java:56) ~[upload.jar:na]

这里发生的事情是 AWS 库正在尝试初始化其日志系统,因此它开始搜索将要处理任何内部日志消息的 LogFactory。问题是它开始在小程序之外搜索,通过对

发出 GET 请求
http://localhost/...myUrl.../commons-logging.properties

(我从这里的文档中发现了这一点:https://commons.apache.org/proper/commons-logging/apidocs/org/apache/commons/logging/package-summary.html

现在,快速附注:我的 Spring 的 security-app-context.xml 文件包含以下入口点 bean,以确保未经身份验证的用户只能看到登录页面:

<beans:bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <beans:constructor-arg value="/loginPage" />
</beans:bean>

正是在这个阶段,我的 Spring 设置正在捕获 GET 请求并将其重定向到服务器登录页面。作为此 GET 请求的结果,此重定向最终会发送一个有效的 HTML 页面。 HTML 页面的第一行是 '',日志框架对其进行解析并尝试使用它来初始化 Java class。显然一个叫做 .class 的 class 不存在,所以我得到了 ClassFormatError。

有没有办法让 AWS 库很好地适应这个设置?最好不要禁用 Spring 的重定向策略。

您可以通过将此行放在 new AmazonS3Client() 调用之前的某处来告诉日志框架确切在哪里可以找到 LogFactory 实现,从而解决该特定错误:

System.setProperty("org.apache.commons.logging.LogFactory", "org.apache.commons.logging.impl.LogFactoryImpl");

但是,您可能会发现同样的问题出现在不同的文件中,实际上是两个文件,这次在 Amazon 的库中更深入。同样,使用 GET 请求搜索它们(如 Java 控制台中所示)。

http://localhost/...myUrl.../com/amazonaws/services/s3/request.handlers
http://localhost/...myUrl.../com/amazonaws/services/s3/request.handler2s

因此,您需要一个名为 request.handlers 的文件和另一个名为 request.handler2s 的文件,它们都位于 com/amazonaws/services/s3 的文件夹结构中,其中 com 文件夹位于您的其中一个文件夹中类路径文件夹(可能是您的小程序 JAR 文件的根目录)。这些文件应该是空的。

将 LogFactory 属性 设置为防止搜索 commons-logging.properties,并且 Amazon 请求处理程序文件就位,初始化应该会成功完成。

(这个答案感觉有点笨拙,我对它不是很满意,所以非常欢迎替代方案)。