Web 是一种分布式应用架构,旨在共享发布在网络上的各个Web服务器中的所有互相链接的信息。WWW(World Wide Web) 是指全球范围内的 Web,它以 Internet 为网络平台。

Internet 是来自世界各地的众多相互连接的计算机和其他设备的集合,而 WWW 则是 Internet 上的一种分布式应用架构。

《Tomcat 与 Java Web 开发技术详解(第2版)》讲述,为了能让 Web 服务器与 Web 应用这两个不同的软件系统协作,首先应该由一个中介方制订 Web 应用与 Web 服务器进行协作的标准接口,而Servlet 就是其中最主要的一个接口。中介方规定:

  • Web 服务器,可访问任意一个 Web 应用中实现的 Servlet 接口的类
  • Web 应用中用于被 Web 服务器动态调用的程序代码位于 Servlet 接口的实现类中。

而 SUN 公司,把一系列标准 Java 接口和规约,统称为Servlet 规范。它把能够发布和运行 JavaWeb 应用的 Web 服务器,统称为 Servlet 容器(最主要特征,是动态执行 JavaWeb 应用中的 Servlet 实现类中的程序代码)。由 Apache 开源软件组织创建的 Tomcat 是一个符合 Servlet 规范的优秀 Servlet 容器。

Chapter 3. Tomcat 服务器的安装与配置

3.1 Web 服务器软件概述

  • 服务器:安装了服务器软件的计算机。

  • 服务器软件:接收用户的请求,处理请求,做出响应。

    在 Web 服务器软件中,可以部署 Web 项目,让用户通过浏览器来访问这些项目

常见的 Java EE 的 Web 服务器软件:

JavaEE:Java 语言在企业级开发中使用的技术规范的总和,一共规定了 13 项大的规范。

TomcatwebLogicwebSphereJBOSS
所属组织Apache 基金组织oracle 公司IBM 公司JBOSS 公司
规模中小型 JavaEE 服务器大型 JavaEE 服务器大型 JavaEE 服务器大型 JavaEE 服务器
规范支持少量的 JavaEE 规范
如:Servlet / JSP
支持所有的 JavaEE 规范支持所有的 JavaEE 规范支持所有的 JavaEE 规范
费用免费开源收费收费收费

3.2 Tomcat 的下载安装与写作

下载

笔者下载的版本为:8.5.63,官网链接为:https://tomcat.apache.org/download-80.cgi,下载 Core 版(压缩包)即可

安装

将压缩包解压到自定义的目录(建议不要有中文和空格)即可。

解压后的 Tomcat 文件目录结构,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apache-tomcat-8.5.63/
├── bin/ # 存放可执行(脚本)文件,启动需从该目录下找到启动文件
│ ├── ...
│ ├── startup.bat # <------ Windows 启动文件
│ └── startup.sh # <------ Linux 启动文件

├── conf/ # 配置文件
├── lib/ # 依赖jar包
├── logs/ # 日志文件夹,用于监控或调试文件
├── temp/ # 临时文件夹
├── webapps/ # 重要:要在Tomcat上发布的JavaWeb应用文件(项目)
│ ├── docs/
│ ├── examples/ # Tomcat 内置项目
│ ├── ...
│ └── 用户创建的项目

├── work/ # Tomcat的工作目录,存放运行时的数据
├── ...

卸载

直接删除之前的目录即可,方便快捷。

3.3 纯 Tomcat 的启动与关闭

启动

双击运行 Tomcat安装目录\bin\startup.bat ,此时会弹出黑窗口

运行着bat文件,访问需用浏览器输入地址:

  • 访问自己的项目:http://localhost:8080
  • 访问别人的项目:http://别人的ip:8080

回车便能够看到如下网页:

启动遇到的问题:

  1. 黑窗口一闪而过:

    原因:可以去 Tomcat安装目录\logs 下查看报错信息,一般来说,是没有正确配置 JAVA_HOME 环境变量(请查阅 JavaSE学习笔记01 )

  2. 端口占用问题:

    暴力:在 CMD 窗口 敲下命令:netstat -ano。找到占用的端口号,并找到其对应的进程 ID,启动任务管理器,查看选择列(PID),杀死该进程。

    温柔(不建议):在 Tomcat安装目录\conf\servel.xml修改自身的端口号:

    1
    <Connector port="端口号" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8445" />

    一般会将 Tomcat 的默认端口号修改为 80 。 80 端口号是 HTTP 协议的默认端口号。

关闭

正常关闭,是点击 Tomcat安装目录\bin\shutdown.bat 或者 在黑窗口敲下快捷键 Ctrl+C

强制关闭,可以点击黑窗口的叉

3.4 项目的部署

  1. 直接将项目放到 Tomcat安装目录\webapps 目录下,以后要运行查看项目时,在浏览器输入地址:localhost:端口号/虚拟目录/资源文件名

    可以将 项目打包成 war 包,再将 war 包 放置到 webapps 目录下。(拷贝到 webapps目录后,war 包会自动地解压缩。

  2. Tomcat安装目录\conf\Catalina\localhost\ 创建任意名称的 XML 文件,在文件中编写:

    1
    <Context docBase = "项目的本地地址">

    此时,虚拟目录,即为 XML 文件的名称。浏览器访问的地址则为:localhost:端口号/xml文件名称/项目文件

  3. 将 Tomcat 集成到 IDEA 中:创建 Java EE 的项目,然后点击 IDEA 上方的 Run - Edit Configurations:

    最后要点击 应用、确定

3.5 IDEA 与 Tomcat 的相关配置

  1. IDEA 会为每一个 由Tomcat部署 的项目单独地建立一份配置文件。

    可通过控制台的 log 查看项目的 Tomcat 配置的根目录:

    Using CATALINA_BASE: "C:\Users\luffy\.IntelliJIdea2019.3\system\tomcat\_LearningJavaWeb"

    打开该目录后,进入 conf 文件夹便能看到 xml 配置文件

  2. 关于 IDEA 工作空间项目 与 Tomcat 部署的 Web 项目

    Tomcat 真正访问的是“ Tomcat 部署的 Web 项目”(其路径,类似于 E:\LearningJavaWeb\out\artifacts\MyEEProjects_war_exploded),"Tomcat 部署的 Web 项目” 也同时对应着 IDEA 工作空间项目 的 Web 目录下所有资源。而 IDEA 工作空间项目的 Web\WEB-INF 的资源不能通过启动服务后被浏览器直接访问。

    因此,不要将你的静态资源,放到 IDEA 工作空间项目的 Web\WEB-INF 目录下。

  3. 关于断点调试

    在某行代码打上断点后,使用“小虫子”启动 Debug模式。

Chapter 4. Servlet 基础

4.1 Servlet 概述

Servlet defines methods that all servlets must implement.

A servlet is a small Java program that runs within a Web server

实际上,Servlet 就是一个接口,定义了 Java 类能够被浏览器访问到(Tomcat 服务器识别到)的规则。我们需要自定义一个类,实现 Servlet 接口,覆写方法。

而 Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

Servlet 任务

  • 读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
  • 读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
  • 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
  • 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
  • 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。

4.2 快速入门

一、新建 Java EE 项目:

目录与项目名称创建后,点击 IDEA 上方的 Run - Edit Configurations ,再点击 Tomcat Server - Deployment ,可观察到,我们新建的项目显示为 “… war exploded”,同时下方的虚拟路径也已经配好了。

二、在 src 目录下定义一个类,实现 Servlet 接口:

src 目录,是在 开发 JavaWeb 应用阶段,开发人员自定义的目录,该目录存放所有 Java 类的源文件。当 Web 应用产品正式发布阶段,若不希望对外公开 Java 源代码,则可将 src 目录转移至其他地方。

注意, src目录下的文件,在部署时,会自动地放到**/web/WEB-INF/classes** 。

另外,类加载器只能获取 src 目录下的文件路径。

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
public class ServletDemo01 implements Servlet {

//初始化方法,在Servlet被创建时,执行。且只执行一次
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init....");
}

//获取ServletConfig对象(Servlet的配置对象)
@Override
public ServletConfig getServletConfig() {
return null;
}

//提供服务的方法,每一次Servlet被访问时,执行。且可以执行多次
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hello, Servlet");
}

//获取Servlet的一些信息,版本,作者等
@Override
public String getServletInfo() {
return null;
}

//销毁方法,在服务器正常关闭时,执行。且只执行一次。
@Override
public void destroy() {
System.out.println("destroy....");
}
}

TIPS:当写完 implements Servlet 时,观察到下方红线,按下快捷键Alt+Enter ,IDEA 就能帮你生成下列需覆写的方法。

三、配置 Servlet

web\WEB-INF 目录下的 web.xml 文档中配置:

web.xml 文档,由开发人员编写,供 Servlet 容器访问。web.xml 文件也称为 JavaWeb 应用的发布描述符文件,Servlet 容器在加载和启动 JavaWeb 应用时会读取它的 web.xml 文件,从中获取当前 Web 应用的发布信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"> <!--所有关于JavaWeb应用的具体配置元素都将加入到 <web-app> 元素中。-->

<!-- 配置Servlet -->
<servlet>
<servlet-name>Demo01</servlet-name> <!--定义Servlet的名字-->
<servlet-class>top.JoyDee.servlet.ServletDemo01</servlet-class> <!--它指定Servlet的完整类名,包括包的名字-->
</servlet>

<servlet-mapping>
<servlet-name>Demo01</servlet-name> <!--指定【带映射】的Servlet的名字-->
<url-pattern>/demo1</url-pattern> <!-- 该元素指定访问 Servlet 的相对URL路径,记得要以 "/" 开头 -->
</servlet-mapping>
</web-app>

<servlet> 元素中,可以加入 <load-on-startup> 元素,它指定当 Servlet 容器启动 Web 应用时,加载各个 Servlet 的次序。若值为正数或零,Servlet 容器优先加载数值小的 Servlet;若值为负数或没有设定,Servlet 容器将在 客户端首次访问 这个 Servlet 时加载它。

五、启动 Tomcat 服务器

点击IDEA右上方的绿色三角形运行,一会后浏览器会弹出一个 Web 应用的入口网页(其URL 是 Web 应用的根目录名)

index.jsp 就是默认的首页,对于Servlet 3.0,可以不勾选 Create web.xml

六、访问 Servlet

接着,在地址栏输入 URL 来请求访问 刚刚编写的 ServletDemo01,URL为: localhost:端口号/虚拟路径(一般为根目录名称)/刚刚填写的url-pattern

热部署:若希望文件发生更改后,无需关闭服务器再重新开启,可以设置如下:

image-20210221002720406

整个流程即为:

关于 Servlet 3.0

该版本的 Servlet ,支持注解配置,无需用 web.xml 配置了。

步骤:

  1. 创建 JavaEE项目,选择 Servlet 版本 3.0 以上(JavaEE 6开始支持),可以不勾选创建 web.xml

  2. 定义一个类,实现 Servlet 接口

  3. 覆写方法

  4. 在类上使用注解@WebServlet("Servlet的访问路径"),进行配置

    一个 Servlet 可以定义多个访问路径,如:@WebServlet({"/d4", "/dd4", "/ddd4"})

    其路径定义规则:

    1. /xxx(推荐):路径匹配
    2. /xxx/xxx:多层路径,目录结构,还能写成 /user/* (其中,* 为通配符,优先级较低)
    3. *.do:拓展名匹配,浏览器访问时要像这样输入 URL:.../demo.do
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
@WebServlet("/heeeeey")
public class ServletDemo02 implements Servlet {

@Override
public void init(ServletConfig servletConfig) throws ServletException {

}

@Override
public ServletConfig getServletConfig() {
return null;
}

@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("我是Servlet3.0!!!");
}

@Override
public String getServletInfo() {
return null;
}

@Override
public void destroy() {

}
}

4.2 JavaWeb应用的生命周期

JavaWeb 应用的生命周期,是由 Servlet 容器(Tomcat)来控制的,它包括三个阶段:

  • 启动阶段

    1. 把 web.xml 文件中的数据加载到内存中;
    2. 为 JavaWeb 应用创建一个 Servlet 上下文对象(ServletContext,Setvlet 通过该对象来访问容器为当前 Web 应用)
    3. 对所有的 Filter 进行初始化(暂不在这讨论)
    4. 对那些需在 Web 应用启动时就被初始化的 Servlet 进行初始化(具体见下节)。
  • 运行时阶段

    所有 Servlet 都处于待命状态,随时可以响应客户端的特定请求,提供相应的服务。

    如客户端请求的 Servlet 还不存在,Servlet 容器会先初始化 Setvlet,然后再调用它的 service() 服务方法

  • 终止阶段

    1. 销毁 JavaWeb 应用中所有处于运行时状态的 Servlet
    2. 销毁 JavaWeb 应用中所有处于运行时状态的 Filter
    3. 销毁所有与 JavaWeb 应用相关的对象,如 ServletContext 对象等,并且释放 Web 应用所占用的相关资源。

4.3 Servlet 的生命周期

Servlet 作为 JavaWeb 应用的最核心组件,其生命周期,同样由 Servlet 容器来控制,它包括三个阶段:

  • 初始化阶段:(init()

    下列情况之一,Servlet 才会进入初始化阶段:

    1. 当前 Web 应用处于运行时阶段,特定 Servlet 被客户端首次请求访问。(多数情况)
    2. 若在 web.xml 文件中为一个 Servlet 设置 <load-on-startup> 元素,则当 Servlet 容器启动 Servlet 所属 Web 应用时,就会初始化这个 Servlet。
    3. 当 Web 应用被重新启动时,Web 应用中所有 Servlet 都会在特定时刻被重新初始化
    1. Servlet 容器加载 Servlet 类,将它的 .class 文件中数据读入内存中;

    2. Servlet 容器创建 ServletConfig 对象(它包含了特定 Servlet 的初始化配置信息)。此外,Servlet 容器还会使得 ServletConfig 对象与当前 Web 应用的 ServletContext 对象进行关联。

    3. Servlet 容器创建 Servlet 对象

    4. Servlet 容器 调用 Servlet 对象的**init(ServletConfig config) 方法**,同时 ServletConfig 对象与 Servlet 对象进行关联。

  • 运行时阶段:(service()

    Servlet 可随时响应客户端的请求。当 Servlet 容器 接收到要求访问特定 Servlet 的客户请求时,Servlet 容器会创建针对于该请求的 ServletRequest 对象和 ServletResponse 对象,然后调用相应 Servlet 对象的 service() 方法

    service() 方法,从 ServletRequest 对象中获得客户请求信息并处理该请求,再通过 ServletResponse 对象生成相应结果。

    当Servlet 容器把 Servlet 生成的响应结果发送到客户时,Servlet 容器便销毁 ServletRequest 对象和 ServletResponse 对象。

  • 销毁阶段:(destroy()

    当 Web 应用被终止时,Servlet 容器会先调用 Web 应用中所有 Servlet 对象的**destroy() 方法**,释放 Servlet 所占用的资源。然后再销毁这些 Servlet 对象及与之关联的 ServletConfig 对象。

4.4 Servlet 体系结构

注意到:

  • GenericServlet(抽象类):将 Servlet 接口中其他的方法做了默认空实现,只留 service() 方法作为抽象方法
  • HttpServlet(抽象类):对HTTP协议的一种封装,简化了大量操作,定义类继承 HttpServlet 时,只需要覆写 doGet / doPost 方法即可

IDEA 快捷创建HttpServlet

右键新建类时,可选择 Create New Servlet,弹出窗口:

但要记得,要将注解改为:@WebServlet("/Servlet相对URL路径入口"),或者通过 IDEA 的模板格式修改:

4.5 ServletContext 接口

ServletContext 是 Servlet 与 Servlet 容器之间直接通信的接口。在 Servlet 容器在启动一个 Web 应用时,会为其创建一个 ServletContext 对象,每个 Web 应用都有唯一ServletContext 对象。

ServletContext对象,相当于 Web 应用的总管家,同一个 Web 应用中的所有 Servlet 对象都共享一个总管家(这些对象们,均可通过这个总管家来访问容器中的各种资源)

4.5.1 获取 ServletContext

  • 通过 request 对象来获取:

    1
    request.getServletContext();
  • 通过 HttpServlet 对象来获取:

    1
    this.getServletContext();

4.5.2 相关方法

(一)获取 MIME 类型:

  • String getMimeType(String file):传入参数为文件名称字符串,该方法能够通过文件名称识别并返回对应的 MIME 类型串。

(二)共享数据:

ServletContext 对象的范围是最大的。通过这个对象,能够获取所有用户所有请求的相关数据

  • setAttribute(String name,Object value)
  • getAttribute(String name)
  • removeAttribute(String name)

(三)获取文件的真实路径

  • getRealPath(String path):根据参数指定的虚拟路径,返回文件系统中的一个真实路径

    1
    2
    3
    4
    5
    6
    7
    ServletContext context = this.getServletContext(); //通过HttpServlet获取
    String realPath = context.getRealPath("/WEB-INF/classes/a.txt"); //找到src目录下资源,对应的真实路径
    File file = new File(realPath);
    System.out.println(realPath);
    /* 输出结果为:
    * E:\LearningJavaWeb\out\artifacts\MyEEProjects_war_exploded\WEB-INF\classes\a.txt
    */