java动态编译整个项目,解决jar包找不到问题
原文:http://itzyx.com/index.php/javac/

动态将java文件编译为class文件解决方案:
将temp\sdl\src目录中的java源文件编译成class文件,并存放到temp\sdl\classes目录中

java中早就提供了用java方式去动态编译java源文件的接口,有关java动态编译的API都在javax.tools包中。使用jdk1.6以上版本提供的JavaCompiler工具来动态编译java源文件。
我们可以通过ToolProvider类的静态方法getSystemJavaCompiler得到JavaCompiler对象实例。
// 获取编译器实例
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

得到JavaCompiler对象实例后,我们可以调用该工具的getTask(Writer out, JavaFileManager fileManager, DiagnosticListener<? super JavaFileObject> diagnosticListener, Iterable<String> options, Iterable<String> classes, Iterable<? extends JavaFileObject> compilationUnits) 方法获取一个编译任务对象。

CompilationTask compilationTask = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);

该方法的第一个参数为文件输出,这里我们可以不指定,我们采用javac命令的-d参数来指定class文件的生成目录。
第二个参数为文件管理器实例

// 获取标准文件管理器实例
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);

该文件管理器实例的作用就是将我们需要动态编译的java源文件转换为getTask需要的编译单元。

// 获取要编译的编译单元
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList);

第三个参数DiagnosticCollector<JavaFileObject> diagnostics是在编译出错时,存放编译错误信息。
第四个参数为编译命令选项,就是javac命令的可选项,这里我们主要使用了-d和-sourcepath这两个选项。

/**
* 编译选项,在编译java文件时,编译程序会自动的去寻找java文件引用的其他的java源文件或者class。 -sourcepath选项就是定义java源文件的查找目录, -classpath选项就是定义class文件的查找目录,-d就是编译文件的输出目录。
*/
Iterable<String> options =Arrays.asList("-encoding",encoding,"-classpath",jars,"-d", targetDir, "-sourcepath", sourceDir);

第五个参数为类名称
第六个参数为上面提到的编译单元,就是我们需要编译的java源文件
当我们得到CompilationTask compilationTask编译任务后,我们就可以调用compilationTask.call()方法进行编译工作

// 运行编译任务
compilationTask.call()
package com.lkb.autoCode.util;

import javax.tools.*;
import javax.tools.JavaCompiler.CompilationTask;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; public class DynamicCompilerUtil {
private String jars = "";
private String targetDir = ""; /**
* 判断字符串是否为空 有值为true 空为:false
*/
public boolean isnull(String str) {
if (null == str) {
return false;
} else if ("".equals(str)) {
return false;
} else if (str.equals("null")) {
return false;
} else {
return true;
}
} /**
* 编译java文件
*
* @param encoding 编译编码
* @param jars 需要加载的jar
* @param filePath 文件或者目录(若为目录,自动递归编译)
* @param sourceDir java源文件存放目录
* @param targetDir 编译后class类文件存放目录
* @param diagnostics 存放编译过程中的错误信息
* @return
* @throws Exception
*/
public boolean compiler(String encoding, String jars, String filePath, String sourceDir, String targetDir, DiagnosticCollector<JavaFileObject> diagnostics)
throws Exception {
// 获取编译器实例
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
// 获取标准文件管理器实例
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
try {
if (!isnull(filePath) && !isnull(sourceDir) && !isnull(targetDir)) {
return false;
}
// 得到filePath目录下的所有java源文件
File sourceFile = new File(filePath);
List<File> sourceFileList = new ArrayList<File>();
this.targetDir = targetDir;
getSourceFiles(sourceFile, sourceFileList);
// 没有java文件,直接返回
if (sourceFileList.size() == 0) {
System.out.println(filePath + "目录下查找不到任何java文件");
return false;
}
// 获取要编译的编译单元
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList);
/**
* 编译选项,在编译java文件时,编译程序会自动的去寻找java文件引用的其他的java源文件或者class。 -sourcepath选项就是定义java源文件的查找目录, -classpath选项就是定义class文件的查找目录。
*/
Iterable<String> options = Arrays.asList("-encoding", encoding, "-classpath", jars, "-d", targetDir, "-sourcepath", sourceDir);
CompilationTask compilationTask = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);
// 运行编译任务
return compilationTask.call();
} finally {
fileManager.close();
}
} /**
* 查找该目录下的所有的java文件
*
* @param sourceFile
* @param sourceFileList
* @throws Exception
*/
private void getSourceFiles(File sourceFile, List<File> sourceFileList) throws Exception {
if (sourceFile.exists() && sourceFileList != null) {//文件或者目录必须存在
if (sourceFile.isDirectory()) {// 若file对象为目录
// 得到该目录下以.java结尾的文件或者目录
File[] childrenFiles = sourceFile.listFiles(new FileFilter() {
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
try {
new CopyDirectory().copyDirectiory(pathname.getPath(), targetDir + pathname.getPath().substring(pathname.getPath().indexOf("src") + 3, pathname.getPath().length()));
} catch (IOException e) {
e.printStackTrace();
}
return true;
} else {
String name = pathname.getName();
if (name.endsWith(".java") ? true : false) {
return true;
}
try {
new CopyDirectory().copyFile(pathname, new File(targetDir + pathname.getPath().substring(pathname.getPath().indexOf("src") + 3, pathname.getPath().length())));
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
});
// 递归调用
for (File childFile : childrenFiles) {
getSourceFiles(childFile, sourceFileList);
}
} else {// 若file对象为文件
sourceFileList.add(sourceFile);
}
}
} /**
* 查找该目录下的所有的jar文件
*
* @param jarPath
* @throws Exception
*/
private String getJarFiles(String jarPath) throws Exception {
File sourceFile = new File(jarPath);
// String jars="";
if (sourceFile.exists()) {// 文件或者目录必须存在
if (sourceFile.isDirectory()) {// 若file对象为目录
// 得到该目录下以.java结尾的文件或者目录
File[] childrenFiles = sourceFile.listFiles(new FileFilter() {
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
return true;
} else {
String name = pathname.getName();
if (name.endsWith(".jar") ? true : false) {
jars = jars + pathname.getPath() + ";";
return true;
}
return false;
}
}
});
}
}
return jars;
} public static void main(String[] args) {
try {
// 编译F:\\亚信工作\\SDL文件\\sdl\\src目录下的所有java文件
String filePath = "E:\\workspace\\COD-MS\\src";
String sourceDir = "E:\\workspace\\COD-MS\\src";
String jarPath = "E:\\workspace\\COD-MS\\WebRoot\\WEB-INF\\lib";
String targetDir = "E:\\java\\project\\bin";
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
DynamicCompilerUtil dynamicCompilerUtil = new DynamicCompilerUtil();
boolean compilerResult = dynamicCompilerUtil.compiler("UTF-8", dynamicCompilerUtil.getJarFiles(jarPath), filePath, sourceDir, targetDir, diagnostics);
if (compilerResult) {
System.out.println("编译成功");
} else {
System.out.println("编译失败");
for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
// System.out.format("%s[line %d column %d]-->%s%n", diagnostic.getKind(), diagnostic.getLineNumber(),
// diagnostic.getColumnNumber(),
// diagnostic.getMessage(null));
System.out.println(diagnostic.getMessage(null));
}
}
} catch (Exception e) {
e.printStackTrace();
}
} }
package com.lkb.autoCode.util;

import java.io.*;

/**
* 复制文件夹或文件夹
*/
public class CopyDirectory {
// 源文件夹
String url1 = "E:\\workspace\\DeployeTest";
// 目标文件夹
String url2 = "E:\\java\\project\\bin"; public static void main(String args[]) throws IOException {
CopyDirectory copyDirectory = new CopyDirectory();
// 创建目标文件夹
(new File(copyDirectory.url2)).mkdirs();
// 获取源文件夹当前下的文件或目录
File[] file = (new File(copyDirectory.url1)).listFiles();
for (int i = 0; i < file.length; i++) {
if (file[i].isFile()) {
// 复制文件
copyDirectory.copyFile(file[i], new File(copyDirectory.url2 + file[i].getName()));
}
if (file[i].isDirectory()) {
// 复制目录
String sourceDir = copyDirectory.url1 + File.separator + file[i].getName();
String targetDir = copyDirectory.url2 + File.separator + file[i].getName();
copyDirectory.copyDirectiory(sourceDir, targetDir);
}
}
} /**
* 复制文件
*
* @param sourceFile 源文件
* @param targetFile 目标文件
* @throws IOException
*/
public void copyFile(File sourceFile, File targetFile)
throws IOException {
// 新建文件输入流并对它进行缓冲
FileInputStream input = new FileInputStream(sourceFile);
BufferedInputStream inBuff = new BufferedInputStream(input); // 新建文件输出流并对它进行缓冲
FileOutputStream output = new FileOutputStream(targetFile);
BufferedOutputStream outBuff = new BufferedOutputStream(output); // 缓冲数组
byte[] b = new byte[1024 * 5];
int len;
while ((len = inBuff.read(b)) != -1) {
outBuff.write(b, 0, len);
}
// 刷新此缓冲的输出流
outBuff.flush(); // 关闭流
inBuff.close();
outBuff.close();
output.close();
input.close();
} /**
* 复制文件夹
*
* @param sourceDir 源文件夹路径
* @param targetDir 目标文件夹路径
* @throws IOException
*/
public void copyDirectiory(String sourceDir, String targetDir)
throws IOException {
// 新建目标目录
(new File(targetDir)).mkdirs();
// 获取源文件夹当前下的文件或目录
File[] file = (new File(sourceDir)).listFiles();
for (int i = 0; i < file.length; i++) {
if (file[i].isFile()) {
// 源文件
File sourceFile = file[i];
// 目标文件
File targetFile = new File(new File(targetDir)
.getAbsolutePath()
+ File.separator + file[i].getName());
copyFile(sourceFile, targetFile);
}
if (file[i].isDirectory()) {
// 准备复制的源文件夹
String dir1 = sourceDir + "/" + file[i].getName();
// 准备复制的目标文件夹
String dir2 = targetDir + "/" + file[i].getName();
copyDirectiory(dir1, dir2);
}
}
}
}

摘自百度文库:http://wenku.baidu.com/link?url=hFsuio_UxS4_vkt7ov8grKZp40rxJ8AR_ktzhNReoG4MGXFKf-dP_wVodVsErD737eKvaaNhVY9yEBdyXG1IEgiZeukpGU93pxCBTIbXvq3###

Java_java动态编译整个项目,解决jar包找不到问题的更多相关文章

  1. java项目打成jar包时引用了第三方jar,此时我们该如何解决呢

    Web项目做多了,反而对单纯的java项目陌生了,今天我们在开发项目的过程中,碰到一个这样的需求:需要将java项目放到linux系统上跑起来,当然这个javaSE项目是带main方法的.我们知道在I ...

  2. 项目做成jar包

    项目做成jar包 方法一.在eclipse3.1中把项目做成jar包步骤. 打包前的工作. 在项目下创建一个文件夹,名为META-INF,再在其下创建文件MANIFEST.MF 编辑的内容如下: Ma ...

  3. 把项目做成jar包

    方法一.在eclipse3.1中把项目做成jar包步骤. 打包前的工作. 在项目下创建一个文件夹,名为META-INF,再在其下创建文件MANIFEST.MF 编辑的内容如下: Manifest-Ve ...

  4. SpringBoot项目打成jar包后上传文件到服务器 目录与jar包同级问题

    看标题好像很简单的样子,但是针对使用jar包发布SpringBoot项目就不一样了.当你使用tomcat发布项目的时候,上传文件存放会变得非常简单,因为你可以随意操作项目路径下的资源.但是当你使用Sp ...

  5. 解决jar包依赖:Spring IO platform推出bom

    名词解释: BOM(bill of materials):材料清单,用于解决jar包依赖的好方法. Spring IO Platform 缘起:Spring起初只专注ioc和aop,现在已发展成一个庞 ...

  6. Maven下载项目依赖jar包和使用方法

    一.Maven3.5.0安装与配置+Eclipse应用 参考:Maven3.5.0安装与配置+Eclipse应用 二.http://mvnrepository.com/ 此处以http://mvnre ...

  7. (转)IntelliJ IDEA java项目导入jar包,打jar包

    以下为转载原文:https://www.cnblogs.com/yulia/p/6824058.html 一.导入 1.java项目在没有导入该jar包之前,如图: 2.点击 File ->   ...

  8. IntelliJ IDEA java项目导入jar包,打jar包

    一.导入 1.java项目在没有导入该jar包之前,如图: 2.点击 File ->  Project Structure(快捷键 Ctrl + Alt + Shift + s),点击Proje ...

  9. 三十、详述使用 IntelliJ IDEA 解决 jar 包冲突的问题

    在实际的 Maven 项目开发中,由于项目引入的依赖过多,遇到 jar 冲突算是一个很常见的问题了.在本文中,我们就一起来看看,如何使用 IntelliJ IDEA 解决 jar 包冲突的问题!简单粗 ...

随机推荐

  1. [LeetCode] Add Two Numbers

    You are given two linked lists representing two non-negative numbers. The digits are stored in rever ...

  2. poj 2337 欧拉回路输出最小字典序路径 ***

    把26个小写字母当成点,每个单词就是一条边. 然后就是求欧拉路径. #include<cstdio> #include<iostream> #include<algori ...

  3. [Eclipse] eclipse中打开xml文件,使用ctrl+鼠标左键无法跳转至Java源文件【待解决】

    eclipse中打开xml文件,使用ctrl+鼠标左键无法跳转至Java源文件: 1. 设置eclipse ctrl + 左键打开源文件代码,如下图,设置都正常 2. 在网上找了很多种办法,均失败,在 ...

  4. 注解:【有连接表的】Hibernate单向1->1关联

    Person与Address关联:单向1->1,[有连接表的] (使用较少!) Person.java package org.crazyit.app.domain; import javax. ...

  5. [UI]实用案例--Shape绘制实用圆圈

    Android允许通过xml定义资源,常见的事string,id,integer,dimen等,也可以定义一些图片资源,比如用来做几何的矢量图就非常好用,其中有许多的细节问题,具体需求可以再结合goo ...

  6. 即时通讯(IM-instant messager)

    即时通讯又叫实时通讯,简单来说就是两个及以上的人使用网络进行文字.文件.语音和视频的交流. 首先,进行网络进行通信,肯定需要网络协议,即时通讯专用的协议就是xmpp.xmpp协议要传递的消息类型是xm ...

  7. SQL连接查询、变量、运算符、分支、循环语句

    连接查询:通过连接运算符可以实现多个表查询.连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志. 常用的两个链接运算符: 1.join   on 2.union 在关系数据库 ...

  8. 为什么调用 FragmentPagerAdapter.notifyDataSetChanged() 并不能更新其 Fragment?

    在一个 Android 应用中,我使用 FragmentPagerAdapter 来 处理多 Fragment 页面的横向滑动.不过我碰到了一个问题,即当 Fragment 对应的数据集发生改变时,我 ...

  9. windows加入path路径

    右键我的电脑,属性:高级系统设置,高级,环境变量:在系统变量中选path,编辑:将python安装路径加入即可(注意分号):

  10. Java ClassLoader基础及加载不同依赖 Jar 中的公共类

    转载自:最新内容及最清晰格式请见 http://www.trinea.cn/android/java-loader-common-class/ 本文主要介绍 ClassLoader 的基础知识,Cla ...