将Java文件编译成Jar包
目录
将Java文件编译成Jar包
1.将指定目录下的java文件编译为class文件
import org.apache.commons.lang3.StringUtils;
import javax.tools.*;
import java.io.File;
import java.util.Arrays;
import java.util.List;
// 将java文件编译为class文件
public class CompilerUtil {
private static JavaCompiler javaCompiler = null;
private static String UTF = "UTF-8";
private CompilerUtil(){
}
private static JavaCompiler getJavaCompiler(){
if (javaCompiler == null) {
synchronized (CompilerUtil.class){
if (javaCompiler == null) {
javaCompiler = ToolProvider.getSystemJavaCompiler();
}
}
}
return javaCompiler;
}
/**
*
* @param filePath java源文件目录
* @param targetDir 编译后class文件的输出目录
* @param sourceDir 待编译的文件
* @param encoding 编码格式
* @param jarPath 依赖的jar路径
* @throws Exception
*/
public static void compiler( String filePath, String targetDir, String sourceDir,String encoding, String jarPath)
throws Exception {
// 得到filePath目录下的所有java源文件
List<File> 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<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
//该文件管理器实例的作用就是将我们需要动态编译的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<String> options = Arrays.asList("-encoding",encoding,"-classpath",jars,"-d", targetDir, "-sourcepath", sourceDir);
/**
* 第一个参数为文件输出,这里我们可以不指定,我们采用javac命令的-d参数来指定class文件的生成目录
* 第二个参数为文件管理器实例 fileManager
* 第三个参数DiagnosticCollector<JavaFileObject> 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)?"编译成功":"编译失败");
}
}
2.将指定目录下的class文件打入到jar包中
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
// 将指定目录下的class文件打入到jar包中
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();
}
}
}
3.先生成class在生成jar的工具类,对外使用
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
public class BuildJarUtil {
//资源文件根路径
static String basePath = "x:\\xxxx\\xxxx\\xxxx";
//java源文件、生成class的文件的根路径,生成jar文件路径
static String jarFilePath = "x:\\xxxx\\xxxx\\xxxx";
//需要编译的java源文件路径
static String[] srcFiles = {
"/xxxx/xxxx/"
};
// 项目中用到的jar包的路径
static String jarReyOnPath = "x:\\xxxx\\xxxx\\lib";
// 生成的jar包的路径
static String jarFileName = "xxxx";
static String encoding = "utf-8";
public static void main(String[] args) {
String sourcePath = "";
String classPath = "";
try {
// 需要使用的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 {
CompilerUtil.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");
}
});
}
}
}
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class File4ComplierUtils {
/**
* @Description: 获取目录下所有源文件
* @param sourceFilePath
* @return java.util.List<java.io.File>
* @Author zhangchengping
* @Date 2019-06-06 19:47
*/
public static List<File> getSourceFiles(String sourceFilePath){
List<File> sourceFileList = new ArrayList<File>();
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<File> 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;
}
}