java命令行构建

来源:互联网 发布:微信分享淘宝优惠券 编辑:程序博客网 时间:2024/06/18 09:32

java命令行构建


http://blog.csdn.net/mingover/article/details/57083176


我们平时编写和编译Java代码都是用ide,或用构建工具,ant或maven等.

但编译代码归根到底是用jdk的原始命令,如javac,java等。工具用多了,基本的处理都不懂了,这在遇到一些新情况或新工具的时候会捉襟见肘。

用java命令行是怎么做到 ant,maven等工具的作用的.

一个简单的javac编译

  • 新建两个文件夹,src和 build 
    src/com/yp/test/HelloWorld.java 
    build/
├─build└─src    └─com        └─yp            └─test                    HelloWorld.java
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • java文件非常简单
package com.yp.test;public class HelloWorld {    public static void main(String[] args) {        System.out.println("helloWorld");    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 编译:
javac src/com/yp/test/HelloWorld.java -d build
  • 1
  • 1

-d 表示编译到 build文件夹下

  • 查看build文件夹
├─build│  └─com│      └─yp│          └─test│                  HelloWorld.class│└─src    └─com        └─yp            └─test                    HelloWorld.java
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 运行文件
E:\codeplace\n_learn\java\javacmd> java com/yp/test/HelloWorld.class错误: 找不到或无法加载主类 build.com.yp.test.HelloWorld.class
  • 1
  • 2
  • 1
  • 2
  • 运行时要指定main
E:\codeplace\n_learn\java\javacmd\build> java com.yp.test.HelloWorldhelloWorld
  • 1
  • 2
  • 1
  • 2

如果多个类来编译,怎样安排路径呢 ?

编译

E:\codeplace\n_learn\java\javacmd>javac src/com/yp/test/HelloWorld.java -sourcepath src -d build -g
  • 1
  • 1

-sourcepath 表示 从指定的源文件目录中打到依赖项

运行,注意:运行在build目录下

E:\codeplace\n_learn\java\javacmd\build>java com.yp.test.HelloWorld
  • 1
  • 1

怎么打成jar包?

  • 生成:
E:\codeplace\n_learn\java\javacmd\build>jar cvf h.jar *
  • 1
  • 1
  • 运行:
E:\codeplace\n_learn\java\javacmd\build>java h.jar错误: 找不到或无法加载主类 h.jar
  • 1
  • 2
  • 1
  • 2
  • 这个错误是没有指定main类,所以类似这样来指定:
E:\codeplace\n_learn\java\javacmd\build>java -cp h.jar com.yp.test.HelloWorld
  • 1
  • 1

生成可以运行的jar包

需要指定jar包的应用程序入口点,用-e选项:

E:\codeplace\n_learn\java\javacmd\build> jar cvfe h.jar com.yp.test.HelloWorld *已添加清单正在添加: com/(输入 = 0) (输出 = 0)(存储了 0%)正在添加: com/yp/(输入 = 0) (输出 = 0)(存储了 0%)正在添加: com/yp/test/(输入 = 0) (输出 = 0)(存储了 0%)正在添加: com/yp/test/entity/(输入 = 0) (输出 = 0)(存储了 0%)正在添加: com/yp/test/entity/Cat.class(输入 = 545) (输出 = 319)(压缩了 41%)正在添加: com/yp/test/HelloWorld.class(输入 = 844) (输出 = 487)(压缩了 42%)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

直接运行

java -jar h.jar
  • 1
  • 1
  • 额外发现 
    指定了Main类后,jar包里面的 META-INF/MANIFEST.MF 是这样的, 比原来多了一行Main-Class….
Manifest-Version: 1.0Created-By: 1.8.0 (Oracle Corporation)Main-Class: com.yp.test.HelloWorld
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

如果类里有引用jar包呢?

先下一个jar包 这里直接下 log4j 
* main函数改成

import com.yp.test.entity.Cat;import org.apache.log4j.Logger;public class HelloWorld {    static Logger log = Logger.getLogger(HelloWorld.class);    public static void main(String[] args) {        Cat c = new Cat("keyboard");        log.info("这是log4j");        System.out.println("hello," + c.getName());    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

现的文件是这样的

├─build├─lib│      log4j-1.2.17.jar│└─src    └─com        └─yp            └─test                │  HelloWorld.java                │                └─entity                        Cat.java
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 这个时候 javac命令要接上 -cp ./lib/*.jar
E:\codeplace\n_learn\java\javacmd>javac -encoding "utf8" src/com/yp/test/HelloWorld.java -sourcepath src -d build -g -cp ./lib/*.jar
  • 1
  • 1
  • 运行, 
    要加上-cp, -cp 选项貌似会把工作目录给换了, 所以要加上 ;../build
E:\codeplace\n_learn\java\javacmd\build>java -cp ../lib/log4j-1.2.17.jar;../build com.yp.test.HelloWorld
  • 1
  • 1

结果:

log4j:WARN No appenders could be found for logger(com.yp.test.HelloWorld).log4j:WARN Please initialize the log4j system properly.log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.hello,keyboard
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

由于没有 log4j的配置文件,所以提示上面的问题,往 build 里面加上 log4j.xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"><log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>    <appender name="stdout" class="org.apache.log4j.ConsoleAppender">        <layout class="org.apache.log4j.PatternLayout">            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n" />        </layout>    </appender>    <root>        <level value="info" />        <appender-ref ref="stdout" />    </root></log4j:configuration>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

再运行

E:\codeplace\n_learn\java\javacmd>java -cp lib/log4j-1.2.17.jar;build com.yp.tes t.HelloWorld15:19:57,359 INFO  [HelloWorld] 这是log4jhello,keyboard
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3
  • 说明: 
    这个log4j配置文件,习惯的做法是放在src目录下, 在编译过程中 copy到build中的,但根据ant的做法,不是用javac的,而是用来处理,我猜测javac是不能copy的,如果想在命令行直接 使用,应该是用cp命令主动去执行 copy操作,

我们要用命令行来实现 源文件-> 可运行jar, 
我们可以参考ant的打jar包脚本。

ant是怎怎样构建的?

源文件->字节码->可执行jar 
源代码和上一篇是一样的,就多了个build.xml

  • 源文件,配置和lib
│  build.xml│├─build├─conf│      log4j.xml│├─lib│      log4j-1.2.17.jar│└─src    └─com        └─yp            └─test                │  HelloWorld.java                │                └─entity                        Cat.java
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • build.xml内容
<?xml version="1.0" encoding="UTF-8"?><!-- 定义一个工程,默认任务为jarFile。 --><project name="myh" default="jarFile" basedir=".">    <!-- 定义属性,打成jar包的名称。 -->    <property name="jarFileName" value="myh.jar"></property>    <!-- 定义路径,编译java文件时用到的jar包。 -->    <path id="project.lib">        <fileset dir="${basedir}/lib">            <include name="**/*.jar"/>        </fileset>    </path>    <!-- 定义任务,清空任务:清空原有的class文件,创建新的build路径。 -->    <target name="clean">        <delete dir="${basedir}/build" />        <mkdir dir="${basedir}/build" />    </target>    <!-- 定义任务,编译src文件夹中的java文件,编译后的class文件放到创建的文件夹下。 -->    <target name="compile" depends="clean">        <javac encoding="utf-8"  srcdir="${basedir}/src" destdir="${basedir}/build" includeantruntime="false">            <classpath refid="project.lib">            </classpath>        </javac>        <copy todir="${basedir}/build">            <fileset dir="${basedir}/conf">                <include name="**/**.*" />                <exclude name="**/*.java"/>               </fileset>        </copy>    </target>    <!-- 定义默认任务,将class文件集合成jar包。 -->    <target name="jarFile" depends="compile">        <!-- 删除原有jar包。 -->        <delete dir="${basedir}/${jarFileName}" />        <!-- 建立新jar包。 -->        <jar destfile="${basedir}/${jarFileName}"             basedir = "${basedir}/build"             includes = "**/**.*"            >           <manifest>             <attribute name="Main-Class" value="com.yp.test.HelloWorld"/>             <attribute name="Class-Path" value="lib/log4j-1.2.17.jar"/>             </manifest>        </jar>    </target></project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 结果会产生一个myh.jar
  • 运行与结果显示正常:
E:\codeplace\n_learn\java\javacmd>java -jar myh.jar10:43:51,453 INFO  [HelloWorld] 这是log4jhello,keyboard
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3
  • 说明 
    我们查看下jar包里面的MANIFEST.MF:
Manifest-Version: 1.0Ant-Version: Apache Ant 1.10.0Created-By: 1.8.0-b132 (Oracle Corporation)Main-Class: com.yp.test.HelloWorldClass-Path: lib/log4j-1.2.17.jar
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

我们打jar的时候,MANIFEST.MF也要搞成这样!!才能查运行

现在我们用命令行构建

我们直接用Python来写这些 各种各样的命令 
参考ant,会有,init,clean,compile,jar

废话不多说,直接上代码:

#!/usr/bin/python#coding:UTF-8import paramiko,datetime,os,loggingimport os,shutilimport sysimport time# 遍历文件夹def getFiles(dir, suffix):    res = []    for root, directory, files in os.walk(dir):        for filename in files:            name, suf = os.path.splitext(filename)            if suf == suffix:                res.append(os.path.join(root, filename))    return res# initjarFileName = "myh.jar"basedir = os.getcwd()mainclass = "com.yp.test.HelloWorld"# cleanlogging.error("当前工作目录:"+os.getcwd()+",清理build")shutil.rmtree(basedir+"\\"+"build")os.mkdir(basedir+"\\"+"build")# compilelogging.error("开始compile")# javac -encoding "utf8" src/com/yp/test/HelloWorld.java -sourcepath src -d build -g -cp ./lib/*.jar# os.system("javac -encoding utf8 src/com/yp/test/HelloWorld.java -sourcepath src -d build -g -cp ./lib/*.jar")# 把文件列表加入到sourcefiles 文件中file=open('sourcefiles','w')for tfile in getFiles(basedir+'/src/', '.java'):    file.writelines (tfile+'\n')file.close()# 执行编译os.system("javac -encoding utf8 -sourcepath src @sourcefiles -d build  -cp ./lib/*.jar ")# logging.error("开始copy配置文件")os.system("cp conf/* build/")# jar# 用python生成清单文件jarfile=open('manifest.mf','w')jarfile.writelines('Class-Path: ')for tfile in getFiles(basedir+'/lib/', '.jar'):    tmppath,filename = os.path.split(tfile)    tmpfilepath = 'lib/'+filename    logging.error(tmpfilepath)    jarfile.writelines(tmpfilepath)jarfile.writelines('\n\n')jarfile.close()# 打jar包os.chdir(basedir+"/build")os.system("jar cvfem "+basedir+"/"+jarFileName+"  "+mainclass+"  "+basedir+"/manifest.mf  *")os.chdir(basedir)# 清理os.remove(basedir+"/manifest.mf")os.remove(basedir+"/sourcefiles")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

需要的入参

jarFileName = “myh.jar” 
mainclass = “com.yp.test.HelloWorld”

使用情况:

一个python build.py命令,一个Java -jar myh.jar

E:\codeplace\n_learn\java\javacmd>python build.pyERROR:root:褰撳墠宸ヤ綔鐩綍:E:\codeplace\n_learn\jERROR:root:寮€濮媍ompileERROR:root:lib/log4j-1.2.17.jar已添加清单正在添加: com/(输入 = 0) (输出 = 0)(存储了 0%)正在添加: com/yp/(输入 = 0) (输出 = 0)(存储了 0%)正在添加: com/yp/test/(输入 = 0) (输出 = 0)(存储了 0正在添加: com/yp/test/entity/(输入 = 0) (输出 = 0)(存正在添加: com/yp/test/entity/Cat.class(输入 = 416) (正在添加: com/yp/test/HelloWorld.class(输入 = 961) (正在添加: log4j.xml(输入 = 1220) (输出 = 512)(压缩了E:\codeplace\n_learn\java\javacmd>java -jar myh.jar17:26:59,424 INFO  [HelloWorld] 这是log4jhello,keyboard
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

说明

  • javac 不能把源文件目录直接入参 
    要把 src的java文件全都搞成列表后入参给javac, 
    这里用python来生成src 目录和子目录下的 java 列表,扔到一个文件sourcefiles 
    sourcefiles会生成如下,过后会清理
E:\codeplace\n_learn\java\javacmd/src/com\yp\test\HelloWorld.javaE:\codeplace\n_learn\java\javacmd/src/com\yp\test\entity\Cat.java
  • 1
  • 2
  • 1
  • 2
  • 代码:https://github.com/huawumingguo/javacmd/

  • jar 添加清单文件 不生效 
    后来发现,,,是需要有回车(这个非常坑爹,错误也不提示)!!!关于清单文件,参考:http://www.jianshu.com/p/61cfa1347894

这里的思路是先 用python生成清单文件manifest.mf,然后jar命令中加上. 
manifest.mf会自动生成lib里面的jar包(最后会清理掉),如下

Class-Path: lib/log4j-1.2.17.jar

原创粉丝点击