环境准备

折腾

基本环境准备

要想在 VSCode 上搭建 Java Web 开发环境,需要如下前提条件:

  • JDK
  • Apache Tomcat
  • Maven

上述安装过于基础,不再赘述。

VSCode 配置

需要如下插件:

使用 Maven 插件创建 Java Web 项目

Maven 插件实际上是可有可无的,它本质上就是在调用安装的 Maven 来执行一些命令,只是每次都手动输入命令过于麻烦,故需要这么一个插件来自动化执行这些操作。

  1. 按下 <C-p>,输入 > Maven 后点击 “Maven: New project”。

  2. 选择 archetype。所谓 archetype,就是 Maven 提供的项目创建的一个模板,其本质就是为你创建一个像下面这样的项目结构:

<artifact-id>/
    ├───src
    │   └───main
    │       └───webapp
    │           │   index.jsp
    │           │
    │           └───WEB-INF
    │                   web.xml
    │
    │───target
    │   ├───classes
    │   └───test-classes
    └───pom.xml
创建项目
创建项目
选择 archetype
选择 archetype
指定 archetype 版本
指定 archetype 版本
指定 group id
指定 group id

Group id 代表了项目中所有源文件的包名前缀,我这里使用 fun.macrohard

指定 artifact id
指定 artifact id

Artifact id 代表了项目的标识,与上面所示的项目结构中的 <artifact-id> 相同,我这里使用 blog

snapshot 版本
snapshot 版本

项目快照版本,这一点暂时不涉及,保持默认即可。

确认
确认

最简 Java Web 项目

项目创建完毕后,要先写出一个最简单的 Java Web 项目,在这之前,需要修改 pom.xml 中的配置。

首先,需要修改文件中的 properties 选项,将 maven.compiler.sourcemaven.compiler.target 改为 1.8(或者 8 也可以,均代表 JDK 8)。这个两个字段代表的是源代码和目标文件使用的 JDK 版本,这个字段和实际安装的 JDK 版本没有关系,只要实际安装的是 JDK 8 以上的版本,都是可以编译的。

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

然后,在 dependencies 选项下新增依赖,引入所需的 Servlet API 包,这里是一个比较大的坑。 对于 Tomcat 4 ~ Tomcat 9,使用如下的依赖:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

对于 Tomcat 10 及以上,使用如下依赖。

<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>5.0.0</version>
    <scope>provided</scope>
</dependency>

该变动的原因是 Tomcat 10 废弃了原有的 javax 命名空间,事情的起因要追溯到 Oracle 将 Java EE 移交给 Eclipse,由于版权原因,Java EE 更名为了 Jakarta EE,引发了一系列后续的变动。

最后,也是最为关键的——找到 build 选项,在其中添加 sourceDirectory 字段(网上的一堆教程没有提及这一点,导致初次配置一直没有办法产生正确的打包,后续有时间一定要去看一下 Maven 的官方文档)。 sourceDirectory 的添加设计到项目文件结构,Maven 根据 archetype 自动创建的项目结构下并没有提供存放 Java 源码的目录,需要手动创建。具体来说,是先在 src/main/ 里创建 java/,然后在其中创建 fun/macrohard/,对应于项目的 group id。

为了让 Maven 能够正确编译 java/ 目录下的源代码,需要在 build 选项内添加:

<sourceDirectory>src/main/java</sourceDirectory>

然后,可以创建一个简易的 Hello.java 文件。需要注意,如果使用的是 Tomcat 10 以下的版本,下面的引入的包命名空间 jakarta 需要改为 javax:

package fun.macrohard;

import java.io.IOException;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;

@WebServlet("/hello")
public class Hello implements Servlet {
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("hello");
    }
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("hello");
    }
    @Override
    public String getServletInfo() {
        return null;
    }
    @Override
    public void destroy() {

    }
}

其中,@WebServelet("/hello") 注解表示当用户访问 <origin>/<artifact-id>/hello (对应到本文,也即 http://localhost:8080/blog/hello)时,服务器(Apache Tomcat)会将请求转发到 Hello 这个最简服务器,由 Hello.service 方法处理该请求。

然后,在左下角找到 Maven 选项卡,点开“Plugins > war > exploded”,右键后点击“Run”(这里的“Debug”与调试上面 Java 代码没有关系)来编译并“打包”本项目(实际并未打包)。

对基于 Servlet 的 Web 项目而言,打包格式称作 WAR(Web Application Archive),其本质上就是一个压缩包,部署到服务器后 Tomcat 将其解压并运行其中的 Java class,以这种方式打包 Java Web 程序的好处是部署方便。然而,实际开发中,项目文件是频繁变动的,这会给开发带来很多不便,因此产生了一种称为“exploded”打包方案,顾名思义就是把 WAR 包炸开(解压),换句话说就是压根不打包,这样在开发过程中就可以实现所谓的“热更新”。

打包
打包

Maven 会自动处理并编译项目,然后“打包”。在 target/blog/ 目录下,可以看到构建的所有文件,其中就有相应的 Java 字节码文件。

生成的目标文件
生成的目标文件

使用 Community Server Connectors 部署项目

首先,创建一个服务器。

创建服务器
创建服务器

接下来会询问是否要下载服务器,由于我们已经自行下载了 Tomcat,故选择使用硬盘上已有的服务器,并根据弹窗指定 Tomcat 服务器所在的根目录即可。选择完毕后,会询问是否需要配置一些东西,保持默认,直接点击“Finish”即可(在这个面板里也配置不了什么东西,端口号都没法改,要配置还是应该去改 Tomcat 的配置文件)。

使用现有服务器
使用现有服务器

然后,为服务器新增部署,部署类型选择为“Exploded”。

新增部署
新增部署
部署类型为 exploded
部署类型为 exploded

接下来会询问是否需要传递参数,这里没有,选择 No。

不需要参数
不需要参数

最后,我们就看到在服务器选项卡下新增了项目,并且状态为“Publish Required”,意思是我们需要“发布”内容,右键并点击“Publish Server(Full)”即可。

需要发布
需要发布
完整发布
完整发布

每当我们对项目本身做出改动,比如重新编译,都需要再次发布。发布后,服务器状态变为“Synchronized”。

这样,就成功地在服务器中部署了 Java Web 项目。

调试

运行这个 Java Web 项目不是我们的最终目标,而且我们也看不到任何运行效果(源代码内完全没有响应客户端请求)。我们想做的是调试这个最简单的 Java Web 项目。 Web 项目运行于 Tomcat 服务器上,调试的流程是 Tomcat 服务器以调试模式运行 Java Web 项目,调试器在某一个另外的端口监听调试请求。 当宿主机连接到调试器后,就可以正常调试了。

右键服务器选项并点击“Debug Server”,此时会弹出一个框,询问我们要给调试的项目起什么名字(这个名字和项目本身没有关系)。

调试服务器
调试服务器
调试器项目名
调试器项目名

在源代码中打好断点,然后访问 http://localhost:8080/blog/test,断点成功命中,折腾成功。

命中断点
命中断点

没有到此为止

这部分内容至关重要,调试完成后,一定要断开连接,然后关闭服务器,否则直接关掉 VSCode 而 socket 没有正确关闭的话是会造成泄漏的。服务器若不正常关闭,那么服务器即使处在关闭状态,其端口也可能被一直占用(Windows 的情况会好些,Linux 比较严重)。

断开连接
断开连接
关闭服务器
关闭服务器