核心类:
package com.zizhu.util;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandlerFactory;
import java.util.HashSet;
import java.util.Set;
/**
* 自定义类加载器,重载URLClassLoader大部分方法,将jar文件添加到ClassLoader,将jar包路径下所有jar包添加到
* ClassLoader,将ClassPath路径下所有的类以及资源加载到ClassLoader
* @author 紫竹
*
*/
public class MyClassLoader extends URLClassLoader {
private Set<String> names = new HashSet<String>();// 存放自定义类的名称
public MyClassLoader(URL[] urls, ClassLoader parent,
URLStreamHandlerFactory factory) {
super(urls, parent, factory);
}
public MyClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
public MyClassLoader(URL[] urls) {
super(urls);
}
/**
* url 既可以是一个文件路径(这个文件路径必须是url格式),里面存放了资源文件,存放了类;也可以是一个jar文件的url格式
* @param urls
*/
public void addURL(URL... urls){
for (URL url : urls) {
System.out.println("加载类路径:" + url.toString());
super.addURL(url);
}
}
/**
* 加载jar文件到ClassLoader
* @param files
*/
public void addJar(File... files){
if(files == null || files.length == 0) return ;
for(File file : files){
try {
addURL(file.toURI().toURL());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
/**
* 加载ClassPath到ClassLoader,classPath下所有的资源文件,类全部加载到ClassLoader
* @param classPath 类路径
*/
public void addClassPath(String classPath){
if(isEmpty(classPath)) return;
addClassPath(new File(classPath));
}
/**
* 添加类路径到ClassLoader
* @param path
*/
public void addClassPath(File path){
if(path.isFile()) return;
try {
addURL(path.toURI().toURL());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
/**
* 添加jar包的路径,即我们所说的lib包
* @param path
*/
public void addJarPath(File path){
URL []urls = Path2URL(path);
if(urls == null || urls.length == 0) return ;
addURL(urls);
}
/**
* @param path jar包路径
* @return ClassLoader支持的URL数组
*/
public static URL[] Path2URL(File path){
if(path.isFile()) return new URL[0];
File files[] = path.listFiles();
URL urls [] = new URL[files.length];
for(int i = 0;i<files.length;i++){
try {
urls[i] = files[i].toURI().toURL();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
return urls;
}
@Override
public URL findResource(String name) {
System.out.println("查找资源:" + name);
return super.findResource(name);
}
private boolean isEmpty(String classPath) {
if(classPath != null && classPath.trim().length() > 0) return false;
return true;
}
}
通过这个类,能将用户指定的jar包,classpath下用户的所有类手动加载到classLoader,这个类增强了很多URLClassLoader的方法,使得它更好理解,更好使用
调用web业务逻辑类:
package com.zizhu;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import com.zizhu.util.ConfigUtil;
import com.zizhu.util.MyClassLoader;
public class WebToNative {
public void startToRun(){
String libPath = ConfigUtil.getValue("libPath");
String mainClass = ConfigUtil.getValue("mainClass");
String homePath = ConfigUtil.getValue("homePath");
String methodName = ConfigUtil.getValue("methodName");
try {
File lib = new File(libPath);
File files[] = lib.listFiles();
URL []urls = MyClassLoader.Path2URL(new File(libPath));
MyClassLoader loader = new MyClassLoader(urls,
Thread.currentThread().getContextClassLoader());
//三种方式都可以,都是添加类路径
// loader.addURL(new File(homePath).toURI().toURL());
// loader.addClassPath(new File(homePath));
loader.addClassPath(homePath);
Thread.currentThread().setContextClassLoader(loader);
Class clazz = loader.loadClass(mainClass);
Method m = clazz.getMethod(methodName, null);
m.invoke(clazz.newInstance(), null);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
下面使用这两个类实现将web程序的部分逻辑在不开web服务器的情况下直接转化成命令行的形式执行:
1.测试类:
package com.zizhu;
public class Test {
public static void main(String args[]){
new WebToNative().startToRun();
}
}
接下来就是想方设法让这个程序跑起来,让这个类跑起来必须定义一个native.properties的配置文件,里面提供四个属性:
libPath=D:/Java/WorkspaceForMyeclipse/exam2.0/WebRoot/WEB-INF/lib/
homePath=D:/Java/WorkspaceForMyeclipse/exam2.0/WebRoot/WEB-INF/classes/
mainClass=com.onnet.utils.schedule.ExamTipAndDeleteSchedule
methodName=tipAndDelete
接下来就能启用命令行,运行这个程序,这个程序运行的原理是这样的:
1.首先会用自定义的MyClassLoader去加载libPath下所有的jar包
2.加载jar包后,必须把web程序的classpath,也就是源码的类加入到classLoader,homePath,这样,自定义的MyClassLoader就能找到web程序所有的资源,web程序运行的类(也就是web程序需要执行的业务逻辑)
3.然后将自定义的这个MyClassLoader设置为当前线程的ClassLoader
4.最后采用反射机制调用web的业务逻辑类,以及业务逻辑的某个方法