JavaWeb——Servlet原理、生命周期、IDEA中实现一个Servlet(全过程)
6、servlet
6.1、什么是servlet
在JavaWeb中,Servlet是基于Java编写的服务器端组件,用于处理客户端(通常是Web浏览器)发送的HTTP请求并生成相应的HTTP响应。Servlet运行在Web服务器上,与Web容器(如Tomcat)进行交互,通过Web容器将请求分发给适当的Servlet进行处理。
Servlet提供了一种动态生成和处理Web内容的方式,可以接收并解析HTTP请求,执行业务逻辑,生成HTML、XML或其他格式的响应结果,并将其返回给客户端。Servlet可以处理各种不同类型的请求,如GET请求、POST请求等,并可以访问请求的参数、请求头、会话信息等。
在Java中,编写一个Servlet需要继承自javax.servlet.http.HttpServlet类,并重写其中的一些方法,如doGet()、doPost()等。在这些方法中,开发人员可以编写处理请求和生成响应的逻辑。另外,Servlet也可以实现一些接口(如javax.servlet.Servlet、javax.servlet.Filter等),以实现更灵活的功能。
Servlet在JavaWeb开发中扮演着非常重要的角色,它可以与数据库进行交互、调用其他Java类库、生成动态内容等。通过Servlet,开发人员可以实现Web应用程序中的用户认证、数据查询、数据处理、页面跳转等功能。
需要注意的是,使用Servlet开发时,通常还会配合使用Web框架(如Spring MVC、Struts等)来简化开发流程和提供更强大的功能。
- Sun公司在这些API中提供一个接口,叫做Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
- 编写一个类,实现Servlet接口
- 吧开发好的Java类部署到web服务器中
总而言之:把实现了Servlet接口的Java程序叫做:Servlet
6.2、HelloServlet
-
构建一个Maven项目,构建一个空的Maven项目,我们从头开始写
-
打开pom.xml即核心配置文件,先配置一些依赖(空的项目中,pom.xml文件中除非必要,并无其他东西,因此是没有任何一点依赖的)
<dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.2.1</version></dependency></dependencies>
我们在此配置了servlet的一些相关依赖以及jsp的一些相关依赖
依赖本质上是jar包,配置相关依赖,即在仓库中找到相应的jar包,如果报错,即仓库中没有该jar包,IDEA可能会提醒你安装,如果没有,则在网上找到相关资源下载并把jar包丢入仓库中
-
关于Maven父子工程的理解:我们一开始创建了一个空的Maven项目(Project),在这个项目中,我们还可以创建一些Maven模块(Module),当我们创建了一个名为servlet-01的Maven模块(以下我们称之为子项目)
父项目的pom.xml中会有:
<modules><module>servlet-01</module></modules>
子项目的pom.xml中会有:
<parent><groupId>com.Xu</groupId><artifactId>javaweb-02-servlet</artifactId><version>1.0-SNAPSHOT</version></parent>
(如果没有,可以手动添加)
父项目中的jar包子项目可以直接使用,子项目的父项目无法直接使用,即类似于继承
-
将子Maven项目的结构搭建完整(创建java包,resource包等)忘记的同学可以回头看上面Maven配置的博客
-
编写一个Servlet程序
-
编写一个普通类
-
实现Servlet接口,这里我们直接继承HttpServlet(HttpServlet是Sun公司写好的,直接继承,不必实现)
public class HelloServlet extends HttpServlet
进入HttpServlet的源码发现:
public abstract class HttpServlet extends GenericServlet
其同样继承了另一个类GenericServlet,再进入源码发现:
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable
GenericServlet最终实现了 Servlet接口,所以,即使是继承HttpServlet,同样也是实现Servlet接口
Servlet接口中,有几个方法:
void init(ServletConfig var1) throws ServletException;ServletConfig getServletConfig();void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;String getServletInfo();void destroy();
其中,最为重要的是service方法,查看源码可以发现,GenericServlet没有实现该方法,而是将其定义为抽象方法:
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
在HttpServlet才最终实现了它:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String method = req.getMethod();long lastModified;if (method.equals("GET")) {lastModified = this.getLastModified(req);if (lastModified == -1L) {this.doGet(req, resp);} else {long ifModifiedSince = req.getDateHeader("If-Modified-Since");if (ifModifiedSince < lastModified) {this.maybeSetLastModified(resp, lastModified);this.doGet(req, resp);} else {resp.setStatus(304);}}} else if (method.equals("HEAD")) {lastModified = this.getLastModified(req);this.maybeSetLastModified(resp, lastModified);this.doHead(req, resp);} else if (method.equals("POST")) {this.doPost(req, resp);} else if (method.equals("PUT")) {this.doPut(req, resp);} else if (method.equals("DELETE")) {this.doDelete(req, resp);} else if (method.equals("OPTIONS")) {this.doOptions(req, resp);} else if (method.equals("TRACE")) {this.doTrace(req, resp);} else {String errMsg = lStrings.getString("http.method_not_implemented");Object[] errArgs = new Object[]{method};errMsg = MessageFormat.format(errMsg, errArgs);resp.sendError(501, errMsg);}}
当然,这其中还有许多方法需要被重写才能完成我们想要的功能
-
重写doGet方法和doPost方法
public class HelloServlet extends HttpServlet {// 由于get或者post只是请求实现的不同方式,可以相互调用,业务逻辑都一样@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// ServletOutputStream outputStream = resp.getOutputStream();PrintWriter writer = resp.getWriter();writer.print("Hello, Servlet");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);} }
-
编写Servlet的映射
为什么需要映射:我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径
在web.xml文件中配置:
<!--注册Servlet--><servlet><servlet-name>hello</servlet-name><servlet-class>com.xu.servlet.HelloServlet</servlet-class></servlet><!--Servlet的注册(请求)路径--><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping>
-
配置Tomcat
-
启动测试
- 首先进入localhost时,是index.jsp页面,想要跳转到Servlet页面,则需要在域名后补上servlet-mapping的url-name,比如,在测试中,笔者所用的url-name为hello,则需要将域名改为:localhost:8080/s1/hello
如果最终测试过程中,遇到:跳转到servlet页面时出现404的页面,则有可能是application context出现了问题,请进入smart tomcat中修改:
用项目名称,即project的名称,本示例中为javaweb-02-servlet
如果遇到:跳转到servlet页面时出现500的情况,则是因为找不到相应的servlet的jar包,因此检查是否环境中配置了servlet的依赖,如果有,则查看Tomcat的版本:
- Tomcat 9.x.x版本时,依赖中添加servlet的jar包名称为javax.servlet-api
- Tomcat 10.x.x版本后,javax变更为javarta,因此查看是否依赖正确,如果不会修改,则卸载Tomcat 10 ,安装Tomcat 9(到目前为止,笔者使用的时Tomcat 10,但是在修改依赖时,将javax修改为javarta,会报错,还在查找原因当中,如果实在没有办法,笔者也只能将Tomcat 10 卸载,重新安装Tomcat 9)
-
6.3、Servlet原理
配置servlet:
想要Tomcat创建servlet实现类,就必须让Tomcat知道它在哪,因此我们在web.xml中配置servlet时,必须给出实现类的全限定类名
<!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><!--注册Servlet--><servlet><servlet-name>hello</servlet-name><!--全限定类名--><servlet-class>com.xu.servlet.HelloServlet</servlet-class></servlet><!--Servlet的注册(请求)路径--><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping>
</web-app>
Tomcat会将被配置好的servlet放入HashMap中以待日后使用,当浏览器发送相应的请求时,Tomcat会在HashMap寻找相应的servlet,调用它并完成响应。
而且,Tomcat并不会一开始就创建servlet对象,而是当浏览器发送相应的请求时,才会调用无参构造函数(若只有有参构造函数而没有无参构造函数,服务器是无法调用的,请在写servlet应用类时注意添加无参构造函数)去创建servlet对象。
初始化:
Servlet中有一个方法:init(ServletConfig var),它将会完成本Servlet的初始化功能,Tomcat在创建完成Servlet的实例化对象后,将会立即执行初始化操作
service:
service是servlet中十分重要的方法,当我们发送多次请求时,并不会重复创建servlet对象(servlet实例化对象只会创建一个,也就是说,当一个servlet类的实例化对象被创造出来,后续发送的请求,都是由这个实例化对象进行回应),而是会不断调用service方法进行响应,比如,我们在service方法中加入以下代码:
@Overridepublic void init() throws ServletException {System.out.println("servlet---->init");} @Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {System.out.println("servlet -----> service");}
在发送多次请求时,我们可以发现:
servlet初始化操作只执行了一次,而service方法则每请求一次,便调用一次。
销毁:
通过调用destroy方法来销毁一个servlet对象,一般而言,关闭浏览器并不会销毁该servlet实例化对象,而是当服务器关闭时才会销毁,即:一个servlet对象的销毁是tomcat服务器调用其destroy方法来完成的。
servlet生命周期:
第一次发送请求 → Tomcat创建servlet对象→调用初始化方法init→执行service方法
非首次发送请求→执行service方法
关闭服务器→调用destroy方法
相关文章:

JavaWeb——Servlet原理、生命周期、IDEA中实现一个Servlet(全过程)
6、servlet 6.1、什么是servlet 在JavaWeb中,Servlet是基于Java编写的服务器端组件,用于处理客户端(通常是Web浏览器)发送的HTTP请求并生成相应的HTTP响应。Servlet运行在Web服务器上,与Web容器(如Tomcat&…...

Android 12.0 ota升级之SettingsProvider新增和修改系统数据相关功能实现
1. 前言 在12.0的系统rom定制化开发中,在解决一些已经上线的bug后,进行ota升级的过程中,由于在SettingsProvider中新增了系统属性和修改某项系统属性值,但是在ota升级以后发现没有 更新,需要恢复出厂设置以后才会更改,但是恢复出厂设置 会丢掉一些数据,这是应为系统数据…...

python---for循环结构中的else结构(是同级关系)
为什么需要在for循环中添加else结构 循环可以和else配合使用, else下方缩进的代码指的是当循环正常结束之后要执行的代码。 强调: 循环 正常结束,else之后要执行的代码。 非正常结束,其else中的代码是不会执行的。…...

XLua中lua读写cs对象的原理
LuaCallCS 1. 传递C#对象到Lua XLua在C#维护了两个数据结构,ObjectPool和ReverseMap。 首次传递一个C#对象obj到Lua时,对象被加入到ObjectPool中,并为它创建一个唯一标识objId,建立obj和objId的双向映射。 ObjectPool: objId-…...

新手小白怎么选择配音软件?
现在的配音软件软件很多,各种类型的都比较多,对于新手小白来说不知该如何选择,今天就来给你分享几款好用的配音软件。不论是制作短视频还是制作平常音频都完全可以。 第一款:悦音配音 这是一款专业的视频配音软件,多端…...

linux查看硬件信息命令
文章目录 cpu内核版本内存硬盘主板服务器参考链接 cpu cat /proc/cpuinfo 一个物理CPU可以有1个或者多个物理内核,一个物理内核可以作为1个或者2个逻辑CPU。 物理CPU数就是主板上实际插入的CPU数量。 在Linux上cat /proc/cpuinfo,会打印每个cpu的信息 …...

TSINGSEE青犀省级高速公路视频上云联网方案:全面实现联网化、共享化、智能化
一、需求背景 随着高速铁路的建设及铁路管理的精细化,原有的模拟安防视频监控系统已经不能满足视频监控需求,越来越多站点在建设时已开始规划高清安防视频监控系统。高速公路视频监控资源非常丰富,需要对其进行综合管理与利用。通过构建监控…...

知识图谱相关的操作
微软生成自己的图谱:GitHub - microsoft/SmartKG: This project accepts excel files as input which contains the description of a Knowledge Graph (Vertexes and Edges) and convert it into an in-memory Graph Store. This project implements APIs to searc…...

【Javascript】json
目录 什么是json? 书写格式 json 序列化和反序列化 序列化 反序列化 什么是json? JSON(JavaScript Object Notation)是⼀种轻量级的数据交换格式,它基于JavaScript的⼀个⼦集,易于⼈的编写和阅读,也易于机器解析…...

零资源的大语言模型幻觉预防
零资源的大语言模型幻觉预防 摘要1 引言2 相关工作2.1 幻觉检测和纠正方法2.2 幻觉检测数据集 3 方法论3.1 概念提取3.2 概念猜测3.2.1 概念解释3.2.2 概念推理 3.3 聚合3.3.1 概念频率分数3.3.2 加权聚合 4 实验5 总结 摘要 大语言模型(LLMs)在各个领域…...

智能终端界面自动化测试操作工具 - Appium常见用法
1. Appium 是什么可以做什么? Appium 是一款开源的移动应用自动化测试框架,用于测试移动应用程序的功能和用户界面。它支持多种移动平台,包括 Android 和 iOS,可以使用多种编程语言进行脚本编写,如 Python、Java、Jav…...

结构体数组经典运用---选票系统
结构体的引入 1、概念:结构体和其他类型基础数据类型一样,例如int类型,char类型,float类型等。整型数,浮点型数,字符串是分散的数据表示,有时候我们需要用很多类型的数据来表示一个整体&#x…...

code too large
描述:比较尴尬,一个方法的代码接近10000行了,部署服务器的时候提示(java :code[255,21] too large),提示代码过长,无法运行。 查看了一下百度:解决的思路 JVM规范:「类或接口可以声明的字段数量限制在 655…...

vue中把弹出层.vue文件注册成组件供其他.vue文件调用的写法
背景:因弹出层多个页面的详情都是一样的,因此把弹出层定义成组件,多次调用 定义组件的过程中出现很多问题,因此再次记录最终成功的写法 一、 简单实现页面调用弹出层组件的打开弹出层方法: 1. 弹出层组件 (in…...

mac 查看GPU使用
首先搜索活动监视器 然后 点击窗口->gpu历史记录 记住不是立马出结果,而是 需要等半分钟左右的...

工业4.0的安全挑战与解决方案
在当今数字化时代,工业4.0已经成为制造业的核心趋势。工业4.0的兴起为生产企业带来了前所未有的效率和灵活性,但与之伴随而来的是一系列的安全挑战。本文将深入探讨工业4.0的安全挑战,并提供一些解决方案,以确保制造业的数字化转型…...

如何查找特定基因集合免疫基因集 炎症基因集
温故而知新,再次看下Msigdb数据库。它更新了很多内容。给我们提供了一个查询基因集的地方。 关注微信:生信小博士 比如纤维化基因集: 打开网址:https://www.gsea-msigdb.org/gsea/msigdb/index.jsp 2.点击search 3.比如我对纤维…...

轮转数组(Java)
大家好我是苏麟 , 这篇文章是凑数的 ... 轮转数组 描述 : 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 题目 : 牛客 NC110 旋转数组: 这里牛客给出了数组长度我们直接用就可以了 . LeetCode 189.轮转数组 : 189. 轮…...

Spring体系结构
Spring体系结构 核心容器 核心容器由 spring-core,spring-beans,spring-context,spring-context-support和spring-expression(SpEL,Spring 表达式语言,Spring Expression Language)等模块组成&…...

PostgreSQL basebackup备份和恢复
一、概述 备份和恢复分为逻辑和物理,这里指物理备份和恢复。 PG的物理备份依赖basebackup,这差不多就是数据目录的拷贝,还依赖归档日志。 恢复分为完全恢复和PITR恢复,它们都需要归档日志,它们关键的差别是…...

XTU-OJ 1248-Alice and Bob
Alice和Bob在玩骰子游戏,他们用三颗六面的骰子,游戏规则如下: 点数的优先级是1点最大,其次是6,5,4,3,2。三个骰子点数相同,称为"豹子",豹子之间按点数优先级比较大小。如果只有两个骰子点数相同&…...

第四章 文件管理 十、文件系统的全局结构
目录 一、文件系统的建立 1、原始磁盘 2、物理格式化后 3、逻辑格式化后 二、文件系统在内存中的结构 三、系统调用背后的过程 一、文件系统的建立 1、原始磁盘 2、物理格式化后 物理格式化,即低级格式化――划分扇区,检测坏扇区,并用…...

【PythonGIS】基于高德Api实现批量地址查询经纬度
之前因为同事需要几千个小区的经纬度信息,所以就帮同事写了一段Python代码,通过调取高德地图的api实现地址查询经纬度这个功能。对于如何使用经纬度查询地址的方法,我之前分享过博文:【Python入门教程】获取图片可视化精准定位&am…...

vue数组中的变更方法和替换方法
变更方法: Vue 能够侦听响应式数组的变更方法,并在它们被调用时触发相关的更新。这些变更方法包括: push():在数组末尾添加一个或者多个元素,返回新的长度。 var arr [1, 2, 3, 4, 5]; // 定义一个数组 arr.push(6…...

Java - 工具类参数初始化
在做第三方接口调用时,经常需要根据不同的环境指定初始化的参数。以下做一个简单的记录。 一、使用static初始化 使用static初始化,仅会初始化一次,但无法从配置文件中获取参数。并且如果写了多个初始化工具类,会互相覆盖。 /**…...

一文搞懂 MineCraft 服务器启动操作和常见问题 2023年10月
文章目录 前言1. 新建文件夹2. 创建 bat 文件3. 编辑 bat 文件4. 启动服务器5. 恭喜完成 文章持续更新中,如果你有问题可以通过 qq 1317699264 获取免费协助,解决的问题将会被更新到本文章中 前言 无论你是使用服务端整合包,还是从上一篇我的…...

第2篇 机器学习基础 —(2)分类和回归
前言:Hello大家好,我是小哥谈。机器学习中的分类和回归都是监督学习的问题。分类问题的目标是将输入数据分为不同的类别,而回归问题的目标是预测一个连续的数值。分类问题输出的是物体所属的类别,而回归问题输出的是数值。本节课就…...

Java游戏修炼手册:2023 最新学习线路图
前言 有没有一种令人兴奋的学习方法?当然有!绝对有!而且我要告诉你,学习的快乐可以媲美游戏的刺激。 小学时代,我曾深陷于一款名为"八百万勇士的梦"的游戏。每当放学,我总是迫不及待地打开电脑&a…...

前端访问geoserver服务发生跨域的解决办法,以及利用html2canvas下载绘制的地图
我的业务场景: 需要利用html2canvas下载Openlayers绘制的地图。 预期:可以下载成图片甚至其他格式(svg)文件。 结果:下载下来是个空白图片。 排查错误:请求数据正常回显到页面上,利用html2canvas截取的时候会发生跨域,导致无法绘制。 首先处理tomcat跨域问题 第一步…...

Word docx转html和markdown
Pypandoc使用pandoc来进行各种文本格式的转换。 安装 # 不带pandoc执行库 pip install pypandoc# 自带pandoc pip install pypandoc_binary使用 import pypandoc# convert all markdown files in a chapters/ subdirectory. pypandoc.convert_file(chapters/*.md, docx, out…...