java的解释执行过程及Tomcat部署

前言

  最近做Gitlab CI的自动测试方面的工作,用简单的Java工程来做测试,在学习Gitlab CI和Docker的过程中又回顾了一下Java的编译,解释,执行的过程。以前做Java的项目多是借助IDE,有种感觉就是离开IDE就不会做Java开发了。这次因为Docker自动测试无法使用IDE,被迫回顾了一下如何用命令行去运行Java程序,以及如何部署在Tomcat上,挺有意义的。

编译成.class文件

  严格来说Java不算纯粹的解释性语言,我觉得是介乎编译与解释性语言的一种。因为它在解释执行之前需要先编译成字节码。这种字节码就是.class文件。我们平常写的源代码都是.java文件,要执行它们,首先得编译成.class文件。

  编译成字节码很简单,只需用javac指令。看下面这个例子:

1
javac -d classes -cp "web/WEB-INF/lib/*:classes" src/weibo/servlet/*

  这行指令最核心的就是第一个词javac以及最后一个目录结构src/weibo/servlet/*。javac是编译成字节码的程序,最后面的目录结构下的文件就是待编译的.java文件。上例就是要把src/weibo/servlet/目录下的所有文件编译成字节码。我们还注意到,除了javac以及目标.java文件以外,中间还有一些参数。这些参数主要是用于提供.java文件里import的其他java类。

  如果待编译的.java文件没有额外引用其他类,或者引用的只是java核心包里的类,中间的这些参数可以统统省掉。但如果用到其他类,则必须提供这些类的.class文件或者所属的jar包。jar包实际上是把一些.class文件打包成一个文件。

  因此编译成.class文件也是有先后顺序的,必须先把待编译的类引入的其他类编译好。

  我们来看一看中间的这些参数。-d后面跟的目录便是我们希望的编译好的.class文件存放的地方。-cp后面跟的参数指定classpath,即引入的.class文件或jar包的目录。如果有多个目录,则在linux系统下用:分隔,windows系统下用;分隔。

解释执行.class文件

  很多人认为Java是解释性语言,就是因为它是在运行时边执行边用java虚拟机解释.class文件的字节码。多次运行同一段代码则需要多次解释,不像编译性语言一样预先编译成机器语言。解释执行.class文件只需用java指令。看下面的例子:

1
java -cp "classes:web/WEB-INF/lib/*" org.junit.runner.JUnitCore weibo.servlet.SignUpAndLoginTest

  上例的意思是我们要用org.junit.runner.JunitCore这个类对weibo.servlet.SignUpAndLoginTest这个类进行单元测试。没有接触过单元测试的只需简单地理解为我们需要执行org.junit.runner.JunitCore这个类,同时需要传入参数,这个参数是weibo.servlet.SignUpAndLoginTest这个类。如果这些类的.class文件不在当前目录下,则需要用-cp指定它们所在的classpath。我们指定类必须完整写出package结构,package结构与目录结构是等同的,上例相当于我们要找的类分别是classes/weibo/servlet/SignUpAndLoginTest和web/WEB-INF/lib/junit-4.11.jar里的org/junit/runner/JunitCore。package目录结构必须与.class存放的目录结构一致。

打成jar包

  有时候我们需要将编译好的.class文件打包,便于迁移,管理与部署。打包很简单,用jar指令即可。

1
jar -cvfe ../binaries/Server.jar buptchat.server.Server buptchat/server/*

  我们先指定打出来的包要放在哪个目录下,以及叫什么名字,上例则是存放在../binaries里的Server.jar。-e指令指定入口类,即运行jar包时执行的main方法所在的类,上例是bupt.server.Server,最后一个参数是指定那些文件需要被打包。

Tomcat部署

  Tomcat是一个java web container,核心功能是用于处理jsp以及servlet,以及内置了http服务器,拥有处理http请求和回应的功能。

打成war包

  将开发好的java web程序部署在Tomcat上,最简单的方法是将其打成war包,然后扔在tomcat的webapps目录下,tomcat启动时候会自动将其解压,便可以访问里面的jsp和servlet了。

  war包是有一定网络扩展功能的jar包。打成war包非常简单,与打jar包一样,都是用jar指令。如下例:

1
jar -cvf weibo.war *

  将当前目录及其子目录的所有文件打成weibo.war这个包,并存放在当前目录下。

war包内的目录结构

  工程目录必须满足一定的目录结构。根目录一般放jsp和一些资源文件,例如css和javascript文件。也可以把jsp文件放在某个目录内。根目录下有一个固定的WEB-INF目录,里面有web.xml文件,主要是首页和servlet以及filter的一些映射配置。

  一般我们还需要在WEB-INF目录下建两个文件夹,分别是lib和classes,存放服务器要用到的java字节码。lib放jar包,classes放编译好的.class文件。

  只要满足这个目录结构,Tomcat便知道怎么用我们这个工程了。