本文主要为将指定java文件编译并生成jar,供其他程序依赖,直接上代码
/**
* @author zhangchengping
* @PackageName:com.demo.wms.tasks
* @ClassName:CompilerUtils
* @Description: 动态编译java文件
* @date 2019-06-06 10:37
* @Version 1.0
*/
import org.apache.commons.lang.StringUtils;
import java.io.*;
import java.util.Arrays;
import java.util.List;
import javax.tools.*;
public class CompilerUtils {
private static JavaCompiler javaCompiler;
private static String encoding = "UTF-8";
private CompilerUtils() {
};
private static JavaCompiler getJavaCompiler() {
if (javaCompiler == null) {
synchronized (CompilerUtils.class) {
if (javaCompiler == null) {
//根据JavaCompiler 的获取方式来看,应该是采用了单例模式的,但是这里为了顺便复习一下单例模式,以及确保一下单例吧
javaCompiler = ToolProvider.getSystemJavaCompiler();
}
}
}
return javaCompiler;
}
/**
* @Description: 编译java文件
* @param encoding 编译编码
* @param jarPath 需要加载的jar的路径
* @param filePath 文件或者目录(若为目录,自动递归编译)
* @param sourceDir java源文件存放目录
* @param targetDir 编译后class类文件存放目录
* @return boolean
* @Author zhangchengping
* @Date 2019-06-06 19:50
*/
public static void compiler( String filePath, String targetDir, String sourceDir,String encoding, String jarPath)
throws Exception {
// 得到filePath目录下的所有java源文件
List sourceFileList = File4ComplierUtils.getSourceFiles(filePath);
if (sourceFileList.size() == 0) {
// 没有java文件,直接返回
System.out.println(filePath + "目录下查找不到任何java文件");
return;
}
//获取所有jar
String jars = File4ComplierUtils.getJarFiles(jarPath);
if(StringUtils.isBlank(jars)){
jars="";
}
File targetFile = new File(targetDir);
if(!targetFile.exists())targetFile.mkdirs();
// 建立DiagnosticCollector对象
DiagnosticCollector diagnostics = new DiagnosticCollector();
//该文件管理器实例的作用就是将我们需要动态编译的java源文件转换为getTask需要的编译单元
StandardJavaFileManager fileManager = getJavaCompiler().getStandardFileManager(diagnostics, null, null);
// 获取要编译的编译单元
Iterable extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList);
/**
* 编译选项,在编译java文件时,编译程序会自动的去寻找java文件引用的其他的java源文件或者class。 -sourcepath选项就是定义java源文件的查找目录, -classpath选项就是定义class文件的查找目录,-d就是编译文件的输出目录。
*/
//Iterable options =Arrays.asList("-encoding",encoding,"-classpath",jars,"-d", targetDir, "-sourcepath", sourceDir);
Iterable options =Arrays.asList("-encoding",encoding,"-classpath",jars,"-d", targetDir, "-sourcepath", sourceDir);
/**
* 第一个参数为文件输出,这里我们可以不指定,我们采用javac命令的-d参数来指定class文件的生成目录
* 第二个参数为文件管理器实例 fileManager
* 第三个参数DiagnosticCollector diagnostics是在编译出错时,存放编译错误信息
* 第四个参数为编译命令选项,就是javac命令的可选项,这里我们主要使用了-d和-sourcepath这两个选项
* 第五个参数为类名称
* 第六个参数为上面提到的编译单元,就是我们需要编译的java源文件
*/
JavaCompiler.CompilationTask task = getJavaCompiler().getTask(
null,
fileManager,
diagnostics,
options,
null,
compilationUnits);
// 运行编译任务
// 编译源程式
boolean success = task.call();
for (Diagnostic diagnostic : diagnostics.getDiagnostics())
System.out.printf(
"Code: %s%n" +
"Kind: %s%n" +
"Position: %s%n" +
"Start Position: %s%n" +
"End Position: %s%n" +
"Source: %s%n" +
"Message: %s%n",
diagnostic.getCode(), diagnostic.getKind(),
diagnostic.getPosition(), diagnostic.getStartPosition(),
diagnostic.getEndPosition(), diagnostic.getSource(),
diagnostic.getMessage(null));
fileManager.close();
System.out.println((success)?"编译成功":"编译失败");
}
}
/**
* @author zhangchengping
* @PackageName:com.demo.wms.tasks.web.listener
* @ClassName:s
* @Description: 文件处理类
* @date 2019-06-06 19:07
* @Version 1.0
*/
public class File4ComplierUtils {
/**
* @Description: 获取目录下所有源文件
* @param sourceFilePath
* @return java.util.List
* @Author zhangchengping
* @Date 2019-06-06 19:47
*/
public static List getSourceFiles(String sourceFilePath){
List sourceFileList = new ArrayList<>();
try {
getSourceFiles(new File(sourceFilePath),sourceFileList);
} catch (Exception e) {
e.printStackTrace();
sourceFileList = null;
}
return sourceFileList;
}
/**
* @Description: 获取目录下所有的jar
* @param sourceFilePath
* @return java.lang.String
* @Author zhangchengping
* @Date 2019-06-06 19:46
*/
public static String getJarFiles(String sourceFilePath){
String jars = "";
try {
getJarFiles(new File(sourceFilePath),jars);
} catch (Exception e) {
e.printStackTrace();
jars = "";
}
return jars;
}
/**
* 查找该目录下的所有的java文件
*
* @param sourceFile
* @param sourceFileList
* @throws Exception
*/
private static void getSourceFiles(File sourceFile, List sourceFileList) throws Exception {
if (!sourceFile.exists()) {
// 文件或者目录必须存在
throw new IOException(String.format("%s目录不存在",sourceFile.getPath()));
}
if (null == sourceFileList) {
// 若file对象为目录
throw new NullPointerException("参数异常");
}
if (sourceFile.isDirectory()) {// 若file对象为目录
File[] childrenDirectoryFiles = sourceFile.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
});
for (File file : sourceFile.listFiles()) {
if(file.isDirectory()){
getSourceFiles(file,sourceFileList);
} else {
sourceFileList.add(file);
}
}
}else{
sourceFileList.add(sourceFile);
}
}
/**
* 查找该目录下的所有的jar文件
*
* @param sourceFile
* @throws Exception
*/
private static String getJarFiles(File sourceFile,String jars) throws Exception {
if (!sourceFile.exists()) {
// 文件或者目录必须存在
throw new IOException("jar目录不存在");
}
if (!sourceFile.isDirectory()) {
// 若file对象为目录
throw new IOException("jar路径不为目录");
}
if(sourceFile.isDirectory()){
for (File file : sourceFile.listFiles()) {
if(file.isDirectory()){
getJarFiles(file,jars);
}else {
jars = jars + file.getPath() + ";";
}
}
}else{
jars = jars + sourceFile.getPath() + ";";
}
return jars;
}
}
**
* @author zhangchengping
* @PackageName:com.demo.wms.tasks.web.listener
* @ClassName:PackageUtil
* @Description: 生成jar文件
* @date 2019-06-06 22:59
* @Version 1.0
*/
import com.sun.javafx.beans.annotations.NonNull;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.annotation.Target;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
public class CreateJarUtils {
/**
* @param rootPath class文件根目录
* @param targetPath 需要将jar存放的路径
* @param jarFileName jar文件的名称
* @Description: 根据class生成jar文件
* @Author zhangchengping
* @Date 2019-06-06 23:56
*/
public static void createTempJar(String rootPath, String targetPath, String jarFileName) throws IOException {
if (!new File(rootPath).exists()) {
throw new IOException(String.format("%s路径不存在", rootPath));
}
if (StringUtils.isBlank(jarFileName)) {
throw new NullPointerException("jarFileName为空");
}
//生成META-INF文件
Manifest manifest = new Manifest();
manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
//manifest.getMainAttributes().putValue("Main-Class", "Show");//指定Main Class
//创建临时jar
File jarFile = File.createTempFile("edwin-", ".jar", new File(System.getProperty("java.io.tmpdir")));
JarOutputStream out = new JarOutputStream(new FileOutputStream(jarFile), manifest);
createTempJarInner(out, new File(rootPath), "");
out.flush();
out.close();
//程序结束后,通过以下代码删除生成的jar文件
/* Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
jarFile.delete();
}
});*/
//生成目标路径
File targetFile = new File(targetPath);
if (!targetFile.exists()) targetFile.mkdirs();
File targetJarFile = new File(targetPath + File.separator + jarFileName + ".jar");
if(targetJarFile.exists() && targetJarFile.isFile())targetJarFile.delete();
FileUtils.moveFile(jarFile, targetJarFile);
//jarFile.renameTo(new File(""));
}
/**
* @Description: 生成jar文件
* @param out 文件输出流
* @param f 文件临时File
* @param base 文件基础包名
* @return void
* @Author zhangchengping
* @Date 2019-06-07 00:02
*/
private static void createTempJarInner(JarOutputStream out, File f,
String base) throws IOException {
if (f.isDirectory()) {
File[] fl = f.listFiles();
if (base.length() > 0) {
base = base + "/";
}
for (int i = 0; i < fl.length; i++) {
createTempJarInner(out, fl[i], base + fl[i].getName());
}
} else {
out.putNextEntry(new JarEntry(base));
FileInputStream in = new FileInputStream(f);
byte[] buffer = new byte[1024];
int n = in.read(buffer);
while (n != -1) {
out.write(buffer, 0, n);
n = in.read(buffer);
}
in.close();
}
}
}
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import com.demo.wms.tasks.utils.CompilerUtils;
import com.demo.wms.tasks.utils.CreateJarUtils;
import org.apache.commons.io.FileUtils;
public class BuildRmi {
//资源文件根路径
static String basePath = "E:\\WorkSpace\\demo\\WMS_TASK_NC";
//生成jar文件路径
static String jarFilePath = "E:\\WorkSpace\\demo\\rmi-client";
//需要编译的源文件路径
static String[] srcFiles = {
"/src/com/demo/wms/tasks/vo/",
"/rmi/com/demo/wms/tasks/rmi/",
"/rmi/com/demo/wms/tasks/rmi/po/",
"/rmi/com/demo/wms/tasks/rmi/client/"
};
static String jarReyOnPath = "E:\\WorkSpace\\demo\\WMS_TASK_NC\\WebRoot\\WEB-INF\\lib";
static String jarFileName = "rim";
static String encoding = "utf-8";
public static void main(String[] args) {
String sourcePath = "";
String classPath = "";
try {
// 将RMI需要使用的JAVA文件拷贝到制定目录中
System.out.println("分隔符:" + File.separator);
System.out.println("资源拷贝......");
sourcePath = jarFilePath + File.separator + "source";
copySource(sourcePath);//拷贝资源
System.out.println("资源拷贝结束");
System.out.println("编译资源......");
//编译java文件
classPath = jarFilePath + File.separator + "class";
try {
CompilerUtils.compiler(sourcePath, classPath, basePath, encoding, jarReyOnPath);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("编译资源结束");
System.out.println("生成jar......");
//生成jar文件
CreateJarUtils.createTempJar(classPath, jarFilePath, jarFileName);
System.out.println("生成jar完成");
//删除临时文件
ExeSuccess(sourcePath, classPath);
} catch (IOException e) {
e.printStackTrace();
deleteTempFile(sourcePath, classPath);
} finally {
}
}
private static void ExeSuccess(String sourcePath, String classPath) {
final String sourcedir = sourcePath;
final String classdir = classPath;
//程序结束后,通过以下代码删除生成的文件
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
deleteTempFile(sourcedir, classdir);
System.out.println("***************执行完毕**********************");
}
});
}
private static void deleteTempFile(String sourcePath, String classPath) {
//程序结束后,通过以下代码删除生成的class 和java文件
try {
File sourceFile = new File(sourcePath);
if (sourceFile.exists()) {
FileUtils.deleteDirectory(sourceFile);
}
File classFile = new File(classPath);
if (classFile.exists()) {
FileUtils.deleteDirectory(classFile);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void copySource(String sourcePath) throws IOException {
for (String f : srcFiles) {
String path = f.replace("/", File.separator);
System.out.println(path);
File srcFile = new File(basePath + path);
File targetFile = new File(sourcePath + path);
FileUtils.copyDirectory(srcFile, targetFile, new FileFilter() {
@Override
public boolean accept(File pathname) {
System.out.println(pathname);
return pathname.getName().endsWith(".java");
}
});
}
}
}