Tomcat常见报错以及手动实现Tomcat

news2025/1/11 4:53:51

一.Tomcat的简单启动

1.安装Tomcat

2.Tomcat启动

1. 双击 bin 目录下的 startup.bat 文件

2. 输入 http://localhost:8080/,显示如下界面代表安装成功, 默认在 8080 端口

3. 注意,不要关闭黑窗口,关闭了,tomcat 服务就停止了.

3.曾经的启动失败案例

3.1Tomcat停止时报错(java.net.ConnectException: 拒绝连接 (Connection refused))

问题:没有关闭之前的Tomcat服务

解决办法:pkill -9 java的方式强制关闭tomcat服务,然后重新启动。

3.2启动Tomcat时终端显示乱码

...\conf\logging.properties配置文件中默认设置的UTF-8改为GBK

3.3Tomcat无法启动:

  • 问题: Tomcat启动失败,通常会在启动脚本或日志中显示错误消息。
  • 解决办法:
    • 检查端口冲突,确保Tomcat所需的端口没有被其他进程占用。
    • 检查server.xml配置文件,确保没有错误配置。
    • 检查Java环境变量(如JAVA_HOME)是否正确设置。
    • 查看Tomcat的日志文件以获取详细错误信息。

3.4内存溢出错误(OutOfMemoryError):

  • 问题: 应用程序使用的内存超出了可用内存限制。
  • 解决办法:
    • 增加Tomcat的JVM堆内存大小,通过修改catalina.shcatalina.bat中的-Xmx参数来实现。
    • 使用内存分析工具(如VisualVM)来查找内存泄漏问题。
    • 当然还可以优化代码,减少内存。嘿嘿嘿

3.5无法连接到数据库:

  • 问题: 应用程序无法连接到数据库。
  • 解决办法:
    • 检查数据库服务器是否正在运行。
    • 检查数据库连接字符串和凭据是否正确。
    • 确保数据库驱动程序JAR文件已正确放置在Tomcat的lib目录中。

4.解决问题大致思路:

4.1运行之后报错:

打开...\logs日志文件查看日志,查看出错的地方并对症下药。

4.2无法运行报错:

当我们点击startup.bat之后,黑屏一闪而逝,那么我们可以在startup.bat的末尾敲击pause之后,报错,当我们再次点击之后就会出现对应的错误。没有问题就会出现你的对应的配置文件,jdk之类的。如果还无法解决,看看server.xml中的具体配置是不是缺少某个文件或者文件位置安装错误。

二.Tomcat简单介绍

Tomcat 目录结构

1. server.xml 用于配置 tomcat 的基本设置(启动端口,关闭端口, 主机名)

2. wex.xml 用于指定 tomcat 运行时配置(比如 servlet 等..)

3. webapps 目录是存放 web 应用,就是网站,通常在我们的url后面添加/.....即可。

例如:localhost:8080/web/text.txt就是访问webapps的text.txt文件

三.Tomcat 服务中部署 WEB 应用

1.什么是Web应用

1.1 WEB应用是多个web资源的集合。简单的说,可以把web应用理解为硬盘上的一个目录, 这个目录用于管理多个web资源。

1.2 Web应用通常也称之为web应用程序,或web工程,通俗的说 就是网站

2.WEb应用组成

一个 WEB 应用由多个 WEB 资源或其它文件组成,包括 html 文件、css 文件、js 文件、动 态 web 页面、java 程序、支持 jar 包、配置文件等。开发人员在开发 web 应用时,按照规 定目录结构存放这些文件。否则,在把 web 应用交给 web 服务器管理时,不仅可能会使 web 应用无法访问,还会导致 web 服务器启动报错

3.JavaWeb程序/应用/工程目录结构

4.部署方式

4.1将 web 工程的目录拷贝到 Tomcat 的 webapps 目录

1. news Web工程(目前都是静态资源 html, 图片)

2. 将该news目录/文件夹 拷贝到 Tomcat 的webapps目录下

3. 浏览器输入: http://ip[域名]:port/news/子目录../文件名

4.2通过配置文件来部署

1.在Tomcat 下的 conf 目录\Catalina\localhost\ 下,配置文件,比如hong.xml(提醒:知道 Tomcat通过配置,可以把一个web应用,映射到指定的目录,可以解决磁盘空间分配

2.访问web工程: http://ip[域名]:port/hong/index.html 就表示访问 D:\album 目录下的 index.html

4.3ROOT 的工程的访问

1. 在浏览器地址栏中输入访问地址如下:http://ip[域名]:port,没有Web工程/应用名时,默认访问的是 ROOT 工程

2. 在浏览器地址栏中输入的访问地址如下: http://ip[域名]:port/工程名/ ,没有资源名, 默认访问 index.jsp 页面

4.4maven

我们可以通过package打包成war格式或者jar格式返给webapps里面进行编译

四.底层逻辑实现

思考问题: Tomcat 底层实现 和 调用到 Servlet 流程?

1.Tomcat 整体架构分析

Tomcat 有三种运行模式(BIO, NIO, APR), 因为准备要说的是 Tomcat 如何接收客户端请求,解析请求, 调用 Servlet , 并返回结果的机制流程, 采用 BIO 线程模型来模拟.

2.手动实现Tomcat 底层机制+ 自己设计 Servlet

1.编写自己 Tomcat, 能给浏览器返回 Hi, Hong

1.1分析

1.2代码实现
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author hong
 * @version 1.0
 * 这是第一个版本的tomcat ,可以完成,接收浏览器的请求,并返回信息
 */
public class HspTomcatV1 {
    public static void main(String[] args) throws IOException {

        //1. 创建ServerSocket, 在 8080端口监听
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("=======mytomcat在8080端口监听======");
        while (!serverSocket.isClosed()) {

            //等待浏览器/客户端的连接
            //如果有连接来,就创建一个socket
            //这个socket就是服务端和浏览器端的连接/通道
            Socket socket = serverSocket.accept();

            //先接收浏览器发送的数据
            //inputStream 是字节流=> BufferedReader(字符流)

            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader =
                    new BufferedReader(new InputStreamReader(inputStream, "utf-8"));

            String mes = null;
            System.out.println("=======接收到浏览器发送的数据=======");
            //循环的读取
            while ((mes = bufferedReader.readLine()) != null) {
                //判断mes的长度是否为0
                if (mes.length() == 0) {
                    break;//退出while
                }
                System.out.println(mes);
            }

            //我们的tomcat会送-http响应方式
            OutputStream outputStream = socket.getOutputStream();
            //构建一个http响应的头
            //\r\n 表示换行
            //http响应体,需要前面有两个换行 \r\n\r\n
            String respHeader = "HTTP/1.1 200 OK\r\n" +
                    "Content-Type: text/html;charset=utf-8\r\n\r\n";
            String resp = respHeader + "hi, hong";

            System.out.println("========我们的tomcat 给浏览器会送的数据======");
            System.out.println(resp);

            outputStream.write(resp.getBytes());//将resp字符串以byte[] 方式返回

            outputStream.flush();
            outputStream.close();
            inputStream.close();
            socket.close();
            // //等会
            // inputStream.close();
            // socket.close();
        }
    }
}

2.使用 BIO 线程模型,支持多线程

2.1BIO 线程模型介绍

2.2分析

2.3代码实现
/**
 * @author hong
 * @version 1.0
 */
public class HspTomcatV2 {
    public static void main(String[] args) throws IOException {
        //在8080端口监听
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("=======hongtomcatV2 在8080监听=======");
        //只要 serverSocket没有关闭,就一直等待浏览器/客户端的连接
        while (!serverSocket.isClosed()) {
            //1. 接收到浏览器的连接后,如果成功,就会得到socket
            //2. 这个socket 就是 服务器和 浏览器的数据通道
            Socket socket = serverSocket.accept();
            //3. 创建一个线程对象,并且把socket给该线程
            //  这个是java线程基础
            HspRequestHandler hspRequestHandler =
                    new HspRequestHandler(socket);
            new Thread(hspRequestHandler).start();

        }
    }
}

3.处理 Servlet

3.1Servlet 生命周期-回顾

3.2分析

浏览器请求 http://localhost:8080/hongCalServlet, 提交数据,完成计算 任务,如果 servlet 不存在,返回 404

3.3代码
package com.hspedu.tomcat;

import com.hspedu.tomcat.handler.HspRequestHandler;
import com.hspedu.tomcat.servlet.HspHttpServlet;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.servlet.Filter;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author hong
 * @version 1.0
 * 第3版的Tomcat, 实现通过xml+反射来初始化容器
 */
public class HspTomcatV3 {

    //1. 存放容器 servletMapping
    // -ConcurrentHashMap
    // -HashMap
    // key            - value
    // ServletName    对应的实例

    public static final ConcurrentHashMap<String, HspHttpServlet>
            servletMapping = new ConcurrentHashMap<>();


    //2容器 servletUrlMapping
    // -ConcurrentHashMap
    // -HashMap
    // key                    - value
    // url-pattern       ServletName

    public static final ConcurrentHashMap<String, String>
            servletUrlMapping = new ConcurrentHashMap<>();


    //你可以这里理解session, tomcat还维护一个容器
    public static final ConcurrentHashMap<String, HttpSession>
            sessionMapping = new ConcurrentHashMap<>();
    

    //你可以这里理解filter, tomcat还维护了filter的容器
    public static final ConcurrentHashMap<String, String>
            filterUrlMapping = new ConcurrentHashMap<>();

    public static final ConcurrentHashMap<String, Filter>
            filterMapping = new ConcurrentHashMap<>();
    //变强..
    public static void main(String[] args) {
        HspTomcatV3 hspTomcatV3 = new HspTomcatV3();
        hspTomcatV3.init();
        //启动hsptomcat容器
        hspTomcatV3.run();
    }


    //启动HspTomcatV3容器
    public void run() {

        try {
            ServerSocket serverSocket = new ServerSocket(8080);
            System.out.println("=====hongtomcatv3在8080监听======");
            while (!serverSocket.isClosed()) {
                Socket socket = serverSocket.accept();
                HspRequestHandler hspRequestHandler =
                        new HspRequestHandler(socket);
                new Thread(hspRequestHandler).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //直接对两个容器进行初始化
    public void init() {
        //读取web.xml => dom4j =>
        //得到web.xml文件的路径 => 拷贝一份.
        String path = HspTomcatV3.class.getResource("/").getPath();
        //System.out.println("path= " + path);
        //使用dom4j技术完成读取
        SAXReader saxReader = new SAXReader();
        //困难->真的掌握
        try {
            Document document = saxReader.read(new File(path + "web.xml"));
            System.out.println("document= " + document);
            //得到根元素
            Element rootElement = document.getRootElement();
            //得到根元素下面的所有元素
            List<Element> elements = rootElement.elements();
            //遍历并过滤到 servlet servlet-mapping
            for (Element element : elements) {
                if ("servlet".equalsIgnoreCase(element.getName())) {
                    //这是一个servlet配置
                    //System.out.println("发现 servlet");
                    //使用反射将该servlet实例放入到servletMapping
                    Element servletName = element.element("servlet-name");
                    Element servletClass = element.element("servlet-class");
                    servletMapping.put(servletName.getText(),
                            (HspHttpServlet) Class.forName(servletClass.getText().trim()).newInstance());
                } else if ("servlet-mapping".equalsIgnoreCase(element.getName())) {
                    //这是一个servlet-mapping
                    //System.out.println("发现 servlet-mapping");

                    Element servletName = element.element("servlet-name");
                    Element urlPatter = element.element("url-pattern");
                    servletUrlMapping.put(urlPatter.getText(), servletName.getText());

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //验证,这两个容器是否初始化成功
        System.out.println("servletMapping= " + servletMapping);
        System.out.println("servletUrlMapping= " + servletUrlMapping);
    }
}
3.4测试
 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1030621.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LabVIEW开发基于物联网的多功能功率分析仪

LabVIEW开发基于物联网的多功能功率分析仪 根据技术规则&#xff0c;电气元件网络中的单个被创建为在标称正弦波振动制造频率下运行。失真顺序的电流和电压波与正弦波不同&#xff0c;它们或多或少地扭曲成形状。它是由交流网络中非线性组件的存在引起的&#xff0c;例如静态转…

R语言进行孟德尔随机化+meta分析(1)---meta分析基础

目前不少文章用到了孟德尔随机化meta分析&#xff0c;今天咱们也来介绍一下&#xff0c;孟德尔随机化meta其实主要就是meta分析的过程&#xff0c;提取了孟德尔随机化文章的结果&#xff0c;实质上就是个meta分析&#xff0c;不过多个孟德尔随机化随机化的结果合并更加加强了结…

月木学途开发 4.公告模块

概述 效果图 数据库设计 DROP TABLE IF EXISTS announcement; CREATE TABLE announcement (announcementId int(11) NOT NULL AUTO_INCREMENT,announcementTitle varchar(255) DEFAULT NULL,announcementTime varchar(255) DEFAULT NULL,announcementContent longtext,PRIMAR…

计算机组成原理——基础入门总结(二)

上一期的路径&#xff1a;基础入门总结&#xff08;一&#xff09; 目录 一.输入输出系统和IO控制方式 二.存储系统的基本概念 三.cache的基本概念和原理 四.CPU的功能和基本结构 五.总线概述 一.输入输出系统和IO控制方式 IO设备又可以被统一称为外部设备~ IO接口&…

Jetpack:在数据变化时如何优雅更新Views数据

本文讲的是关于Jetpack的架构组件LiveData&#xff0c;LiveData是Lifecycle-aware 组件的一个应用&#xff0c;这意味着LiveData遵守Activity、Fragment和Service等组件的生命周期&#xff0c;在它们生命周期处于活跃状态&#xff08;CREATED和RESUMED&#xff09;才进行更新Vi…

《计算机视觉中的多视图几何》笔记(8)

8 More Single View Geometry 本章主要讲述除了点以外的几何体&#xff0c;在投影变换下的性质。这些几何体包括&#xff1a;平面&#xff0c;线&#xff0c;圆锥曲线&#xff0c;二次曲线。 讲到这里就明白了&#xff0c;为什么投影几何这么重要&#xff0c;因为摄像机就是一…

VLANIF配置

目录 实验原理&#xff1a; 案例&#xff1a; 设备配置 用ping验证不同vlan之间实现相互通信 实验原理&#xff1a; VLANIF接口是一种第三层的逻辑接口&#xff0c;用于在第三层实现不同VLAN 之间的通信。 每个VALN有一个VLANIF接口&#xff0c;并通过该接口在网络层转发…

【操作系统笔记】缓存一致性

CPU 核心之间数据如何传播 高速缓存中的值被修改了&#xff0c;那么怎么同步到内存中呢&#xff1f; ① 写直达&#xff08;Write-Through&#xff09;② 写回&#xff08;Write-Back&#xff09; 写直达&#xff08;Write-Through&#xff09; 简单&#xff0c;但是很慢&am…

《Kubernetes部署篇:Ubuntu20.04基于containerd二进制部署K8S 1.25.14集群(多主多从)》

一、架构图 如下图所示&#xff1a; 二、部署说明 2.1、部署流程 1、系统环境初始化&#xff0c;主要包括 主机名设置、主机hosts解析、关闭防火墙、关闭swap分区、修改系统参数、时间时区同步、修改内核参数、启用ipvs模式。 2、使用一键生成K8S集群证书工具创建证书文件。…

vue页面嵌入飞书网页组件,用于在类似ERP,OA等系统中展示在线文档

先展示最终效果(就是在vue页面中,内嵌了一块ifream页面): 1. 注册进入飞书开放平台,地址为: 飞书开放平台 2.进入开放平台后,选择--创建企业自建应用--创建网页应用,然后在主页面记住该应用的appId和appSecret参数,后面要用 3.然后注意一点的是,因为后面的授权等逻辑我们一般…

Android设计支持库

本文所有的代码均存于 https://github.com/MADMAX110/BitsandPizzas 设计支持库&#xff08;Design Support Library&#xff09;是 Google 在 2015 年的 I/O 大会上发布的全新 Material Design 支持库&#xff0c;在这个 support 库里面主要包含了 8 个新的 Material Design …

clickhouse简单安装部署

目录 前言(来源于官方文档)&#xff1a; 一.下载并上传 1.下载地址&#xff1a;点我跳转下载 2.上传至Linux 二.解压和配置 1.解压顺序 注意&#xff1a;必须按照以下顺序解压&#xff0c;并且每解压一个都要执行该解压后文件的install/doinst.sh文件 解压步骤&#xff…

antd-design-vue Table组件全局配置(分页器...)

描述&#xff1a;该框架许多默认配置好像还不支持&#xff0c;一般都是挨个使用挨个配置。我的项目中也遇到了类似的情况&#xff0c;但是当需求发生变化时&#xff0c;代码所有的组件使用则都需要修改&#xff0c;这种方式真的很不礼貌。 《我为了一口醋包了顿饺子》 需求是将…

MQ - 19 安全_限流方案的设计

文章目录 导图Pre概述集群中的数据加密加密算法分类消息队列限流机制思考单机限流全局限流全局限流还是单机限流?对哪些资源和维度进行限流发生限流后怎么处理消息队列全局限流设计单机限流方案全局限流方案消息队列的服务降级配置 Broker 的 CPU 或内存的使用率额度配置磁盘保…

C语言每日一题(5):求两个数二进制中不同位的个数

文章主题&#xff1a;求两个数二进制中不同位的个数&#x1f525;所属专栏&#xff1a;C语言每日一题&#x1f4d7;作者简介&#xff1a;每天不定时更新C语言的小白一枚&#xff0c;记录分享自己每天的所思所想&#x1f604;&#x1f3b6;个人主页&#xff1a;[₽]的个人主页&a…

BOA服务器移植

BOA服务器移植 1、源码下载 http://www.boa.org/ News! (last updated 23 February 2005) Latest Released Version (0.94.13) here (signature here) --- 下载地址1.1 boa简介&#xff1a; 其可执行代码只有大约60KB左右&#xff0c;Boa是一个单任务的HTTP服务器&#xff…

MyBatisPlus(五)配置表名前缀:table-prefix

说明 数据库中的表名&#xff0c;和项目中的实体类名&#xff0c;并不符合默认对应规则。所有表都有同样的前缀&#xff0c;而实体类名是和表名去掉前缀后的部分对应的。 解决方案 配置全局表名前缀&#xff0c;使实体类名对应的表名&#xff0c;自动加上一段前缀。 限制 …

JSON 串和 Java 对象的相互转换

JSON 串和 Java 对象的相互转换 以 json 格式的数据进行前后端交互 前端发送请求时&#xff0c;如果是复杂的数据就会以 json 提交给后端&#xff1b; 而后端如果需要响应一些复杂的数据时&#xff0c;也需要以 json 格式将数据响应回给浏览器 为达到以上目的就需要重点学习…

基于微信小程序的美术馆预约平台设计与实现(源码+lw+部署文档+讲解等)

前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb;…

Linux_9_网络协议和管理

目录 1网络基础1.1 网络概念1.2常见的网络物理组件1.3网络应用程序1.3.1各种网络应用1.3.2应用程序对网络的要求 1.4网络的特征1.4.1速度(带宽)1.4.2网络拓扑 1.5网络1.5.1网络准和分层1.5.2开放系统互联OSI1.5.3网络的通信过程1.5.3.1数据封装和数据解封1.5.3.2协议数据单元PD…