我理解的WAR包

war包是什么?

war包就是一个web应用程序。不懂,我想知道详细一点,war包到底是个啥?来,从上之下,我们把问题逐步分解,先从最高的逻辑层面说起。

一. 为什么要打成war包

1.这个web应用是做什么的

开始的开始,我们不知道什么叫做web应用,我们只有一个需求:公司需要统计员工的基本信息。老板希望每个人登录一个固定的网站,填写表单信息之后,保存在一个地方,然后统一管理起来。

要满足这个需求,我们需要提供一个网页,这个网页上有很多表单要填写,填好了之后一点击,所有信息都没保存起来了。这个能提交保存数据的东西叫做web应用,可以知道,这个应用最少有一个网页,还需要能把网页数据保存下来的东西。

2.写出来以后给谁用

写出来当然是给员工用,把这个web应用放到网上,大家能通过网页开启这个应用就行。现在又有了一个新的需求,身在海外的其他分公司也想使用这个web应用,并且他们不希望自己的信息被别人知道,那么我就需要将这个应用”独立”地发给他们,让他们自己把这个东西用起来。所以,我们写的这个东西还可能被独立的拿到其他地方运行,因此我们的应用需要满足各种各样的环境。

接下来我们说点实际的东西。

二. 一个war包有什么样的结构

1. 一个web应用需要哪些文件

一个web应用,直观地来说,需要一个界面,这个界面是一个用户交互的界面,负责给用户提供信息输入的地方,所以一个web页面是要有的,这里设定为jsp页面,接着往下想,这些数据需要保存下来,那么需要一个界面背后的东西,这个东西其实就是一个java类,jsp把网页上的数据穿送给后台的java类,java类在得到这些数据之后再进行数据相关的工作,如存入数据库,给出相关统计数据等等,这里的java类比如servlet,那么接着你就会想,servlet是别人的东西啊,我们需要引入它,于是我们还需要一些外部依赖包,就是一些jar包。自己写的java类编译之后生成的是class文件。

感觉好像差不多了,该有的就有了,那我们开始着手给这些东西建立依赖关系吧,以便他们能正常工作。好,现在我们把自己想成是整个应用的组织人,我们要召集各位同事,jsp同志,java类同志来一起为公司的数据采集工作献身了,和之前一样,你能很直观的看到jsp在最前面工作,其他的都是幕后英雄,那后面的人怎么办,我也要把他们协调起来,于是我必须有一个list写明后面有谁在工作,在我们的应用里,后台的任务是java类来完成的,这里是servlet,于是就有了一个web.xml的文件来记录这个web应用中有哪些类,那么在jsp页面上只需要给出这个servlet的名字即可,然后我们在web.xml文件中详细记录这个servlet的各种信息,以便应用能够准确的使用它。那么你可能会想,为什么不将详细信息直接记录在jsp页面呢?我觉得可能是犹由于模块之间的低耦合要求吧。至于怎么工作呢,后面我们再来说。

2. 这些东西放在什么位置

我们已经有了应用需要的文件,接下来需要让这些文件各司其职,也就是把文件放在固定的位置,需要他们的时候去对应的位置找。那么这种位置关系就是应用的目录结构。一个基本的war包的目录结构如图1所示,根目录下有一个index.jsp文件,是应用的界面,当然你也可以加上css等让界面变得更炫。然后有一个WEB-INF文件夹,这个是war包的核心,在WEB-INF文件夹有web.xml文件,lib文件夹下存的是需要用到的外部依赖的jar包,classes下存的是带包名结构的java类,因为包名和文件目录是一一对应的关系,所以你在classes文件夹下就会看到和包名一致的目录结构,最后一层就是你编译好的class文件。


图1


3. 文件是怎么交互的

这些目录组织好了,那么文件是怎么交互的呢,这么多目录结构,程序怎么知道哪里是哪里,该去哪里找相关的class呢?这就和web.xml文件相关了,那么web.xml文件是怎么记录这些class的呢,下面我们来看一下:


从标签可以看出来,从第1行到第4行是servlet的注册信息,第2行给出了这个servlet的名字,是这个servlet编译后带包名的class类。那么是干什么的,先看看它里面有什么,和上面标签中的name是一致的,下面有个,看到url就想到一定是给出位置信息的标签,以便程序能够定位servlet。我们在jsp页面里,要提交一个表单,我们会这么写:

其中action属性后面的值给出了点击”提交”这个动作,之后的工作交给servlet文件下AcceptUserReg这个类来做,通过中的属性来定位servlet。那你可能要问了,我访问的是AcceptUserReg这个class,那为什么直接写AcceptUserReg呢?至少要有一个包名吧?其实的作用就在这里,在标签下我们给com.wzt.AcceptUserReg这个类起了个名字叫AcceptUserReg,也就是被注册了,在任何要用到com.wzt.AcceptUserReg的地方都能用AcceptUserReg代替,这里的jsp的URL·就是一个例子。

最后我们让代码跑起来试试。

1<servlet>

2    <servlet-name>AcceptUserReg</servlet-name>

3    <servlet-class>com.wzt.AcceptUserReg</servlet-class>

4</servlet>

5<servlet-mapping>

6    <servlet-name>AcceptUserReg</servlet-name>

7    <url-pattern>/com/wzt/AcceptUserReg</url-pattern>

8 </servlet-mapping>

从标签可以看出来,从第1行到第4行是servlet的注册信息,第2行给出了这个servlet的名字,是这个servlet编译后带包名的class类。那么是干什么的,先看看它里面有什么,和上面标签中的name是一致的,下面有个,看到url就想到一定是给出位置信息的标签,以便程序能够定位servlet。我们在jsp页面里,要提交一个表单,我们会这么写:

<form method="POST" action="servlet/AcceptUserReg" name="form1">

其中action属性后面的值给出了点击”提交”这个动作,之后的工作交给servlet文件下AcceptUserReg这个类来做,通过中的属性来定位servlet。那你可能要问了,我访问的是AcceptUserReg这个class,那为什么直接写AcceptUserReg呢?至少要有一个包名吧?其实的作用就在这里,在标签下我们给com.wzt.AcceptUserReg这个类起了个名字叫AcceptUserReg,也就是被注册了,在任何要用到com.wzt.AcceptUserReg的地方都能用AcceptUserReg代替,这里的jsp的URL·就是一个例子。

最后我们让代码跑起来试试。

三. war包怎么用起来

1. 怎么打包一个war包

打包war包很简单,首先需要把你的java文件编译成class文件,使用javac命令,记得跟上依赖的外部jar包,指定输出路径为WEB-INF下的classes,然后使用jar cvf命令将你的jsp文件和WEB-INF文件一起打包即可。

2. war怎么跑起来

其实这个问题有两种含义,第一,怎么运行一个war包。第二,Tomcat服务器是怎么样解析这个war包的。

对于第一个问题,我们只需要把打好的war包拷贝到Tomcat的webapps目录下,Tomcat服务器会自行解压这个包。

对于第二个问题,大致的流程是这样的:


图2

在开启这个web应用的时候,servlet容器扫描应用下的web.xml文件,注册所有的servlet,等待触发行为的发生,也就是等待用户提交等行为,一旦需要后台的处理,那么久轮到servlet干活了,可以看到, 下的给出的路径是经过处理后的路径,它被浏览器访问的路径所匹配,但是不是直接匹配,一个URL路径与web应用根目录做差之后,得到一个目标路径,拿这个路径和所有的servlet的匹配。比如我访问的是:

1. http://localhost:8080/FormDemo/com/wzt/servlet/AcceptUserReg

我们的应用根目录是:

2. http://localhost:8080/FormDemo

将1-2可以得到:

/com/wzt/servlet/AcceptUserReg

这就是待匹配的目标url,之后到了图中1的地方,匹配成功,然后找到同级子标签下的servlet名字,即图中步骤2,之后再去标签中找相同名字的servlet,到了步骤3,最后找到该标签同级子标签下的,完成第4个步骤之后,servlet容器便找到了该次响应的servlet类,执行这个类就能完成想要的工作了。

在明白了war包的结构和工作原理之后,我们来想想最开始的那个上层的逻辑问题?为什么一定要把这些文件打包呢?这个包怎么拿给别人用呢?其实你肯定已经感受到了,我们在把这一大堆的文件有组织有纪律的放在一起,通过打包的方式变成一个文件,那么别人需要的时候就传输这一个文件即可,越简单越不容易出错嘛。因为大家用的都是Tomcat,所以大家把拿到的这一个war包放在Tomcat下,Tomcat就会哗哗哗的自己运行了,多省心啊。

推荐阅读更多精彩内容