03_Tomcat

文章目录

  • Tomcat
    • 概念
    • 自制简易的服务器
    • JavaEE规范
    • Tomcat安装
    • Tomcat启动
    • Tomcat的资源部署
      • 直接部署
      • 虚拟映射
    • Tomcat的设置

Tomcat

概念

  • 服务器:两层含义。
    • 软件层面:软件,可以将本地的资源发布到网络中,供网络上面的其他用户来访问,比如tomcat
    • 硬件层面:一台性能比较高效的计算机主机,云服务器。
  • 服务器开发:指的是在服务器软件程序中进一步去编写程序来运行
  • 静态资源:页面一成不变的。
  • 动态资源:富有交互性、变化性。
    • 目前访问的网站页面基本都是动态资源。本质就是程序。比如登录之后会显示各自的用户名。开发动态资源的技术有很多种,其中java语言中 servlet。

自制简易的服务器

单线程的服务器

public class ServerDemo {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8089);Socket socket = serverSocket.accept();// 怎么从socket获取信息InputStream inputStream = socket.getInputStream();byte[] bytes = new byte[20480];//输入的数据会放到字节数组bytes里面;读出的长度会返回lengthint length = inputStream.read(bytes);String inputStr = new String(bytes, 0, length);System.out.println(inputStr);// 想根据url上面的信息,返回1.txt 1.png// 应该拿出请求行; 再取出第二个数据// \r\n表示回车int index1 = inputStr.indexOf("\r\n");String firstLine = inputStr.substring(0, index1);// firstLine 为 GET /1.txt HTTP/1.1System.out.println(firstLine);// Strings = {GET, /1.txt, HTTP/1.1}String[] strings = firstLine.split(" ");System.out.println(strings[0]);System.out.println(strings[1]);System.out.println(strings[2]);// split之后获取到了1.txt// resourceName = 1.txtString resourceName = strings[1].substring(1);System.out.println(resourceName);// data如果有数据// 那么则传入1.txt// 1. 把数据的字节数组写回来// 2. 文件不存在,返回长度为0的字节数组byte[] data = getDataFromFile(resourceName);OutputStream outputStream = socket.getOutputStream();StringBuffer stringBuffer = new StringBuffer();if (data.length == 0) {// 代表文件没找到stringBuffer.append("HTTP/1.1 404 NotFound\r\n");stringBuffer.append("Server: coo1heisenberg\r\n");stringBuffer.append("Content-type: text/html\r\n");stringBuffer.append("\r\n");// 如果文件没找到,把data数组赋值data = "<div style = 'font-size: 50px'>file not found</div>".getBytes("utf-8");} else {stringBuffer.append("HTTP/1.1 200 Ok\r\n");stringBuffer.append("Server: coo1heisenberg\r\n");stringBuffer.append("Content-type: text/html\r\n");stringBuffer.append("\r\n");}// StringBuffer里面是响应行,响应头,空行的内容outputStream.write(stringBuffer.toString().getBytes("utf-8"));// data里面是文件的内容outputStream.write(data);outputStream.close();}private static byte[] getDataFromFile(String resourceName) throws IOException {InputStream inputStream1 = ServerDemo1.class.getClassLoader().getResourceAsStream(resourceName);byte[] bytes = new byte[20480];if (inputStream1 == null) {return new byte[0];} else {int len = inputStream1.read(bytes);byte[] bytes1 = Arrays.copyOf(bytes, len);return bytes1;}}
}

多线程的服务器

public class ServerDemo {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8089);while (true) {Socket socket = serverSocket.accept();new Thread(() -> {// 怎么从socket获取信息InputStream inputStream = null;try {inputStream = socket.getInputStream();} catch (IOException e) {throw new RuntimeException(e);}byte[] bytes = new byte[20480];//输入的数据会放到字节数组bytes里面;读出的长度会返回lengthint length = 0;try {length = inputStream.read(bytes);} catch (IOException e) {throw new RuntimeException(e);}String inputStr = new String(bytes, 0, length);System.out.println(inputStr);// 想根据url上面的信息,返回1.txt 1.png// 应该拿出请求行; 再取出第二个数据// \r\n表示回车int index1 = inputStr.indexOf("\r\n");String firstLine = inputStr.substring(0, index1);// firstLine 为 GET /1.txt HTTP/1.1System.out.println(firstLine);// Strings = {GET, /1.txt, HTTP/1.1}String[] strings = firstLine.split(" ");System.out.println(strings[0]);System.out.println(strings[1]);System.out.println(strings[2]);// split之后获取到了1.txt// resourceName = 1.txtString resourceName = strings[1].substring(1);System.out.println(resourceName);// data如果有数据// 那么则传入1.txt// 1. 把数据的字节数组写回来// 2. 文件不存在,返回长度为0的字节数组byte[] data = new byte[0];try {data = getDataFromFile(resourceName);} catch (IOException e) {throw new RuntimeException(e);}OutputStream outputStream = null;try {outputStream = socket.getOutputStream();} catch (IOException e) {throw new RuntimeException(e);}StringBuffer stringBuffer = new StringBuffer();if (data.length == 0) {// 代表文件没找到stringBuffer.append("HTTP/1.1 404 NotFound\r\n");stringBuffer.append("Server: coo1heisenberg\r\n");stringBuffer.append("Content-type: text/html\r\n");stringBuffer.append("\r\n");// 如果文件没找到,把data数组赋值try {data = "<div style = 'font-size: 50px'>file not found</div>".getBytes("utf-8");} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}} else {stringBuffer.append("HTTP/1.1 200 Ok\r\n");stringBuffer.append("Server: coo1heisenberg\r\n");stringBuffer.append("Content-type: text/html\r\n");stringBuffer.append("\r\n");}// StringBuffer里面是响应行,响应头,空行的内容try {outputStream.write(stringBuffer.toString().getBytes("utf-8"));} catch (IOException e) {throw new RuntimeException(e);}// data里面是文件的内容try {outputStream.write(data);} catch (IOException e) {throw new RuntimeException(e);}try {outputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}).start();}}private static byte[] getDataFromFile(String resourceName) throws IOException {InputStream inputStream1 = ServerDemo1.class.getClassLoader().getResourceAsStream(resourceName);byte[] bytes = new byte[20480];if (inputStream1 == null) {return new byte[0];} else {int len = inputStream1.read(bytes);byte[] bytes1 = Arrays.copyOf(bytes, len);return bytes1;}}
}

抽象出一个Request方法

public class Request {// GET POSTString method;String resourceName;String protocol;// 请求头用什么数据来装?Map<String, String> Header = new HashMap<>();public void parseContent(String content) {//parseFirstLine(content);parseHeaders(content);}private void parseHeaders(String content) {// 在windows下面是\n// 在Linux下面是 \r\n// 在mac下面是 \rint index1 = content.indexOf("\r\n");// 怎么确定请求头结束int index2 = content.indexOf("\r\n\r\n");String headersStr = content.substring(index1 + 2, index2);System.out.println(headersStr);// 1.按照\r\n切分split// 2. 得到数组,代表一行// 3. 一行切分,按照":"}private void parseFirstLine(String content) {int index = content.indexOf("\r\n");String firstLine = content.substring(0, index);String[] strings = firstLine.split(" ");method = strings[0];resourceName = strings[1];protocol = strings[2];}
}

JavaEE规范

  • 制定了一系列的接口。相应的厂商需要实现该接口,对于开发者来说,只需要面向接口编程即可。
  • JDBC也是,定义了很多的接口

Tomcat安装

在这里插入图片描述

Tomcat控制台乱码解决办法

  • 原因:cmd是GBK编码,Tomcat是UTF8编码
  • 解决:
    • 修改logging.properties配置:
      • 打开tomcat/conf/logging.properties
      • 添加语句:java.util.logging.ConsoleHandler.encoding = GBK
      • 重启tomcat,查看日志数据即可

Tomcat启动

  1. 双击startup.bat文件
  2. bin目录下换出cmd,执行startup

常见的启动故障

  • 没有正确配置好JAVA_HOME,导致tomcat一闪而过

Tomcat的资源部署

直接部署

在这里插入图片描述
eg:

  1. 写ip+端口 --> 相当于找到了webapps目录
    • localhost:8080/test
  2. 如果你想访问test文件夹下的1.txt。 只用写相对路径,
    • http://localhost:8080/test/1.txt
  3. 如果想访问test文件夹里面的2.png,怎么写呢?
    • http://localhost:8080/test/2.png

注意
不能将文件直接放置在webapps目录下。需要放在webapps目录下的文件夹内。

虚拟映射

不在webapps目录这种方式叫做虚拟映射。虚拟地映射到Tomcat的webapps目录下。

  1. conf/Catalina/localhost掌握
    • 新建一个.xml的配置文件
    • 在这里插入图片描述
    • .xml的文件(test1.xml)里面配置context的节点信息
      eg:
第一行是一个标识,表示这是一个xml
<?xml version="1.0" encoding="UTF-8"?>第二行表示在D盘有一个叫test_Photo的目录
<Context docBase="D:\test_Photo"/>
  • 访问流程
    • localhost:8080/{xml的名称}
      • 相当于会找到了docBase指定的文件夹
    • localhost:8080/{xml的名称}/{相对于docBase的相对路径}
      • eg:在这里插入图片描述

服务器最终会把url的路径映射到本地磁盘的一个路径上面

  1. conf/server.xml了解
  • 需要在Host节点下配置Context节点

    • /app452-----Context
<Context path="/app452" docBase="D:\test_Photo" />
  • http://localhost:8080/{path}/{文件相对于docBase的相对路径}
    • eg:http://localhost:8080/app452/2.jpg

Tomcat的设置

  1. 设置默认端口号
    • 对于http协议来说,默认端口号是80端口号。如果你也希望访问你的tomcat时,也不携带端口号,你只需要设置你的tomcat监听80端口号即可。
    • conf/server.xml中配置
    • 在这里插入图片描述
 <Connector port="80" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
  1. 设置缺省应用
    • tomcat中存在着一个缺省应用,如果没有找到匹配的应用时,则将该请求交给缺省应用来处理。
    • 具体步骤:
      • 如果希望配置一个ROOT应用,那么webapps目录下新建一个ROOT目录
      • conf/Catalina/localhost目录下新建一个ROOT.xml
    • ROOT应用下的资源文件在访问时,不需要携带应用的名称
以下为ROOT.xml的示例代码:<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="D:\test_Photo"/>

虚拟映射也可以配置一个ROOT.xml,如果虚拟映射和直接部署都有,那么则是虚拟映射优先级高

  1. 设置欢迎页面(缺省页面)
  • 比如:访问http://localhost,可以显示出一个页面,那么访问的是哪个页面:

    1. 没有应用名,说明访问的是ROOT应用

    2. 没有页面,说明访问的是欢迎页面(conf/web.xml文件中有配置)

      • 表示的是:如果请求没有指明具体访问的是哪个页面,那么会在当前应用下依次去查找是否存在该文件,如果存在,则加载;如果不存在,则返回404在这里插入图片描述

eg:
现在在chrome里面输入localhost,直接访问到我的D:\app31.jpg的图片,那么分为几个步骤?

  1. 修改端口号,改成8080端口

    • 在这里插入图片描述
  2. 虚拟映射

    • 在这里插入图片描述
  3. /conf/web.xml下修改welcome-file-list加上一个1.jpg

    • 在这里插入图片描述

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

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

相关文章

grafana table合并查询

注&#xff1a;本文基于Grafana v9.2.8编写 1 问题 默认情况下table展示的是一个查询返回的多个field&#xff0c;但是我想要的数据在不同的metric上&#xff0c;比如我需要显示某个pod的读写IO&#xff0c;但是读和写这两个指标存在于两个不同的metirc&#xff0c;需要分别查…

多种方法求解数组排序

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary_walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…

C++——string模拟实现

前言&#xff1a;上篇文章我们对string类及其常用的接口方法的使用进行了分享&#xff0c;这篇文章将着重进行对这些常用的接口方法的内部细节进行分享和模拟实现。 目录 一.基础框架 二.遍历字符串 1.[]运算符重载 2.迭代器 3.范围for 三.常用方法 1.增加 2.删除 3.调…

数据库-第十一章 并发控制【期末复习|考研复习】

前言 总结整理不易&#xff0c;希望大家点赞收藏。 给大家整理了一下数据库系统概论中的重点概念&#xff0c;以供大家期末复习和考研复习的时候使用。 参考资料是王珊老师和萨师煊老师的数据库系统概论(第五版)。 数据库系统概论系列文章传送门&#xff1a; 第一章 绪论 第二/…

数据分析-Pandas数据画箱线图

数据分析-Pandas数据画箱线图 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&#xff…

【重新定义matlab强大系列十七】Matlab深入浅出长短期记忆神经网络LSTM

&#x1f517; 运行环境&#xff1a;Matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 #### 防伪水印——左手の明天 #### &#x1f497; 大家好&#x1f917;&#x1f91…

音视频学习笔记——c++多线程(二)

✊✊✊&#x1f308;大家好&#xff01;本篇文章是多线程系列第二篇文章&#x1f607;。首先讲解了利用mutex解决多线程数据共享问题&#xff0c;举例更好理解lock和unlock的使用方法&#xff0c;以及错误操作造成的死锁问题&#xff0c;最后讲解了lock_guard与unique_lock使用…

Django模型层(附带test环境)

Django模型层(附带test环境) 目录 Django模型层(附带test环境)连接数据库Django ORM在models.py中建表允许为空指定默认值数据库迁移命令 开启测试环境建表语句补充(更改默认表名)数据的增加时间数据的时区 多表数据的增加一对多多对多 数据的删除修改数据查询数据查询所有数据…

鸿蒙OpenHarmony HDF 驱动开发

目录 序一、概述二、HDF驱动框架三、驱动程序四、驱动配置坚持就有收获 序 最近忙于适配OpenHarmonyOS LiteOS-M 平台&#xff0c;已经成功实践适配平台GD32F407、STM32F407、STM32G474板卡&#xff0c;LiteOS适配已经算是有实际经验了。 但是&#xff0c;鸿蒙代码学习进度慢下…

【AcWing】蓝桥杯集训每日一题Day1|二分|差分|503.借教室(C++)

503. 借教室 503. 借教室 - AcWing题库难度&#xff1a;简单时/空限制&#xff1a;1s / 128MB总通过数&#xff1a;8052总尝试数&#xff1a;26311来源&#xff1a;NOIP2012提高组算法标签二分差分 题目内容 在大学期间&#xff0c;经常需要租借教室。 大到院系举办活动&…

基于机器学习的网络入侵检测二元分类模型构建与性能评估(NSL-KDD数据集)

简介 该项目是一个基于NSL-KDD数据集的网络入侵检测系统&#xff0c;主要采用机器学习方法对网络流量数据进行使用了多种机器学习模型&#xff0c;如逻辑回归、线性SVM、多项式核SVM、高斯核SVM、决策树、随机森林、朴素贝叶斯和K近邻算法训练二元分类&#xff08;正常/异常&a…

bug总结(1)--变量取错

a c t i v i t y [ ′ t a g n a m e ′ ] 应为 activity[tag_name]应为 activity[′tagn​ame′]应为couponActivitList[0][‘name’] .隐藏的bug&#xff0c;在测试中竟然测不出来&#xff0c;而且上线了好久。为啥会出现这种低级错误呢&#xff1f;第一是写的时候不够仔细认…

Day26:安全开发-PHP应用模版引用Smarty渲染MVC模型数据联动RCE安全

目录 新闻列表 自写模版引用 Smarty模版引用 代码RCE安全测试 思维导图 PHP知识点&#xff1a; 功能&#xff1a;新闻列表&#xff0c;会员中心&#xff0c;资源下载&#xff0c;留言版&#xff0c;后台模块&#xff0c;模版引用&#xff0c;框架开发等 技术&#xff1a;输…

2024 年中国高校大数据挑战赛赛题 C:用户对博物馆评论的情感分析完整思路以及源代码分享

博物馆是公共文化服务体系的重要组成部分。国家文物局发布&#xff0c; 2021 年我国新增备案博物馆 395 家&#xff0c;备案博物馆总数达 6183 家&#xff0c;排 名全球前列&#xff1b;5605 家博物馆实现免费开放&#xff0c;占比达 90%以上&#xff1b;全国 博物馆举办展览 3…

【深度学习笔记】6_5 RNN的pytorch实现

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 6.5 循环神经网络的简洁实现 本节将使用PyTorch来更简洁地实现基于循环神经网络的语言模型。首先&#xff0c;我们读取周杰伦专辑歌词…

Python操作Redis 各种数据类型

本文将深入探讨如何使用Python操作Redis&#xff0c;覆盖从基础数据类型到高级功能的广泛主题。无论是字符串、列表、散列、集合还是有序集合&#xff0c;我们将一一解析&#xff0c;同时提供丰富的代码示例帮助读者更好地理解和应用。除此之外&#xff0c;本文还将介绍Redis的…

【20240309】WORD宏设置批量修改全部表格格式

WORD宏设置批量修改全部表格格式 引言1. 设置表格文字样式2. 设置表格边框样式3. 设置所有表格边框样式为075pt4. 删除行参考 引言 这两周已经彻底变为office工程师了&#xff0c;更准确一点应该是Word工程师&#xff0c;一篇文档动不动就成百上千页&#xff0c;表格图片也是上…

STM32之串口中断接收UART_Start_Receive_IT

网上搜索了好多&#xff0c;都是说主函数增加UART_Receive_IT()函数来着&#xff0c;实际正确的是UART_Start_Receive_IT()函数。 —————————————————— 参考时间&#xff1a;2024年3月9日 Cube版本&#xff1a;STM32CubeMX 6.8.1版本 参考芯片&#xff1a…

Svg Flow Editor 原生svg流程图编辑器(二)

系列文章 Svg Flow Editor 原生svg流程图编辑器&#xff08;一&#xff09; 说明 这项目也是我第一次写TS代码哈&#xff0c;现在还被绕在类型中头昏脑胀&#xff0c;更新可能会慢点&#xff0c;大家见谅~ 目前实现的功能&#xff1a;1. 元件的创建、移动、形变&#xff1b;2…

【C语言】字符指针

在指针的类型中我们知道有一种指针类型为字符指针char* 一般使用&#xff1a; int main() { char ch w; char *pc &ch; *pc w; return 0; } 还有一种使用方式&#xff0c;如下&#xff1a; int main() { const char* pstr "hello bit.";//这⾥是把⼀个字…