这是一个完整的示例,使用实现您自己的技术URLStreamHandler
来处理resource
协议。您必须将您的类命名为“Handler”,并且包名称的最后一段必须是协议名称(在本例中为resource
)
src/main/java/com/example/protocols/resource/Handler.java
:
package com.example.protocols.resource;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
public class Handler extends URLStreamHandler {
private final ClassLoader classLoader;
public Handler() {
this.classLoader = getClass().getClassLoader();
}
@Override
protected URLConnection openConnection(URL url) throws IOException {
URL resource = classLoader.getResource(url.getPath());
if (resource == null) {
throw new FileNotFoundException("Resource file not found: " + url.getPath());
}
return resource.openConnection();
}
}
从这里开始,我们需要设置系统属性java.protocol.handler.pkgs
以包含基本包com.example.protocols
,以便注册协议。这可以在 Neo4j ExtensionFactory 中静态完成。由于类被 Neo4j 加载,我们知道静态块将被执行。我们还需要提供我们自己的 URLAccessRule,因为默认情况下 Neo4j 只允许使用一些选择协议。这也可能发生在 ExtensionFactory 中。
src/main/java/com/example/protocols/ProtocolInitializerFactory.java
:
package com.example.protocols;
import org.neo4j.annotations.service.ServiceProvider;
import org.neo4j.graphdb.security.URLAccessRule;
import org.neo4j.kernel.extension.ExtensionFactory;
import org.neo4j.kernel.extension.ExtensionType;
import org.neo4j.kernel.extension.context.ExtensionContext;
import org.neo4j.kernel.lifecycle.Lifecycle;
import org.neo4j.kernel.lifecycle.LifecycleAdapter;
@ServiceProvider
public class ProtocolInitializerFactory extends ExtensionFactory<ProtocolInitializerFactory.Dependencies> {
private static final String PROTOCOL_HANDLER_PACKAGES = "java.protocol.handler.pkgs";
private static final String PROTOCOL_PACKAGE = ProtocolInitializerFactory.class.getPackageName();
static {
String currentValue = System.getProperty(PROTOCOL_HANDLER_PACKAGES, "");
if (currentValue.isEmpty()) {
System.setProperty(PROTOCOL_HANDLER_PACKAGES, PROTOCOL_PACKAGE);
} else if (!currentValue.contains(PROTOCOL_PACKAGE)) {
System.setProperty(PROTOCOL_HANDLER_PACKAGES, currentValue + "|" + PROTOCOL_PACKAGE);
}
}
public interface Dependencies {
URLAccessRule urlAccessRule();
}
public ProtocolInitializerFactory() {
super(ExtensionType.DATABASE, "ProtocolInitializer");
}
@Override
public Lifecycle newInstance(ExtensionContext context, Dependencies dependencies) {
URLAccessRule urlAccessRule = dependencies.urlAccessRule();
return LifecycleAdapter.onInit(() -> {
URLAccessRule customRule = (config, url) -> {
if ("resource".equals(url.getProtocol())) { // Check the protocol name
return url; // Optionally, you can validate the URL here and throw an exception if it is not valid or should not be allowed access
}
return urlAccessRule.validate(config, url);
};
context.dependencySatisfier().satisfyDependency(customRule);
});
}
}
设置完成后,按照指南将这些类打包为 Neo4j 插件并将其放入数据库的插件目录中。
诚然,需要覆盖默认 URLAccessRule 感觉有点阴暗。最好简单地实现 URLStreamHandler,并使用另一种 CSV 加载方法,如APOC 的 apoc.load.csv。这不需要覆盖 URLAccessRule,但需要设置 Java 系统属性java.protocol.handler.pkgs
。