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


    一.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代码实现
    1. import java.io.*;
    2. import java.net.ServerSocket;
    3. import java.net.Socket;
    4. /**
    5. * @author hong
    6. * @version 1.0
    7. * 这是第一个版本的tomcat ,可以完成,接收浏览器的请求,并返回信息
    8. */
    9. public class HspTomcatV1 {
    10. public static void main(String[] args) throws IOException {
    11. //1. 创建ServerSocket, 在 8080端口监听
    12. ServerSocket serverSocket = new ServerSocket(8080);
    13. System.out.println("=======mytomcat在8080端口监听======");
    14. while (!serverSocket.isClosed()) {
    15. //等待浏览器/客户端的连接
    16. //如果有连接来,就创建一个socket
    17. //这个socket就是服务端和浏览器端的连接/通道
    18. Socket socket = serverSocket.accept();
    19. //先接收浏览器发送的数据
    20. //inputStream 是字节流=> BufferedReader(字符流)
    21. InputStream inputStream = socket.getInputStream();
    22. BufferedReader bufferedReader =
    23. new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
    24. String mes = null;
    25. System.out.println("=======接收到浏览器发送的数据=======");
    26. //循环的读取
    27. while ((mes = bufferedReader.readLine()) != null) {
    28. //判断mes的长度是否为0
    29. if (mes.length() == 0) {
    30. break;//退出while
    31. }
    32. System.out.println(mes);
    33. }
    34. //我们的tomcat会送-http响应方式
    35. OutputStream outputStream = socket.getOutputStream();
    36. //构建一个http响应的头
    37. //\r\n 表示换行
    38. //http响应体,需要前面有两个换行 \r\n\r\n
    39. String respHeader = "HTTP/1.1 200 OK\r\n" +
    40. "Content-Type: text/html;charset=utf-8\r\n\r\n";
    41. String resp = respHeader + "hi, hong";
    42. System.out.println("========我们的tomcat 给浏览器会送的数据======");
    43. System.out.println(resp);
    44. outputStream.write(resp.getBytes());//将resp字符串以byte[] 方式返回
    45. outputStream.flush();
    46. outputStream.close();
    47. inputStream.close();
    48. socket.close();
    49. // //等会
    50. // inputStream.close();
    51. // socket.close();
    52. }
    53. }
    54. }

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

    2.1BIO 线程模型介绍

    2.2分析

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

    3.处理 Servlet

    3.1Servlet 生命周期-回顾

    3.2分析

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

    3.3代码
    1. package com.hspedu.tomcat;
    2. import com.hspedu.tomcat.handler.HspRequestHandler;
    3. import com.hspedu.tomcat.servlet.HspHttpServlet;
    4. import org.dom4j.Document;
    5. import org.dom4j.DocumentException;
    6. import org.dom4j.Element;
    7. import org.dom4j.io.SAXReader;
    8. import javax.servlet.Filter;
    9. import javax.servlet.http.HttpSession;
    10. import java.io.File;
    11. import java.io.IOException;
    12. import java.net.MalformedURLException;
    13. import java.net.ServerSocket;
    14. import java.net.Socket;
    15. import java.util.List;
    16. import java.util.concurrent.ConcurrentHashMap;
    17. /**
    18. * @author hong
    19. * @version 1.0
    20. * 第3版的Tomcat, 实现通过xml+反射来初始化容器
    21. */
    22. public class HspTomcatV3 {
    23. //1. 存放容器 servletMapping
    24. // -ConcurrentHashMap
    25. // -HashMap
    26. // key - value
    27. // ServletName 对应的实例
    28. public static final ConcurrentHashMap
    29. servletMapping = new ConcurrentHashMap<>();
    30. //2容器 servletUrlMapping
    31. // -ConcurrentHashMap
    32. // -HashMap
    33. // key - value
    34. // url-pattern ServletName
    35. public static final ConcurrentHashMap
    36. servletUrlMapping = new ConcurrentHashMap<>();
    37. //你可以这里理解session, tomcat还维护一个容器
    38. public static final ConcurrentHashMap
    39. sessionMapping = new ConcurrentHashMap<>();
    40. //你可以这里理解filter, tomcat还维护了filter的容器
    41. public static final ConcurrentHashMap
    42. filterUrlMapping = new ConcurrentHashMap<>();
    43. public static final ConcurrentHashMap
    44. filterMapping = new ConcurrentHashMap<>();
    45. //变强..
    46. public static void main(String[] args) {
    47. HspTomcatV3 hspTomcatV3 = new HspTomcatV3();
    48. hspTomcatV3.init();
    49. //启动hsptomcat容器
    50. hspTomcatV3.run();
    51. }
    52. //启动HspTomcatV3容器
    53. public void run() {
    54. try {
    55. ServerSocket serverSocket = new ServerSocket(8080);
    56. System.out.println("=====hongtomcatv3在8080监听======");
    57. while (!serverSocket.isClosed()) {
    58. Socket socket = serverSocket.accept();
    59. HspRequestHandler hspRequestHandler =
    60. new HspRequestHandler(socket);
    61. new Thread(hspRequestHandler).start();
    62. }
    63. } catch (IOException e) {
    64. e.printStackTrace();
    65. }
    66. }
    67. //直接对两个容器进行初始化
    68. public void init() {
    69. //读取web.xml => dom4j =>
    70. //得到web.xml文件的路径 => 拷贝一份.
    71. String path = HspTomcatV3.class.getResource("/").getPath();
    72. //System.out.println("path= " + path);
    73. //使用dom4j技术完成读取
    74. SAXReader saxReader = new SAXReader();
    75. //困难->真的掌握
    76. try {
    77. Document document = saxReader.read(new File(path + "web.xml"));
    78. System.out.println("document= " + document);
    79. //得到根元素
    80. Element rootElement = document.getRootElement();
    81. //得到根元素下面的所有元素
    82. List elements = rootElement.elements();
    83. //遍历并过滤到 servlet servlet-mapping
    84. for (Element element : elements) {
    85. if ("servlet".equalsIgnoreCase(element.getName())) {
    86. //这是一个servlet配置
    87. //System.out.println("发现 servlet");
    88. //使用反射将该servlet实例放入到servletMapping
    89. Element servletName = element.element("servlet-name");
    90. Element servletClass = element.element("servlet-class");
    91. servletMapping.put(servletName.getText(),
    92. (HspHttpServlet) Class.forName(servletClass.getText().trim()).newInstance());
    93. } else if ("servlet-mapping".equalsIgnoreCase(element.getName())) {
    94. //这是一个servlet-mapping
    95. //System.out.println("发现 servlet-mapping");
    96. Element servletName = element.element("servlet-name");
    97. Element urlPatter = element.element("url-pattern");
    98. servletUrlMapping.put(urlPatter.getText(), servletName.getText());
    99. }
    100. }
    101. } catch (Exception e) {
    102. e.printStackTrace();
    103. }
    104. //验证,这两个容器是否初始化成功
    105. System.out.println("servletMapping= " + servletMapping);
    106. System.out.println("servletUrlMapping= " + servletUrlMapping);
    107. }
    108. }
    3.4测试
     

     

  • 相关阅读:
    入行测试一年半的心得体会
    LeetCode Cookbook 数组习题(2)
    OpenCV--图像的分割与融合方法
    陕西直销系统开发如何让别人听你讲?
    SQL 撤销索引、表以及数据库||SQL CREATE DATABASE 语句||SQL CREATE TABLE 语句
    一起来学Kotlin:概念:14. Kotlin List 的使用 1:filter,map,count,first,last,any,find
    github Release 下载加速,绿色合法,遥遥领先
    JS中计算时数据有误差解决方案
    Java面试题07
    编译添加了ALPHA开发板的NXP官方uboot
  • 原文地址:https://blog.csdn.net/weixin_54107527/article/details/133002342