如何部署项目到Tomcat + 第一个Servlet程序
- 博主简介:想进大厂的打工人
- 博主主页:@xyk:
- 所属专栏: JavaEE初阶
目录
文章目录
一、Tomcat
1.1 Tomcat是什么
1.2 下载安装
1.3 部署项目
二、第一个Servlet程序
2.1 Servlet是什么
2.2 创建Maven项目
2.3 引入依赖
2.4 创建目录
2.5 编写类方法
2.6 打包代码
2.7 部署项目
2.8 验证程序
三、Smart Tomcat部署方式
四、Servlet程序中常见的问题
4.1 404
4.2 出现405
4.3 出现500
4.4 出现空白页面
一、Tomcat
1.1 Tomcat是什么
Tomcat 这个单词很容易让大家想到“汤姆猫”,大家可能会想到小时候看的动画片~~
事实上, Java 世界中的 "汤姆猫" 完全不是一回事, 但是同样大名鼎鼎
Tomcat 是一个 HTTP 服务器.在Java圈子中,最出名的 HTTP 服务器就是Tomcat,是apache社区开源的 http 服务器~~~
1.2 下载安装
下载官网:Apache Tomcat® - Apache Tomcat 8 Software Downloads
最新的版本不一定好用,我推荐下载 Tomcat8 版本的,因为大部分企业都在使用~~
点击即可~
大版本是 8 系列即可,小版本由差别,无所谓~~
目录结构:
- 这就是一个绿色软件,连双击安装都不需要~
bin 表示binary,里面包含了一下可执行的二进制脚本
启动成功是这个界面:乱码没关系的,不影响使用
查看Tomcat的端口号是否绑定成功
打开命令行输入:
netstat -ano | findstr 8080
- netstat -ano:获得所有端口情况
- findstr 8080:找包含8080的字符串
两个的话,一个是ipv4,一个是ipv6,出现这样的界面就代表绑定成功了~~~
.bat后缀的为 Windows的批处理文件
.sh后缀的为 linux / mac 的shell脚本
如果启动失败怎么办?
最常见的启动失败原因是端口号被占用,Tomcat 启动的时候默认会绑定 8080 和 8005 端口,如果有其他进程已经绑定了这两个端口中的任意一个, 都会导致 Tomcat 不能启动.把对方进程干掉,再重新启动 Tomcat 一般就可以解决问题.
conf 表示config,配置文件
- 一个复杂的软件,通常会有配置,开启不同的功能~
logs表示运行日志
webapps 放webapp,即放我们写的代码压缩包,一个Tomcat上可以同时部署多个网站
1.3 部署项目
- 我们自己电脑内打开html当然简单,但是别人不行呀
- 部署到Tomcat上面,别人也能访问才能我们的网站
我把我写过的项目拷贝到 webapps目录下面:
再次启动Tomcat,就可以看见这个 war包 被自动解压缩了,然后我们进行访问
可以看到,我们访问成功了,证明我们已经成功部署到Tomcat服务器上面~~
但是由于 NAT机制,在外网的设备,还是不能访问我部署的项目,后续我会在云服务器上部署,外网就可以访问了~~
二、第一个Servlet程序
2.1 Servlet是什么
Servlet 是一种实现动态页面的技术. 是一组 Tomcat 提供给程序猿的 API, 帮助程序猿简单高效的开发一个 web app.
Servlet 主要做的工作:
- 允许程序猿注册一个类, 在 Tomcat 收到某个特定的 HTTP 请求的时候, 执行这个类中的一些代码.
- 帮助程序猿解析 HTTP 请求, 把 HTTP 请求从一个字符串解析成一个 HttpRequest 对象.
- 帮助程序猿构造 HTTP 响应. 程序猿只要给指定的 HttpResponse 对象填写一些属性字段, Servlet就会自动的安装 HTTP 协议的方式构造出一个 HTTP 响应字符串, 并通过 Socket 写回给客户端.
简而言之, Servlet 是一组 Tomcat 提供的 API, 让程序猿自己写的代码能很好的和 Tomcat 配合起来, 从而更简单的实现一个 web app.
而不必关注 Socket, HTTP协议格式, 多线程并发等技术细节, 降低了 web app 的开发门槛, 提高了开发效率.
2.2 创建Maven项目
使用 IDEA 创建一个 Maven 项目
首次使用maven项目,会从互联网上加载很多依赖,所以要保持网络通畅!
2.3 引入依赖
在Maven中央仓库中搜索servlet
Maven中央仓库官方网站:Maven Repository: Search/Browse/Explore (mvnrepository.com)
点击3.1.0,选择3.1.0是跟我们的Servlet版本匹配的,不能乱选
复制下来,粘贴进pom.xml
<dependencies><!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency></dependencies>
2.4 创建目录
要跟我一模一样哦!!!
这些目录中:
- src 表示源代码所在的目录
- main/java 表示源代码的根目录. 后续创建 .java 文件就放到这个目录中.
- main/resources 表示项目的一些资源文件所在的目录
- test/java 表示测试代码的根目录.
我们要在main包下面,创建webapp包,webapp包下创建WEB-INF包,WEB-INF包下创建web.xml
web.xml中的内容:
<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>Archetype Created Web Application</display-name>
</web-app>
2.5 编写类方法
在java包下创建HelloServlet
继承HttpServlet,并重写doGet方法,并在类上面写上注解@WebServlet(“....”)表示 Tomcat 收到的请求才会调用 HelloServlet 这个类的代码.
@WebServlet(),括号里面写的路径跟我们后续访问网页有很大关系,所以一定要记住!!!
@WebServlet("/hello")
public class helloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("hello world");resp.getWriter().write("hello world");}
}
- doGet方法的工作就是,根据请求计算响应
而我们之前做的TCP回显服务器的基本流程就是:
- 读取请求并解析
- 根据请求计算响应
- 把响应写回客户端
但是Tomcat已经帮我们把1,3步都做好了,所以我们只需要做好第二步即可~~
为什么不用写main方法??
这是因为Tomcat内部帮我们实现了,它在合适的时机调用了我们重写的代码去计算响应~
伪码:
main {HttpServlet servlet = new HelloServlet();//触发重写HttpServletRequest req = ...;//获取请求的一系列操作HttpServletResponse resp = new HttpServletResponse();//空响应servlet.doGet(req, resp);//调用我们重写的方法,这个响应就被构造好了 }
如果我们不重写doGet方法,那么就会出现405错误:
我们随便写个类都能被 Tomcat 调用嘛? 满足啥样条件才能被调用呢?
主要满足三个条件:
- 创建的类需要继承自 HttpServlet
- 这个类需要使用 @WebServlet 注解关联上一个 HTTP 的路径
- 这个类需要实现 doXXX 方法
这三个条件都满足之后, Tomcat 就可以找到这个类, 并且在合适的时机进行调用
2.6 打包代码
我们的程序不能独立运行,必须部署(放置)到Tomcat上才能运行,而Tomcat服务器只认识 war包,只能解析 war包!!
- 对于一个规模很大的项目,就会有很多很多的java文件和class文件,所以我们是需要将这些class文件打成一个压缩包,再进行拷贝,是比较科学的~
- java中使用的压缩包,就是jar、war
- jar:普通java程序,打成jar包
- war:部署到Tomcat上的压缩包
我们要在pom.xml里面加下面代码才能打成war包:
<packaging>war</packaging><build><finalName>hello_servlet</finalName></build>
接下来打war包:
双击package,就会自动生成war包
可见我们已经生成了war包~~~
2.7 部署项目
把 war 包拷贝到 Tomcat 的 webapps 目录下,启动 Tomcat , Tomcat 就会自动把 war 包解压缩.
看到这个日志说明 Tomcat 已经正确识别了 ServletHelloWorld 这个 webapp.
2.8 验证程序
此时通过浏览器访问 http://127.0.0.1:8080/ServletHelloWorld/hello
就可以看到结果了.
注意: URL 中的 PATH 分成两个部分, 其中 HelloServlet 为 Context Path, hello 为 Servlet Path
Context Path是war包名,Servlet Path 是我们之前在类上面写的路径
三、Smart Tomcat部署方式
- 其他操作没办法简化,这也很好理解
- 而5和6则需要点击package去打包,还有拷贝部署到对应目录,太麻烦了,不简化的话,每次调整代码,都要重新打包,重新拷贝部署替换原来的那个war包
我们只需要通过IDEA的插件(plugin)来完成这个工作(一键式完成5和6)
点击下载,我这里已经下载好了,不再下载~~
使用Smart Tomcat插件
首次使用比较麻烦,需要配置:
点击 + 号
配置完之后,点击运行
这样就运行起来啦!!!
- 那个地址就是提示你的路径是什么,localhost == 127.0.0.1
- 点了一定404,因为这个路径没有第二级目录:/hello(注解里的字符串)
我们加上hello之后,再次访问
可见,访问成功了!!!
Smart Tomcat的运行方式和之前拷贝到webapps是存在区别的~
smart tomcat其实是使用了tomcat的另外一种运行方式,在运行tomcat的时候,通过特定的参数,来指定tomcat加载某个特定目录中的webapp
因此,上述过程既不会打包,也不会拷贝!!!是开发和调试阶段,使用的方式,如果是部署到生产环境,还是得打war包!!!
四、Servlet程序中常见的问题
4.1 404
404 表示用户访问的资源不存在. 大概率是 URL 的路径写的不正确.
错误实例1: 少写了 Context Path
通过 /hello 访问服务器
错误实例2: 少写了 Servlet Path
通过 /ServletHelloWorld 访问服务器
错误实例3: Servlet Path 写的和 URL 不匹配
修改 @WebServlet 注解的路径
错误实例4: web.xml 写错了
清除 web.xml 中的内容
4.2 出现405
405 表示对应的 HTTP 请求方法没有实现
错误实例: 没有实现 doGet 方法
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
}
在浏览器地址栏直接输入 URL , 会发送一个 HTTP GET 请求.
此时就会根据 /ServletHelloWorld/hello 这个路径找到 HelloServlet 这个类. 并且尝试调用
HelloServlet 的 doGet 方法.
4.3 出现500
往往是 Servlet 代码中抛出异常导致的.
错误实例:修改代码
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String s = null;
resp.getWriter().write(s.length());
}
}
异常信息里已经提示了出现异常的代码是 HelloServlet.java 的第 13 行
resp.getWriter().write(s.length());
4.4 出现空白页面
错误实例:修改代码, 去掉 resp.getWritter().write() 操作
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("hello");
}
}
抓包可以看到, 响应 body 中的内容就是 "空数据"
相关文章:

如何部署项目到Tomcat + 第一个Servlet程序
博主简介:想进大厂的打工人博主主页:xyk:所属专栏: JavaEE初阶 目录 文章目录 一、Tomcat 1.1 Tomcat是什么 1.2 下载安装 1.3 部署项目 二、第一个Servlet程序 2.1 Servlet是什么 2.2 创建Maven项目 2.3 引入依赖 2.4 创建目录 2.5 编写类方法 2.6 打包…...

牛客刷题(HTML-Day1)
第一题: 1.下列代码在页面中显示的内容为( ) <!DOCTYPE html> <html> <body> <p>hello<q>html</q></p> </body> </html> A hello“html” B hello html C hello“”html D 其他几…...

性能测试如何入门?熬夜7天整理出这一份3000字超全学习指南
赶鸭子上架要我搞性能测试,怎么办? 我第一次真正意义上搞性能测试是在2014年。项目组要求搞性能测试,我之前也没搞过,对服务端也不熟悉。就那么一脸懵逼地开始搞性能。当时我连linux上有哪些能看系统资源的命令都不知道。稀里糊涂…...

信息安全实践1.2(重放攻击)
前言 这个实验是看一本书做的,就是李华峰老师的书——《Metasploit Web 渗透测试实战》,我之前写过一篇Slowloris DoS攻击的博客,也是看这本书写的,总的来说,有用处。这篇博客其实也只是很浅显的去做一下重放攻击。 要…...

上海亚商投顾:沪指高开高走 地产股迎来久违反弹
上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 市场情绪 三大指数今日高开高走,沪指午后涨近1%,深成指、创业板指涨超1.2%,上证50盘中大…...

Vim学习笔记【Ch02】
Vim学习笔记 系列笔记链接Ch02 Buffers, Windows, TabsBuffers什么是buffer查看所有bufferbuffer之间的切换删除buffer退出所有窗口 Windows窗口的创建窗口切换快捷键其他快捷键 Tabs什么是tabtab相关命令 window和buffer结合的3D移动小结 系列笔记链接 Ch00,Ch01 …...

《低代码指南》——低代码维格云能源行业解决方案
目录 典型场景介绍: 一、能源资产管理 二、碳核查 三、配电运营 总 结: 从业界实际情况来看,流程建设本身是一个对业务现实进行抽象的过程,这个过程即使不考虑软件开发的门槛,对于很多客户而言也是个涉及较长周期的复杂工作,往往需要咨询专家或专业公司帮助其建设内…...

【自制C++深度学习推理框架】Layer的设计思路
Layer的设计思路 Layer的抽象 如果将深度学习中的所有层分为两类, 那么肯定是"带权重"的层和"不带权重"的层。 基于层的共性,我们定义了一个Layer的基类,提供了一些基本接口,并可以通过继承和多态机制实现不同类型的L…...

Rust每日一练(Leetday0011) 下一排列、有效括号、搜索旋转数组
目录 31. 下一个排列 Next Permutation 🌟🌟 32. 最长有效括号 Longest Valid Parentheses 🌟🌟🌟 33. 搜索旋转排序数组 Search-in-rotated-sorted-array 🌟🌟 🌟 每日一练刷…...

STL --- 五. 函数对象 Function Objects
目录 1、函数对象的定义和作用 2、函数对象的分类和使用 3、std 常用的函数对象 4、函数对象的适配器 5、std 算法和函数对象区别 1、函数对象的定义和作用 STL(Standard Template Library)中的函数对象(Functor)是一种重载…...

Java IO 流操作详解
Java IO 流操作详解 一、简介1. 什么是IO流2. IO流的分类3. IO流的作用 二、Java IO流的输入操作1. 文件输入流2. 字节输入流3. 缓冲输入流4. 对象输入流 三、Java IO流的输出操作1. 文件输出流2. 字节输出流3. 缓冲输出流4. 对象输出流 四、Java IO流的常用方法解析1. 字节读写…...

Halcon 形状匹配参数详解
find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score) find_shape_model(Image : : //搜索图像 ModelID, //模板句柄 AngleStart, // 搜索时的起始角度 AngleExte…...

C++11强类型枚举
C11引入了强类型枚举(enum class),也称为枚举类。 强类型枚举是一种更加类型安全的枚举类型,相对于传统的枚举类型,强类型枚举可以提供更好的安全性和可读性。 强类型枚举的格式如下: enum class 枚举名 …...

pytorch讲解(部分)
友爱的目录 自动求导机制从后向中排除子图自动求导如何编码历史信息Variable上的In-place操作In-place正确性检查 CUDA语义最佳实践使用固定的内存缓冲区使用 nn.DataParallel 替代 multiprocessing 扩展PyTorch扩展 torch.autograd扩展 torch.nn 多进程最佳实践共享CUDA张量最…...

C++ 基本的7种数据类型和4种类型转换(C++复习向p3)
文章目录 基本内置类型存储范围typedef 声明新名字enum 枚举类型类型转换 基本内置类型 boolcharintfloatdoublevoidwchar_t ⇒ short int 存储范围 可以这样 sizeof(int) 来确认 int 占用字节数 char,1字节,-128~127 或 0~255 wchar_t,2…...

Scrum敏捷迭代规划和执行
Sprint Backlog看板 迭代工作的开展是围绕Sprint Backlog展开的,在Leangoo中,我们需要为每个迭代创建一个Sprint Backlog看板。Sprint Backlog(迭代)看板,用于管理当前Sprint的需求和开发任务,可视化展示每…...

智警杯赛前学习1.1---excel基本操作
修改默认设置 步骤一:打开“Excel选项”窗口,打开“文件”菜单,选择“选项”标签 步骤二:在“Excel选项”窗口中,选择“常规与保存”标签,在“常规与保存”标签中,可以修改录入数据时的默认字体…...

【Android】Handle(一) 主要特点和用途
在Android中,Handler是一种消息处理机制,它允许我们在不同线程之间交换信息并更新UI。具体来说,Handler可以将一个Runnable或Message对象加入到消息队列中,并在合适的时间去执行它们。 以下是Handler的主要特点和用途:…...

40亿个QQ号,限制1G内存,如何去重?【已通过代码实现】
前几天发现一个有趣的文章 “40亿个QQ号,限制1G内存,如何去重?”,发现很有意思,就想着用代码实现一下,下面是分析和实现过程 一、审题分析 一个 QQ 号现在最长有 11 位,因为 int 是四字节,数值范围是2的31次方,因此得使用 long 存储,但考虑到实现,使用 int 存储(1…...

Talk预告 | 新加坡国立大学张傲:10%成本定制类 GPT-4 多模态大模型
本期为TechBeat人工智能社区第502期线上Talk! 北京时间06月01日(周四)20:00,新加坡国立大学在读博士生 — 张傲的Talk将准时在TechBeat人工智能社区开播! 他与大家分享的主题是: “10%成本定制类 GPT-4 多模态大模型 ”,届时将介…...

从C语言到C++_13(string的模拟实现)深浅拷贝+传统/现代写法
前面已经对 string 类进行了简单的介绍和应用,大家只要能够正常使用即可。 在面试中,面试官总喜欢让学生自己 来模拟实现string类, 最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数。 为了更深入学习STL,下面我…...

reduce()方法详解
一、 定义和用法 reduce() 方法将数组缩减为单个值。 reduce() 方法为数组的每个值(从左到右)执行提供的函数。 函数的返回值存储在累加器中(结果/总计)。 注释:对没有值的数组元素,不执行 reduce() 方法。…...

C++虚假唤醒
概念: 虚假唤醒是指在使用条件变量时,线程被唤醒但条件并没有满足,导致线程执行错误的情况,这个过程就是虚假唤醒。 虚假唤醒弊端: 虚假唤醒会导致程序的正确性受到影响,因为唤醒的线程并没有满足条件&…...

【AI】dragonGPT - 单机部署、极速便捷
dragonGPT 从数据私有化,到prompt向量库匹配,再到查询,一条龙服务,单机部署,极简操作 pre a.需要下载gpt4all model到本地. ggml Model Download Link 然后将存放model的地址写入.env MODEL_PATH your pathb.…...

Uuiapp使用生命周期,路由跳转传参
Uniapp生命周期: 1. beforeCreate:在实例初始化之后,数据观测和事件配置之前被调用。 2. created:在实例创建完成后被立即调用。 3. beforeMount:在挂载开始之前被调用:相关的 render 函数首次被调用。 …...

定积分的计算(牛顿-莱布尼茨公式)习题
前置知识:定积分的计算(牛顿-莱布尼茨公式) 习题1 计算 ∫ 0 2 ( x 2 − 2 x 3 ) d x \int_0^2(x^2-2x3)dx ∫02(x2−2x3)dx 解: \qquad 原式 ( 1 3 x 3 − x 2 3 x ) ∣ 0 2 ( 8 3 − 4 6 ) − 0 14 3 (\dfrac 13x^3-…...

leak 记录今天的一个小题
先看题, add没有大小限制,这里edit可以溢出8字节,也就是可以改后边的size,可以调用4次free没有调用函数只是把指针置0,show可以用一次. void __fastcall __noreturn main(__int64 a1, char **a2, char **a3) {init_0(a1, a2, a3);while ( 1 ){menu();switch ( read_n() ){cas…...

软考A计划-试题模拟含答案解析-卷二
点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&am…...

【C++】pthread
一、pthread简介 pthread是C98接口且只支持Linux,使用时需要包含头文件#include <pthread.h>,编译时需要链接pthread库,其中p是POSIX的缩写,而POSIX是Portable Operating System Interface的缩写,是IEEE为要在各…...

2023年前端面试题汇总-浏览器原理
1. 浏览器安全 1.1. 什么是 XSS 攻击? 1.1. 1. 概念 XSS 攻击指的是跨站脚本攻击,是一种代码注入攻击。攻击者通过在网站注入恶意脚本,使之在用户的浏览器上运行,从而盗取用户的信息如 cookie 等。 XSS 的本质是因为网站没有对…...