Servlet 详解!

news/2025/1/19 11:35:26/文章来源:https://www.cnblogs.com/o-O-oO/p/18679395

一、Servlet简介

Servlet是Sun公司开发动态Web的一门技术。Sun公司在这些API中提供了一个Servlet接口,如果你想开发一个Servlet程序只需要完成如下两个步骤:

1、编写一个Java类实现Servlet接口。

2、把开发好的Java类部署到Web服务器中。

我们把实现了Servlet接口的Java程序叫做Servlet。

注:

  • 一个Servlet就是一个实现了Servlet接口的Java类。
    
  • 一个Servlet对应一个URL。
    

二、父项目与子项目

关于父子项目的理解:

(1)父项目的pom.xml配置文件中存在……标签,记录了子项目的信息:

<modules><module>servlet-01</module>
</modules>

(2)相对应的,子项目(即:Module模块)中存在……标签,记录了父项目的信息:

<parent><artifactId>javaWeb-Servlet</artifactId><groupId>com.atangbiji</groupId><version>1.0-SNAPSHOT</version>
</parent>

(3)父项目中的依赖包,子项目可以直接使用。(类似于Java中的继承)

这样我们把所有项目的依赖都添加到父项目的pom.xml配置文件中后,那么所有的子项目就不用每次再重复导入依赖包了。

(4)Servlet接口在子项目中实现。

三、Hello Servlet

3.1 创建父项目

(1)创建一个普通的Maven项目(具体步骤参考《Maven详解》),项目名称为javaWeb-Servlet。

(2)删除项目中的src目录,所得到的空项目就是我们的Maven父项目,我们可以在其中创建多个子项目(即:Module)。

(3)在父项目的pom.xml文件中导入父/子工程需要的依赖,根据需求查询有哪些依赖需要导入。

以Servlet项目为例,需要在父项目的pom.xml文件中导入如下依赖:

<dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version></dependency>
</dependencies>

注:若在父项目的pom.xml文件中已经添加了某个依赖后,则子项目的pom.xml文件中不要再重复添加该依赖了,否则Maven项目编译会出错。

至此,父项目创建完毕。

3.2 创建子项目

(1)在父项目中新建一个模块(子项目)。

(2)使用Maven模板创建一个MavenWeb子项目。

(3)填写子项目名称和Maven项目GAV。

(4)配置子项目Maven。点击Finish按钮完成子项目创建,等待Maven依赖包导入完毕。

(5)由于使用Maven模板创建的MavenWeb项目的版本较低(“web-app_2_3”)。为了避免以后出现兼容性问题,建议我们先将该子项目中的web.xml文件替换成“web-app_4_0”版本。具体可以参考Tomcat安装目录下的(D:\Environment\apache-tomcat-9.0.65\webapps\examples\WEB-INF)web.xml文件。

web.xml文件:

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app>

注:Web.xml是Java Web项目的一个核心配置文件,主要用于配置首页、Servlet、Filter、Listener等。

(6)在子项目的main文件夹下新建一个java文件夹和一个resource文件夹,并将它们分别标记为“源码根目录”和“资源根目录”。(具体步骤参考《Maven详解》)

(7)至此,子项目创建完毕。编译父项目或子项目,此时父项目与子项目的目录结构如下图所示。

3.3 编写一个Java类实现Servlet接口(重点)

(1)在子项目的java目录下新建一个com.atangbiji.servlet包,并在该包下新建一个HelloServlet类,用于实现Servlet接口。

(2)让HelloServlet类继承(extends)HttpServlet类。(此时,Maven会通过父项目中的依赖自动导入依赖包。)

HelloServlet.java文件:

public class HelloServlet extends HttpServlet {}

注:

  • Servlet是一个接口程序,也就是一个java程序,其存放于main-java文件夹中。

  • 由于sun公司为我们提供了两个默认的Servlet接口实现类:①HttpServlet,②GenericServlet。因此,我们只需继承HttpServlet类便可实现Servlet接口。

附:Servlet接口、GenericServlet类和HttpServlet类详解

a、Servlet接口源码

public interface Servlet {void init(ServletConfig var1);ServletConfig getServletConfig();void service(ServletRequest var1, ServletResponse var2);//核心接口String getServletInfo();void destroy();
}

b、GenericServlet类源码(部分)

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {……public abstract void service(ServletRequest var1, ServletResponse var2);//直接继承,未做任何处理……
}

c、HttpServlet类源码(部分)

public abstract class HttpServlet extends GenericServlet {……//重写service方法public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {HttpServletRequest request = (HttpServletRequest)req;HttpServletResponse response = (HttpServletResponse)res;this.service(request, response);} else {throw new ServletException("non-HTTP request or response");}}//重载service方法protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String method = req.getMethod();long lastModified;//若请求方式为get,则调用doGet方法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);                //若请求方式为post,则调用doPost方法} 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);}}protected void doGet(HttpServletRequest req, HttpServletResponse resp) {……}protected void doPost(HttpServletRequest req, HttpServletResponse resp){……}……
}

分析源码,我们可以发现:

  • 我们自定义的Servlet类与Servlet接口、GenericServlet类和HttpServlet类的关系如下图所示。

  • HttpServlet类重写的service(ServletRequest,ServletResponse)方法中会把ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse,然后再调用service(HttpServletRequest,HttpServletResponse)方法。

  • HttpServlet类重载了service(HttpServletRequest,HttpServletResponse)方法,该方法是 HttpServlet 自己重载的方法,而不是从Servlet继承来的。

【结论】:HttpServlet类在重载的service(HttpServletRequest,HttpServletResponse)方法中,会根据不同的Http请求方式,调用不同的处理方法。因此,我们需要在我们自己编写的Servlet类中重写相应的Http请求处理方法(重点掌握doGet和doPost方法)。

:我们可以通过IDEA为我们提供的Structure窗口来查看HttpServlet类的成员变量和成员函数。

(3)在HelloServlet类中重写doGet和doPost方法。

HelloServlet.java文件:

public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("进入了doGet方法");//在控制台打印调试信息PrintWriter writer = resp.getWriter();//响应流writer.print("Hello Servlet!");//在浏览器显示Hello Servlet!}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);    //因为`get`和`post`只是不同的Http请求方式,所以它们之间可以相互调用。}
}

:因为get和post只是不同的Http请求方式,所以它们之间可以相互调用。

3.4 编写Servlet的映射(重点)

:因为我们写的是一个Java程序,但是如果我们要通过浏览器去访问它,就需要连接web服务器。因此,我们需要在Web配置文件(web.xml)中注册(映射)我们自己编写的Servlet,并为其提供一个浏览器可以访问的路径。

web.xml文件:

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"><!--  注册Servlet  --><servlet><servlet-name>servlet1</servlet-name><servlet-class>com.atangbiji.servlet.HelloServlet</servlet-class></servlet><!--  Servlet的访问路径  --><servlet-mapping><servlet-name>servlet1</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping></web-app>

3.5 配置Tomcat服务器

(1)配置Tomcat服务器。(具体步骤参考《Tomcat详解》)

(2)deploy(发布)servlet-01:war包,并为该子项目添加虚拟路径映射:/s1。

3.6 启动测试

在IDEA中启动Tomcat。

(1)在浏览器中输入http://localhost:8080/s1/,访问结果如下:

:此时访问的是该Web项目的index.jsp文件。

index.jsp文件:

<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

(2)在浏览器中输入http://localhost:8080/s1/hello,访问结果如下:

:此时访问的是我们自己编写的Servlet类。

原创 阿汤笔迹

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

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

相关文章

图论/连通性

点边连通度:耳分解: 强连通有向图/边双联通无向图 从一个点出发,每次加入从集合出发回到集合,中间点不在集合内的环,一定能生成该图。 边双 强连通 双极定向:link 割空间与环空间互为正交补。 切边等价:模板 qoj1351CF1648F 树分解:也就是找到一种划分方式,使得每种划…

比特c语言-分支与循环

# 分支与循环 if语句 目录if语句ifeg:输入一个整数,判断是否为奇数elseeg:输入一个整数,判断是否为奇数,如果是奇数打印是奇数,否则打印偶数嵌套ifeg:输入一个人的年龄关系操作符条件操作符eg:使用条件操作符表示代码逻辑eg:使用条件表达式找两个数中较大值逻辑操作符…

NOIP 冲刺之——数据结构

\(\texttt{0x00}\) 前言 本篇文章主要记录笔者 NOIP 冲刺阶段复习的各种数据结构题型及 tricks ans tips,同时也用于及时复习与巩固。 那么,开始吧。 \(\texttt{0x01}\) 树状数组、线段树 知识点 \(1\):二维偏序 众所周知,逆序对可以用归并排序离线求,但是要求在线呢? 这…

windows 将docker desktop上镜像打包并通过资源管理器找到使用

在 Windows 上使用 Docker Desktop 时,可以通过以下步骤将 Docker 镜像保存为 .tar 文件,并通过资源管理器找到该文件:步骤 1:打开 Docker Desktop 确保 Docker Desktop 正在运行。如果未运行,请启动它。步骤 2:打开 PowerShell 或命令提示符按 Win + S,搜索 PowerShell…

解决方案 | office365/office 修复方法

打开控制面板,选择卸载程序,右键office 一般情况下,选择快速修复可以实现修复。如不行,那么选择联机修复‘。还是不行那就重装office

【pywinauto 库】启动PC端应用程序 - 上篇

一、简介 经过上一篇的学习、介绍和了解,想必小伙伴或者童鞋们,已经见识到pywinauto的强大了,今天继续介绍pywinauto,上一篇已经可以打开计算器了,这里宏哥再提供其他方法进行打开计算器和非电脑自带程序。pywinauto 可以启动电脑自带的应用程序,也可以启动电脑安装的应用…

【反EDR 】概要

一、什么是 EDR EDR 是“端点检测和响应”的缩写。它是部署在每台机器上的代理,用于观察操作系统生成的事件以识别攻击。如果检测到某些东西,它将生成警报并将其发送到 SIEM 或 SOAR,由人工分析师进行查看。“响应”是指在识别威胁后执行的操作,例如隔离主机,这不是本文的…

USB接口颜色都代表什么含义

手机充电器人人都有!充电器线颜色都不同!你知道不同颜色的USB接口的各个颜色都代表什么含义吗?大部分人都是不知道的,这篇文章让您 一目了然!建议收藏备用!以备不时之需!

Windows资源管理器Icon图标注入

免责声明 本文发布的工具和脚本,仅用作测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。简介 使用图标将 DLL 注入资源管理器的非正统和隐蔽方式 IconJector 这是一个Windows资源管理器DLL注入技术,使用Windows上的更改图…

ElasticSearch Query DSL(查询领域特定语言)

目录常用 DSL 关键字查询上下文相关度评分:_score源数据:_source数据源过滤器query 和 filter 上下文相关性评分 (relevance scores)query 的上下文filter 的上下文关于 query 和 filter 上下文的例子全文查询 (full text query)intervals 查询请求示例intervals的顶级参数ma…

ESP32 学习笔记(九)舵机实验

概念 舵机是一种位置(角度)伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。舵机只是一种通俗的叫法,其本质是一个伺服电机。 舵机有很多规格,但所有的舵机都有外接三根线,分别用棕、红、橙三种颜色进行区分,由于舵机品牌不同,颜色也会有所差异,棕色为…

(原创)[开源][.Net Standard 2.0] SimpleMMF (进程间通信框架)更新 v1.1,极低CPU占用

一、前言 在上一篇 (原创)[.Net] 进程间通信框架(基于共享内存)——SimpleMMF 中,发布了v1.0版,最大的问题是:CPU占用较高,至少40-50%。 这既与我的开发水平有关,也与SimpleMMF诞生环境有关,这个主要是用在数字孪生各软件之间同步数据,而部署软件的工作站性能都强悍…