核心類:
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的業務邏輯類,以及業務邏輯的某個方法