存档

2012年6月 的存档

Myeclipse中启动Jetty异常的问题

2012年6月19日 1 条评论

  Jetty7.6.4在MyEclipse8.5中启动后报出下面错误。

java.lang.ClassNotFoundException: org.eclipse.jetty.plus.webapp.Configuration
 at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
 at org.eclipse.jetty.util.Loader.loadClass(Loader.java:92)
 at org.eclipse.jetty.util.Loader.loadClass(Loader.java:71)
 at org.eclipse.jetty.webapp.WebAppContext.loadConfigurations(WebAppContext.java:833)
 at org.eclipse.jetty.webapp.WebAppContext.preConfigure(WebAppContext.java:398)
 at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
 at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
 at org.eclipse.jetty.deploy.bindings.StandardStarter.processBinding(StandardStarter.java:36)
 at org.eclipse.jetty.deploy.AppLifeCycle.runBindings(AppLifeCycle.java:183)
 at org.eclipse.jetty.deploy.DeploymentManager.requestAppGoal(DeploymentManager.java:491)
 at org.eclipse.jetty.deploy.DeploymentManager.addApp(DeploymentManager.java:138)
 at org.eclipse.jetty.deploy.providers.ScanningAppProvider.fileAdded(ScanningAppProvider.java:142)
 at org.eclipse.jetty.deploy.providers.ScanningAppProvider$1.fileAdded(ScanningAppProvider.java:53)
 at org.eclipse.jetty.util.Scanner.reportAddition(Scanner.java:604)
 at org.eclipse.jetty.util.Scanner.reportDifferences(Scanner.java:535)
 at org.eclipse.jetty.util.Scanner.scan(Scanner.java:398)
 at org.eclipse.jetty.util.Scanner$1.run(Scanner.java:348)
 at java.util.TimerThread.mainLoop(Timer.java:512)
 at java.util.TimerThread.run(Timer.java:462)

解决办法是在项目发布后删除Jetty contexts目录下名为 {项目名}.xml 文件,这样再从Myeclipse中启动jetty就完全正常了,调试什么的都不会出问题。

分类: 高级民工 标签:

让动态加载的jar包相互访问

2012年6月6日 没有评论

  接上一篇文章,如何让加载的jar可以相互访问class的问题,其实方法很简单只用同一个ClassLoader来加载插件的jar即可。这里可以扩展一下URLClassLoader实现。
一个简单的例子:

public class JarLoader extends URLClassLoader {
 
	public JarLoader(){
		super(new URL[]{});
	}
 
	public JarLoader(URL[] urls) {
		super(urls);
	}
 
	/**
	 * 把jar加载到classloader中
	 * @param path jar路径
	 */
	public void addJar(String path){
		try {
			this.addURL(new File(path).toURI().toURL());
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}
 
}

通过调用URLClassloader的protected方法addURL即可实现在需要时加载jar到loader中。

分类: 高级民工 标签:

Java动态加载jar包到运行环境

2012年6月5日 没有评论

  在为一个正在运行的系统添加新功能或在软件主体不升级的情况下添加新功能往往是通过插件的方式实现,而插件模式设计上无非就是实现一个统一的接口然后由系统加载调用相应的方法达到插件的安装和卸载。典型的例子就如wordpress中的插件。在Java中特别是J2EE应用中插件开发好后一般都是打包成jar上传到服务器然后安装。那么如何实现把jar加载到运行时中呢?

  其实比较简单使用URLClassLoader即可,一个简单的例子:

File file = new File("c:/x.jar");//java
URL uri = file.toURI().toURL();
System.out.println(uri);
URLClassLoader load = new URLClassLoader(new URL[]{uri});

此时x.jar里的所有class都将被加载到运行环境中,如果要实例化某个类那么只需要使用load.loadClass()方法得到Class再newInstance().

在设计插件包结构时可能还需要一个描述文件,这个描述文件中定义了插件信息包括:插件名称,插件依赖,插件入口类(这个是最主要的);插件入口类就是插件接口的一个实现,在把插件的jar加载到系统中后就可以根据插件描述信息来启动插件。

另外由于ClassLoader存在访问隔离,简单来说就是用上面例子中的代码加载两个jar到系统中那么两个jar中的类是不能相互访问的。因为他们是平级的不存在父子关系。这样在需求上如果存在一个插件依赖另一个插件中的类的情况就不能达到目的。这里访问权限的问题我将在下一篇文章中介绍一种解决方案。

分类: 高级民工 标签:

Java RMI

2012年6月5日 没有评论

  Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。可以用此方法调用的任何对象必须实现该远程接口。作为早期的分布式解决方案RMI在如今还是有其合适的应用场景的,诸如EJB,JMX都是建立在rmi上的。

  RMI的应用主要包含有Remote,UnicastRemoteObject,Naming等类或者接口实现,一个简单的例子:http://www.cnblogs.com/ninahan0419/archive/2009/06/25/javarmi.html

了解一下RMI也许在以后可以用上。

分类: 高级民工 标签: ,