tomcat - 在 Windows 下搭建 Tomcat 环境

环境说明

  • 操作系统:Microsoft Windows 11 专业版
  • Tomcat:9.0.104

搭建流程

下载安装包

点击 https://tomcat.apache.org/ 到 Tomcat 官网,下载 Tomcat,我这里选择 Tomcat 9.0.x 最新版本 9.0.104,如下

示意图

示意图

安装软件包

这是绿色版软件,解压即可

启动服务器

  1. 需要事先安装 Java 开发环境(JDK) or 运行环境(JRE),并正确配置 JAVA_HOME or JRE_HOME(为什么?

  2. 然后到 bin 目录下,双击 startup.bat 即可执行(乱码了?

PS. 停止的话,只需要 Ctrl+C 终止,或者关闭黑窗口,或者执行 bin 目录下的 shutdown.bat 均可

访问服务器

打开浏览器,访问 http://localhost:8080/ 即可

示意图

扩展阅读

为什么要事先准备好 Java 开发环境(JDK) or 运行环境(JRE),并正确配置 JAVA_HOME or JRE_HOME?

那个 bat 脚本不容易理解,我这里以 sh 脚本解读

  • startup.sh:exec "$PRGDIR"/"$EXECUTABLE" start "$@"
    • catalina.sh:. "$CATALINA_HOME"/bin/setclasspath.sh
      • setclasspath.sh:这是关键代码,见如下详细解读,重点关注 _RUNJAVA 这个变量是怎么赋值的
    • catalina.sh:eval $_NOHUP "\"$_RUNJAVA\"",这里开始调用 java 命令启动项目了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 写的很清楚,如果两个环境变量均不存在,则直接退出
if [ -z "$JAVA_HOME" ] && [ -z "$JRE_HOME" ]; then
echo "Neither the JAVA_HOME nor the JRE_HOME environment variable is defined"
echo "At least one of these environment variable is needed to run this program"
exit 1
fi

# 如果JRE_HOME不存在,则使用JAVA_HOME的值
if [ -z "$JRE_HOME" ]; then
JRE_HOME="$JAVA_HOME"
fi

# 最终使用的就是JRE_HOME对应目录下的java可执行文件
# Set standard commands for invoking Java, if not already set.
if [ -z "$_RUNJAVA" ]; then
_RUNJAVA="$JRE_HOME"/bin/java
fi

为什么Tomcat启动,控制台会乱码,如何解决?

示意图

为什么会乱码呢?首先要明白,这些输出是 日志输出,因此,我们要关注 Windows 控制台的编码日志输出编码

  • Windows 控制台的编码:通过 chcp 命令(cmd)/ [console]::OutputEncoding 命令(PowerShell)查看,默认是 936(gb2312)

示意图

  • 在 conf/logging.properties 是日志配置,如下,很明显,打印到控制台使用的是 UTF-8 编码

示意图

知道原因了,我们有两种策略可以修复乱码

  • 将 Windows 编码设置为 UTF-8(代价太大,不知道会不会导致莫名其妙的问题,不推荐
  • 将日志的 ConsoleHandler 的 encoding 设置为与控制台一样的编码,即 GB2312推荐

【提示】这里的 encoding 可以写什么?

1
2
3
4
5
6
7
8
9
10
// ConsoleHandler -> StreamHandler -> Handler 
// -> Handler#encoding -> Handler#getEncoding -> StreamHandler#setOutputStream
// -> OutputStreamWriter#OutputStreamWriter(OutputStream out, String charsetName)
// -> StreamEncoder#forOutputStreamWriter(OutputStream var0, Object var1, String var2)
// -> Charset.isSupported(var3)

// 三大寻找路线
if ((cs = standardProvider.charsetForName(charsetName)) != null || // StandardCharsets
(cs = lookupExtendedCharset(charsetName)) != null || // ExtendedCharsets
(cs = lookupViaProviders(charsetName)) != null)

总之,经过调用链分析,最终能不能用还得看 Charset 支不支持。如下验证代码

1
2
3
public static void main(String[] args) {
System.out.println(Charset.isSupported("GB2312")); // GB2312最终由ExtendedCharsets处理了
}

示意图