Java 是否有类似Tomcat的类加载器可以独立使用?
我正在使用一种Java类的应用服务器(Smartfox),它可以运行多个应用程序(“扩展”),但同时有一个非常不方便的类路径设置,以及尝试使用SLF4J时出现的问题 为了解决这个问题,我想将我的应用程序包装在它们自己的类加载器中。这样一个包含类加载器应该很像Tomcat,因为它Java 是否有类似Tomcat的类加载器可以独立使用?,java,classpath,osgi,classloader,encapsulation,Java,Classpath,Osgi,Classloader,Encapsulation,我正在使用一种Java类的应用服务器(Smartfox),它可以运行多个应用程序(“扩展”),但同时有一个非常不方便的类路径设置,以及尝试使用SLF4J时出现的问题 为了解决这个问题,我想将我的应用程序包装在它们自己的类加载器中。这样一个包含类加载器应该很像Tomcat,因为它 可以从包含JAR的目录加载类 优先选择来自其自身类路径的类,而不是来自父类路径的类 在我的项目中,是否有一个库有这样一个类加载器,我可以“拖放”它?如果不是的话,我自己创造它会很难吗?任何已知的陷阱?(和其他模块系统
- 可以从包含JAR的目录加载类
- 优先选择来自其自身类路径的类,而不是来自父类路径的类
例如,Eclipse使用的是OSGi实现。因为我在嵌入OSGi容器时遇到了问题,而且确实有点过火,所以我推出了自己的解决方案。但总有一天我会学会使用OSGi,在这种情况下,我不需要嵌入框架 如果你碰巧想使用这段代码,它就在“用它做你想做的事”许可证下
公共类SmartfoxExtensionContainer扩展了AbstractExtension{
私有抽象扩展;
私有void initrealtextension(){
最终字符串区域=this.getOwnerZone();
System.out.println(“[SmartfoxExtensionContainer]=============区域的初始扩展”+区域+”======================”;
试一试{
//负载特性
File propFile=新文件(“wext/”+zone+“.properties”);
System.out.println(“[SmartfoxExtensionContainer]从”+propFile.getCanonicalPath()加载配置);
Properties props=新属性();
最终文件输入流ins=新文件输入流(propFile);
试一试{
道具加载(新的InputStreamReader(ins,“UTF-8”);
}最后{
试一试{
ins.close();
}捕获(IOE){}
}
//构造类加载器
File jarDir=新文件(props.getProperty(“classpath”,“wext/”+zone));
System.out.println(“[SmartfoxExtensionContainer]从”+jarDir.getCanonicalPath()加载类);
如果(!jarDir.isDirectory())抛出新的RuntimeException(“这不是现有目录”);
最终文件[]fs=jarDir.listFiles();
URL[]URL=新URL[fs.length];
对于(int f=0;f
这似乎正是我想要的,但尽管关于创建捆绑包的教程非常丰富,但我很难找到关于如何嵌入OSGI框架/容器(使用Equinox或Felix)的信息在我的应用程序中。有什么相关信息吗?@BartvanHeukelom:你通常不会在你的应用程序中嵌入OSGi,相反:你创建你的应用程序(和插件)作为OSGi捆绑包。我知道,但我的应用程序本身就是Smartfox中的插件/扩展,我不能将Smartfox放在OSGi中。无论如何,我在See上找到了一些关于扩展设置的详细信息。我写了一篇关于如何将OSGi嵌入应用程序的博文。对于最简单的情况,大约只有5行代码:
public class SmartfoxExtensionContainer extends AbstractExtension {
private AbstractExtension extension;
private void initRealExtension() {
final String zone = this.getOwnerZone();
System.out.println("[SmartfoxExtensionContainer] ========= Init extension for zone " + zone + " =========");
try {
// load properties
File propFile = new File("wext/" + zone + ".properties");
System.out.println("[SmartfoxExtensionContainer] Load config from " + propFile.getCanonicalPath());
Properties props = new Properties();
final FileInputStream ins = new FileInputStream(propFile);
try {
props.load(new InputStreamReader(ins, "UTF-8"));
} finally {
try {
ins.close();
} catch (IOException e) {}
}
// construct classloader
File jarDir = new File(props.getProperty("classpath", "wext/" + zone));
System.out.println("[SmartfoxExtensionContainer] Load classes from " + jarDir.getCanonicalPath());
if (!jarDir.isDirectory()) throw new RuntimeException("That is not an existing directory");
final File[] fs = jarDir.listFiles();
URL[] urls = new URL[fs.length];
for (int f = 0; f < fs.length; f++) {
System.out.println("[SmartfoxExtensionContainer] " + fs[f].getName());
urls[f] = fs[f].toURI().toURL();
}
SelfishClassLoader cl = new SelfishClassLoader(urls, SmartfoxExtensionContainer.class.getClassLoader());
// get real extension class
String mainClass = props.getProperty("mainClass", "Extension");
System.out.println("[SmartfoxExtensionContainer] Main class: " + mainClass);
@SuppressWarnings("unchecked")
Class<? extends AbstractExtension> extClass = (Class<? extends AbstractExtension>) cl.loadClass(mainClass);
// create extension and copy settings
extension = extClass.newInstance();
extension.setOwner(this.getOwnerZone(), this.getOwnerRoom());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/* ======================= DELEGATES ======================= */
@Override
public void init() {
initRealExtension();
extension.init();
}
@Override
public void destroy() {
extension.destroy();
}
@Override
public void handleRequest(String arg0, ActionscriptObject arg1, User arg2, int arg3) {
extension.handleRequest(arg0, arg1, arg2, arg3);
}
@Override
public void handleRequest(String arg0, String[] arg1, User arg2, int arg3) {
extension.handleRequest(arg0, arg1, arg2, arg3);
}
@Override
public void handleInternalEvent(InternalEventObject arg0) {
extension.handleInternalEvent(arg0);
}
@Override
public Object handleInternalRequest(Object params) {
return extension.handleInternalRequest(params);
}
@Override
public void handleRequest(String cmd, JSONObject jso, User u, int fromRoom) {
extension.handleRequest(cmd, jso, u, fromRoom);
}
/* ======================= CUSTOM CLASSLOADER ======================= */
private static class SelfishClassLoader extends URLClassLoader {
SelfishClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
// override default behaviour: find classes in local path first, then parent
@Override protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// First, check if the class has already been loaded
Class<?> clz = findLoadedClass(name);
if (clz == null) {
try {
clz = findClass(name);
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from current class loader
}
if (clz == null) {
// If still not found, then invoke parent.findClass in order
// to find the class.
clz = getParent().loadClass(name);
}
}
if (resolve) {
resolveClass(clz);
}
return clz;
};
}
}