在这里我表示作者的思路非常好,赞一个~,可以很好的控制更新的文件省去了查找、粘贴、拷贝、打包的步骤,因为实现的功能都是一样,所以这篇文章的标题、部分内容同原著一致,这种更新打包方法非常适合中小型项目,尤其是项目上线阶段更新非常频繁的增量更新,虽然可以用hudson+maven+svn实现持续集成自动测试打包部署但是这种方式对小项目来说有点奢侈,而且由于各种因素比如生产环境不在本地加上带宽的因素、项目整体打包文件100多M、只更新单个功能模块、用户要的非常急等因素,所以有时候不得不用增量更新的方法。如果增量更新的时候文件太多,比如css、js、jpg、class等一大堆,这时候可就苦了打包的人员了。
为什么要写这篇文章呢? 主要是我觉得原著写的不够详细,处理路径的时候思路不够清晰代码不易阅读,存在BUG
修复BUG:
1、项目存在多个src路径的时候读取不到class文件
2、java文件有内部类的情况下,打包后的class没有包含内部类class
3、选择文件夹时,递归把该文件夹下的子文件夹的所有文件都放了该文件夹下面。
4、支持从其他路径导入的项目
5、支持maven目录结构class在{project_name}\target\classes, webContent文件
在{project_name}\src\main\webapp
该项目的开发步骤如下: 创建项目就不用多说了
一、创建execWinrar.bat放到execWinrar项目下面,内容如下:注:不用修改
@echo off
REM echo %1
REM echo %2
REM echo %3
REM echo %4
goto exec
(2>nul pushd %2%3)||(echo %2%3 文件&goto :file)
echo %1 文件夹
popd
REM D:\MyDir\MyTools\MyApps\WinRAR\WinRAR a -agYYYYMMDDHHMM -IBCK -R -U -Y -ver -ep -ap%3 %2\%1\%1 %2%3
goto end
:file
REM D:\MyDir\MyTools\MyApps\WinRAR\WinRAR a -agYYYYMMDDHHMM -IBCK -U -Y -ver -ep -ap%3 %2\%1\%1 %2%3
:exec
"%JAVA_HOME%/bin/java" -jar execWinrar_fat.jar %1 %2 %3 %4
choice /c:EC /t:0005 /d:C /n /m "[E] Open Explore,[C] Cancel"
if errorlevel 2 goto end
c:\windows\explorer %1
:end
Echo Compression have done !
二、创建cmd.properties文件放到项目下面,把红色内容替换成你的winrar安装目录,如果路径有空格必须用
引号括起来。 内容如下:
command="C:\\Program Files\\WinRAR\\winrar" a -afzip -agYYYYMMDD -IBCK -ver -Y
三、配置Eclipse External Tools工具
1、打开External Tools 工具
2、新建一个lanch configration,然后配置execWinrar
通过调用批处理将几个关键变量传入批处理,批处理再执行ExecCommand类将参数再传到
ExecCommand类进行处理。
${project_loc} 选中资源所在项目的路径
${project_name} 选中资源所在项目名称
${resource_path} 选中资源路径
${resource_name} 选中资源名称
四、ExecCommand.java,代码如下:
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
/**
* @author martinwu
*
*/
public class ExecCommand {
public static final String BACKSLASH="\\";
public static Map<String, List<ClassPathEntry>> parserXmlClassPath(String fileName) {
Map<String, List<ClassPathEntry>> dataMap = new HashMap<String, List<ClassPathEntry>>();
SAXBuilder builder = new SAXBuilder(false);
Element employees = null;
try {
Document document = builder.build(fileName);
employees = document.getRootElement();
} catch (Exception e) {
e.printStackTrace();
}
List<Element> elList = employees.getChildren();
List<ClassPathEntry> srcItems = new ArrayList<ClassPathEntry>();
List<ClassPathEntry> outputItems = new ArrayList<ClassPathEntry>();
for (Element element : elList) {
if ("src".equals(element.getAttribute("kind").getValue())) {
String output=element.getAttribute("output")==null ? null:element.getAttribute("output").getValue();
String path=element.getAttribute("path")==null ? null:element.getAttribute("path").getValue().replace("/", "\\");
srcItems.add(new ClassPathEntry("src", path, output));
}
if ("output".equals(element.getAttribute("kind").getValue())) {
String output=element.getAttribute("output")==null ? null:element.getAttribute("output").getValue();
String path=element.getAttribute("path")==null ? null:element.getAttribute("path").getValue().replace("/", "\\");
outputItems.add(new ClassPathEntry("output", path, output));
}
}
dataMap.put("src", srcItems);
dataMap.put("output", outputItems);
return dataMap;
}
public static String getExtensionName(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot > -1) && (dot < (filename.length() - 1))) {
return filename.substring(dot + 1);
}
}
return filename;
}
public static String getPerfixName(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot > -1) && (dot < (filename.length() - 1))) {
return filename.substring(0, dot);
}
}
return filename;
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) {
Properties cmdProperties = new Properties();
FileInputStream fis = null;
try {
fis = new FileInputStream("cmd.properties");
cmdProperties.load(fis);
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
if (args.length < 4) {
System.out.println("参数错误!");
System.exit(0);
}
//projectLoc项目绝对路径
String projectLoc = args[0], projectName = args[1], resoucePath = args[2], resouceName = args[3];
// String projectLoc= "F:\AllWorkSpace\indigo\execWinrar";
// String projectName = "execWinrar";
// String resoucePath="\execWinrar\src\ExecCommand.java";
// String resouceName = "ExecCommand.java";
//System.out.println(workspacePath+"\n"+projectName+"\n"+resoucePath+"\n"+resouceName);
//项目路径
// 相对路径 \execWinrar\src\
String relativePath = resoucePath.substring(0,resoucePath.length()-resouceName.length());
File file = new File(projectLoc.substring(0,projectLoc.lastIndexOf(BACKSLASH)) + resoucePath);
/** 获取command命令和项目配置信息 -begin **/
String cmd = cmdProperties.getProperty("command");
Map<String, List<ClassPathEntry>> pathMap = parserXmlClassPath(projectLoc + BACKSLASH + ".classpath");
List<ClassPathEntry> srcEntry = pathMap.get("src");
List<ClassPathEntry> classEntry = pathMap.get("output");
String perfix = getPerfixName(file.getName());
String suffix = getExtensionName(file.getName());
/** 获取command命令和项目配置信息 -end **/
boolean isDirectory = file.isDirectory();
boolean isClassPath = false;
boolean isJava = resouceName.toLowerCase().endsWith(".java");
String srcPath="",classPath=BACKSLASH+classEntry.get(0).getPath();
String curentFilePath = " " + file.getPath();
String compressFilePaths="", compressedFile = " " + projectLoc + BACKSLASH + projectName;
for (int i = 0; i < srcEntry.size(); i++) {
//判断文件是否在src目录
String _tSrc = BACKSLASH+srcEntry.get(i).getPath();
int indexSrc = resoucePath.indexOf(_tSrc);
if(indexSrc!=-1){
isClassPath = true;
srcPath = _tSrc;
break;
}
}
if(isDirectory){
cmd += " -R";
if(isClassPath){
relativePath = resoucePath.replace(srcPath, classPath);
relativePath = relativePath.substring(0,relativePath.lastIndexOf(BACKSLASH));
compressFilePaths = curentFilePath.replace(srcPath, classPath);
}
else{
//relativePath = resoucePath;
relativePath = resoucePath.substring(0,resoucePath.lastIndexOf(BACKSLASH));
compressFilePaths = curentFilePath;
}
}
//single file
else{
if(isClassPath){
relativePath = relativePath.replace(srcPath, classPath);
curentFilePath = curentFilePath.replace(srcPath, classPath);
compressFilePaths = isJava ? curentFilePath.replace(".java", ".class") : curentFilePath;
if (!isFileExist(compressFilePaths)) {
System.err.println("严重: File not Fond !!!"+curentFilePath.trim());
}
if(isJava){
//处理内部类
File _directory = new File(curentFilePath.substring(0,curentFilePath.lastIndexOf(BACKSLASH)).trim());
File[] _files=_directory.listFiles();
for (File f : _files) {
String _fname = f.getName();
if(_fname.endsWith(".class")&&_fname.startsWith(file.getName().replace(".java", "$"))){
compressFilePaths += " "+f.getPath();
}
}
}
}
else{
compressFilePaths = curentFilePath;
}
}
cmd += isDirectory ? " -ep1" : " -ep";
cmd += " -ap" + relativePath.substring(1);
cmd += compressedFile + compressFilePaths;
System.out.println(cmd);
Runtime run = Runtime.getRuntime();
try {
Process p = run.exec(cmd);
printOutStream(p.getInputStream());
if (p.waitFor() != 0) {
if (p.exitValue() == 1) {// p.exitValue()==0表示正常结束,1:非正常结束
System.out.println("命令执行失败!");
p.destroy();
}
}
} catch (Exception e) {
System.out.println("命令执行异常!");
e.printStackTrace();
}
}
private static void printOutStream(InputStream is) {
BufferedInputStream in = new BufferedInputStream(is);
BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
String lineStr;
try {
while ((lineStr = inBr.readLine()) != null)
// 获得命令执行后在控制台的输出信息
/** 经测试无法获取信息 **/
System.out.println("message: "+new String(lineStr.getBytes("ISO-8859-1"),"GBK"));// 打印输出信息
} catch (IOException e) {
e.printStackTrace();
}
}
private static boolean isFileExist(String filePath){
File file = new File(filePath.trim());
return file.exists();
}
public static class ClassPathEntry{
protected String kind;
protected String path;
protected String output;
public ClassPathEntry(){
}
public ClassPathEntry(String kind, String path){
this.kind = kind;
this.path = path;
}
public ClassPathEntry(String kind, String path,String output){
this.kind = kind;
this.path = path;
this.output = output;
}
public String getKind() {
return kind;
}
public String getPath() {
return path;
}
public String getOutput() {
return output;
}
}
}
最后附上项目结构图,该项目用了jdom来处理xml,我是把jdom的源代码放到了项目里一起打包。WebContent是测试用的目录。附件里附带项目工程。