我目前正在尝试添加URLStreamHandler,以便可以使用自定义协议处理URL。在本地运行时,这可以正常工作。当部署到AWS Lambda时,我得到:
java.net.MalformedURLException: unknown protocol: baas
我正在关注"Handler" approach to registering the URLStreamHandler。
我什至可以复制URL.getURLStreamHandler(String)
中的代码,并添加登录到我自己的由Lambda运行的代码中:
((注意:这是从Java 8来源提供的-我现在意识到这可能不具有代表性,因为AWS Lambda使用Java 11运行时)。
URLStreamHandler handler = null;
String packagePrefixList = null;
packagePrefixList
= java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction(
"java.protocol.handler.pkgs",""));
if (packagePrefixList != "") {
packagePrefixList += "|";
}
// REMIND: decide whether to allow the "null" class prefix
// or not.
packagePrefixList += "sun.net.www.protocol";
LOG.debug("packagePrefixList: " + packagePrefixList);
StringTokenizer packagePrefixIter =
new StringTokenizer(packagePrefixList, "|");
while (handler == null &&
packagePrefixIter.hasMoreTokens()) {
String packagePrefix =
packagePrefixIter.nextToken().trim();
try {
String clsName = packagePrefix + "." + "baas" +
".Handler";
Class<?> cls = null;
LOG.debug("Try " + clsName);
try {
cls = Class.forName(clsName);
} catch (ClassNotFoundException e) {
ClassLoader cl = ClassLoader.getSystemClassLoader();
if (cl != null) {
cls = cl.loadClass(clsName);
}
}
if (cls != null) {
LOG.debug("Instantiate " + clsName);
handler =
(URLStreamHandler)cls.newInstance();
}
} catch (Exception e) {
// any number of exceptions can get thrown here
LOG.debug(e);
}
}
此打印(在Cloudwatch日志中:)
packagePrefixList: com.elsten.bliss|sun.net.www.protocol (BaasDriver.java:94, thread main)
Try com.elsten.bliss.baas.Handler (BaasDriver.java:108, thread main)
Instantiate com.elsten.bliss.baas.Handler (BaasDriver.java:118, thread main)
com.elsten.bliss.baas.Handler constructor (Handler.java:55, thread main)
因此,在Lambda中以我自己的代码运行时,它可以工作。
但是,下一行记录:
java.lang.IllegalArgumentException: URL is malformed: baas://folder: java.lang.RuntimeException
java.lang.RuntimeException: java.lang.IllegalArgumentException: URL is malformed: baas://folder
...
Caused by: java.net.MalformedURLException: unknown protocol: baas
at java.base/java.net.URL.<init>(Unknown Source)
at java.base/java.net.URL.<init>(Unknown Source)
at java.base/java.net.URL.<init>(Unknown Source)
因此在URL
中运行时,相同的代码正在失败似乎很奇怪。我可以想到的主要区别是用于加载URL
的父类加载器,并且我的代码不同,因此存在某种类加载问题。
起初,我认为应该避免使用旧的META-INF
方法,但是事实证明,在最近的Java版本中,这种方法已经得到了改进,因此我又回到了这一点。
特别是,如果提供的自定义选项无法处理流,则能够将流处理为URL.setURLStreamHandlerFactory(URLStreamHandlerFactory)
,URLStreamHandlerFactory
,http
等的默认回退https
用作回退。
尽管这是一种解决方法-知道为什么无法加载该类很有趣。