Tomcat Servlet

news2024/11/25 10:48:46

Tomcat & Servlet

  • 一、What is “Tomcat”?
  • 二、 What is “Servlet”?
    • 1、HttpServlet
    • 2、HttpServletRequest
    • 3、HttpServletResponse

一、What is “Tomcat”?

Tomcat 本质上是一个基于 TCP 协议的 HTTP 服务器。我们知道HTTP是一种应用层协议,是 HTTP 客户端和 HTTP 服务器之间的交互数据的格式。Tomcat 就是基于 Java 实现的一个开源免费,也是被广泛使用的 HTTP 服务器。

以下是 Tomcat 安装完成后的文件目录:

运行Tomcat我们可以使用cmd命令查看Tomcat的端口号的进程ID:


二、 What is “Servlet”?

对于网站的后端开发,我们总是围绕着 HTTP 服务器展开相关工作,当然我们也可以重 0 开始写一个服务器,一步步的实现服务器的功能,包括根据 HTTP 协议解析请求报文、根据HTTP构造响应报文等等……对于服务器来说,很多功能都是千篇一律的,如果我们把中心放到整个服务器的开发上,这对于业务逻辑的开发来说,显然是非常不友好的。因此我们可以借助现成的 HTTP 服务器进行开发,例如 Tomcat 就为我们省去了这些不必要的环节,为我们提供了一些列的 API ,让我们能够更专注于业务逻辑。

Servlet 就是一组 Tomcat 提供的 API,让程序猿自己写的代码能很好的和 Tomcat 配合起来,从而更简单的实现一个 webapp,而不必关注 Socket、HTTP协议格式、多线程并发等技术细节,降低了 webapp 的开发门槛,提高了开发效率。

Servlet 中提供的 API 有很多,这里我们重点掌握 3 个类:HttpServletHttpServletRequestHttpServletResponse,下面我们逐一介绍👇:

1、HttpServlet

我们写 Servlet 代码的时候,首先第一步就是先创建类,继承自 HttpServlet,并重写其中的某些方法。

HttpServlet 核心方法展示:

方法名称调用时机
init在 HttpServlet 实例化之后被调用一次
destroy在 HttpServlet 实例不再使用的时候调用一次
service收到 HTTP 请求的时候调用
doGet收到 GET 请求的时候调用 (由 service 方法调用)
doPost收到 POST 请求的时候调用 (由 service 方法调用)
doPut/doDelete/doOptions/…收到其他请求的时候调用(由 service 方法调用)

其中 init、destroy、service 这 3 个方法的调用时机,就称为 “Servlet 生命周期”:

  1. init方法,只会在初始情况下调用1次,也就是HttpServlet实例化时调用,一般使用这个方法做一些初始化的相关工作。(HttpServlet 的实例只是在程序启动时创建一次,而不是每次收到 HTTP 请求都重新创建实例。)
  2. destroy方法,用于该webapp被销毁之前执行1次,用来做一些首尾工作。但是并不建议使用这个方法,因为通常采用直接杀死进程的方式停止服务器,此时destroy执行不了。
  3. service方法,每次收到路径匹配的请求都会执行,例如上述doGet、doPost方法其实都是在service方法中被调用,一般不会重写service方法。

在实际开发中,我们往往重写 doXXX 方法,很少会重写 init / destory / service:

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
    throws ServletException, IOException {
    	resp.getWriter().write("hello world");
    }
}

代码说明:

  1. 在这个类上方加上 @WebServlet("/hello") 注解, 表示 Tomcat 收到的请求中, 路径为 /hello的请求才会调用HelloServlet 这个类的代码

  2. HttpServletRequest 表示 HTTP 请求。Tomcat 按照 HTTP 请求的格式把 字符串 格式的请求转成了一个 HttpServletRequest 对象。后续想获取请求中的信息(方法、url、 header、body 等) 都是通过这个对象来获取。

  3. HttpServletResponse 表示 HTTP 响应。我们可以根据resp响应对象提供的方法,构造响应的状态码, header, body 等。Tomcat 会把整个响应转成字符串,通过 socket 写回给浏览器。

2、HttpServletRequest

当 Tomcat 通过 Socket API 读取到 HTTP 请求(字符串)后,就会按照 HTTP 协议的格式把字符串解析成 HttpServletRequest 对象。

HttpServletRequest 提供了一些方法,可以获取到一个请求中的各个方面的信息:

HttpServletRequest 提供的方法都只是“读”方法,而不是“写”方法。其实这也很容易理解,请求对象是服务器收到的内容,不应该被修改。

方法描述
String getProtocol()返回请求协议的名称和版本。
String getMethod()返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT。
StringBuffer getRequestURL()它用于获取请求的URL,不包含 query string
String getRequestURI()它用于获取请求的统一资源标识符(URI)的部分,即资源路径。
String getContextPath()获取请求的ContextPath,ContextPath标识一个webapp,即webapp的目录名
String getServlettPath()获取请求的ServletPath,ServletPath标识一个类
String getQueryString()返回包含在路径后的请求 URL 中的查询字符串。
Enumeration getHeaderNames()返回一个枚举,包含该请求中包含的所有请求头名。
String getHeader(String name)以字符串形式返回指定请求头的值。
String getCharacterEncoding()返回请求主体中使用的字符编码的名称。
String getContentType()返回请求主体的类型,如果不知道类型则返回 null。
int getContentLength()以字节为单位返回请求主体的长度,如果长度未知则返回 -1。
InputStream getInputStream()返回一个 InputStream 对象,用于读取请求的 body 内容。

上面这些方法只要对HTTP协议足够了解,简单看一下就能够使用。这里主要介绍有关getParameter相关的方法:

方法描述
Enumeration getParameterNames()返回一个枚举,表示在该请求中包含的参数的名称。
String getParameter(String name)返回请求参数的值,以字符串形式返回,如果参数不存在则返回 null。
String[] getParameterValues(String name)返回一个字符串数组,表示给定请求参数的所有值,如果参数不存在则返回 null。

这些方法主要是获取请求中的请求信息的,下面以getParameter()为例:

1. 获取GET请求中的参数值

@WebServlet("/getParameter")
public class Test extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // 前端通过 url 的 query string 传递 username 和 password 两个属性.
        String userName = req.getParameter("username");
        String passWord = req.getParameter("password");

        resp.setContentType("text/html; charset=utf-8");
        resp.getWriter().write("username="+userName+"<br/>"+"password="+passWord);
    }
}

2. 获取POST请求中的参数值

(1)请求参数通过body传递,采用 form 表单格式提交,即 Content-Type 是 application/x-www-form-urlencoded
此时同样可以使用getParameter直接获取参数值:

注意:需要显示地告诉后端请求的编码方式,防止解析请求时出现中文乱码情况。

@WebServlet("/postParameter")
public class Test extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
		// 显示地告诉后端请求的编码方式,防止中文乱码
        req.setCharacterEncoding("utf8");
		
        // 前端通过 url 的 query string 传递 username 和 password 两个属性.
        String userName = req.getParameter("username");
        String passWord = req.getParameter("password");

        resp.setContentType("text/html; charset=utf-8");
        resp.getWriter().write("username="+userName+"<br/>"+"password="+passWord);
    }
}

(2)请求参数通过body传递,Content-Type 是 application/json

对于Servlet,其没有内置 json 的解析功能,此时想要获取这种格式的参数就需要借助第三方库 jackson,首先我们在中央仓库找到 jackson 依赖引入到 pom.xml 中,然后就可以编写解析 json 格式请求参数的代码了。

使用 jackson,最核心的对象就是 ObjectMapper,通过这个对象里面的两个方法,就可以把 json 字符串解析成 java 对象;也可以把一个 java 对象转成一个 json 格式字符串,具体如下:

  1. writeValueAsString 方法把一个 Java 对象转成 JSON 格式字符串。
  2. readValue方法, 第一个参数为输入流对象,或Json字符串,的第二个参数为 JsonData 的 类对象,通过这个类对象,在 readValue 的内部就可以借助反射机制来构造出 Java 对象。
class User {
    public String username;
    public String password;

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

@WebServlet("/jsonParameter")
public class Test extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
     throws ServletException, IOException {
     	// 设置响应格式
        resp.setContentType("text/html;charset=utf-8");
        // 通过 post 请求的 body 传递过来一个 json 格式的字符串.
        // 1.使用objectMapper将json字符串解析成java对象
        User user = objectMapper.readValue(req.getInputStream(), User.class);
        resp.getWriter().write("1.使用objectMapper将json字符串解析成java对象:<br/>"+user.toString()+"<br/>");

        // 2.使用objectMapper将java对象解析成json字符串
        String jsonString = objectMapper.writeValueAsString(user);
        resp.getWriter().write("2.使用objectMapper将java对象解析成json字符串:<br/>"+jsonString);
    }
}

3、HttpServletResponse

Servlet 中的 doXXX 方法的目的就是根据请求计算得到响应,然后把响应的数据设置到 HttpServletResponse 对象中,Tomcat 内壁就会把这个 HttpServletResponse 对象按照 HTTP 协议的格式,转成一个字符串,并通过 Socket 写回给浏览器。

响应对象是服务器要返回给浏览器的内容,这里的重要信息都是程序员根据请求设置到响应中的,因此下面的方法都是 “写” 方法。

下面是在设置响应时常用到的方法:

方法描述
void setStatus(int sc)为该响应设置状态码。
void setHeader(String name, String value`设置一个带有给定的名称和值的 header。如果 name 已经存在,则覆盖旧的值。
void addHeader(String name, String value)添加一个带有给定的名称和值的 header。如果 name 已经存在,不覆盖旧的值,并列添加新的键值对。
void setContentType(String type)设置被发送到客户端的响应的内容类型。
void setCharacterEncoding(String charset)设置被发送到客户端的响应的字符编码(MIME 字符集),例如 UTF-8。
void sendRedirect(String location)使用指定的重定向位置 URL 发送临时重定向响应到客户端。
PrintWriter getWriter()用于往 body 中写入文本格式数据。
OutputStream getOutputStream()用于往 body 中写入二进制格式数据。

其实上面这些方法和同样只要对HTTP协议足够了解,简单看一下就能够使用,下面就简单演示几个方法,体会一下设置响应的过程:

(1)设置自动刷新

@WebServlet("/Refresh")
public class Refresh extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
     throws ServletException, IOException {
        // 设置自动刷新,刷新频率:每隔1秒自动刷新一次
        resp.setHeader("Refresh","1");
        resp.getWriter().write("time = "+System.currentTimeMillis());
    }
}

(2)设置重定向
方式1:使用 sendRedirect 方法

@WebServlet("/Redirect")
public class Redirect extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
     throws ServletException, IOException {
     	// 设置重定向:
        resp.sendRedirect("https://www.baidu.com");
    }
}

方式1:使用 setStatus + setHeader方法

@WebServlet("/Redirect")
public class Redirect extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
     throws ServletException, IOException {
        // 设置重定向:
        resp.setStatus(302);
        resp.setHeader("Location","https://www.baidu.com");
    }
}

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

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

相关文章

PWN 基础篇 Write Up

PWN 05 解题过程 给了两个文件&#xff0c;一个是asm后缀&#xff0c;汇编代码文件&#xff0c;另外一个file看看&#xff0c;32位i静态编译可执行文件 分析一下汇编代码&#xff0c;里面包含有两个节&#xff0c;data节 该代码片段只展示了数据段的一部分&#xff0c;缺少了…

[VIM]VIM初步学习-3

3-1 编写 vim 配置&#xff0c;我的 vim 我做主_哔哩哔哩_bilibili

【GESP考级C++】1级样题 闰年统计

GSEP 1级样题 闰年统计 题目描述 小明刚刚学习了如何判断平年和闰年&#xff0c;他想知道两个年份之间&#xff08;包含起始年份和终止年份&#xff09;有几个闰年。你能帮帮他吗&#xff1f; 输入格式 输入一行&#xff0c;包含两个整数&#xff0c;分别表示起始年份和终止…

(四)动态阈值分割

文章目录 一、基本概念二、实例解析 一、基本概念 基于局部阈值分割的dyn_threshold()算子&#xff0c;适用于一些无法用单一灰度进行分割的情况&#xff0c;如背景比较复杂&#xff0c;有的部分比前景目标亮&#xff0c;或者有的部分比前景目标暗&#xff1b;又比如前景目标包…

数量关系 --- 方程

目录 一、代入排除法 例题 练习 二、数字特性 例题 练习 整除特性 例题 倍数特性 普通倍数 因子倍数 比例倍数 例题 练习 三、方程法 例题 练习 四、 不定方程&#xff08;组&#xff09; 例题 练习 一、代入排除法 例题 素数&#xff1a…

以32bit加法器为核心的加法、减法、乘法和除法计算器(ALU)

1 任务概述 实现一个以加法器为核心的计算器。 加法&#xff1a;能够实现32bit加法 减法&#xff1a;能够实现32bit减法 乘法&#xff1a;能够实现两个32bit数字的乘法&#xff0c;乘积为64bit 除法&#xff1a;能够实现两个32bit无符号数的除法&#xff0c;商为32bit&#xf…

一款简化Python自然语言处理的开源库

迷途小书童 读完需要 3分钟 速读仅需 1 分钟 1 简介 TextBlob 是一个 Python 库&#xff0c;用于处理文本数据的自然语言处理&#xff08;NLP&#xff09;任务。它提供了简单且易于使用的 API&#xff0c;使得对文本进行分析、情感分析、词性标注、名词短语提取等任务变得更加简…

ARP和DDOS攻击防御介绍

ARP攻击如何产生的&#xff1f; ARP如何进行有效的防御&#xff1f; ARP地址解析协议 已知对方ip地址&#xff0c;求得对方mac地址 交换机会自动学习&#xff1a; 当pc1想访问外网&#xff0c;会向外发一个广播包&#xff0c;交换机会收到一个广播包 ARP地址表&#xff1a; …

Netgear R6700v3 1.0.4.102(CVE-2021-27239)

漏洞信息 此漏洞允许网络相邻攻击者在受影响的NETGEAR R6400和R6700固件版本1.0.4.98路由器上执行任意代码。利用此漏洞不需要身份验证。该漏洞存在于upnpd服务中&#xff0c;upnpd服务默认监听UDP 1900端口。SSDP消息中精心制作的MX报头字段可能会触发固定长度的基于堆栈的缓…

Python教程:PyQt5需要学习,哪些知识点??

PyQt5是基于图形程序框架Qt5的Python语言实现&#xff0c;由一组Python模块构成。它可用于Python 2和3&#xff0c;拥有超过620个类和6000个函数和方法。这是一个跨平台的工具包&#xff0c;可以运行在所有主要的操作系统&#xff0c;包括UNIX、Windows、Mac OS、Linux等。 #我…

打开英雄联盟缺少d3dcompiler_43.dll有哪些处理方法

五招步骤解决电脑d3dcompiler_43.dll文件丢失的问题&#xff01; 在使用电脑软件的过程中&#xff0c;我们可能会遇到一些奇怪的问题。其中之一就是打开某些软件时&#xff0c;系统提示找不到d3dcompiler_43.dll文件。这个错误通常出现在使用DirectX 11的应用程序中&#xff0…

CCF CSP认证 历年题目自练Day19

题目一 试题编号&#xff1a; 201812-1 试题名称&#xff1a; 小明上学 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 512.0MB 问题描述&#xff1a; 题目背景   小明是汉东省政法大学附属中学的一名学生&#xff0c;他每天都要骑自行车往返于家和学校。为了能尽可能充…

力扣刷题-哈希表-求两个数组的交集Ⅱ

350. 两个数组的交集 II 给你两个整数数组 nums1 和 nums2 &#xff0c;请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数&#xff0c;应与元素在两个数组中都出现的次数一致&#xff08;如果出现次数不一致&#xff0c;则考虑取较小值&#xff09;。可以不考虑…

【C语言】模拟实现strcpy

strcpy是常用的字符串函数 目录 介绍&#xff1a;模拟实现&#xff1a; 介绍&#xff1a; 我们可以知道此函数是为了拷贝字符串的 代码示例&#xff1a; #include<string.h>int main() {char str1[20] { 0 };char str2[] "hello world";strcpy(str1, str2)…

2023.10.01 homework

一个小数&#xff0c;小数位乘以3等于10.8&#xff0c;小数位乘以7等于13.2&#xff0c;求小数&#xff08;题目不是很严谨&#xff09;

自定义类型:结构体、位段、枚举、联合

文章目录 前言1. 结构体a. 关键字&#xff1a;structb. 结构体基础知识&#xff1a;c. 结构体声明&#xff1a;d. 特殊的声明e. 结构的自引用f. 结构体变量的定义与初始化<font color red>g. 结构体内存对齐h. 结构体传参 2. 位段a. 设计目的&#xff1a;节省空间b. 什么…

黑马程序员RabbitMQ入门到实战教程【高级篇】学习笔记

目录 一、发送者的可靠性 1.1、生产者重试机制 1.2、生产者确认机制 1.3、实现生产者确认 1.3.1、开启生产者确认 1.3.2、定义ReturnCallback 1.3.3、定义ConfirmCallback 二、MQ的可靠性 2.1、数据持久化 2.1.1.交换机持久化 2.1.2、队列持久化 2.1.3、消息持久化…

正则表达式 Regular Expression学习

该文章内容为以下视频的学习笔记&#xff1a; 10分钟快速掌握正则表达式_哔哩哔哩_bilibili正则表达式在线测试工具&#xff1a;https://regex101.com/, 视频播放量 441829、弹幕量 1076、点赞数 19330、投硬币枚数 13662、收藏人数 26242、转发人数 2768, 视频作者 奇乐编程学…

红包雨高并发压测记录(200台机器压测实录)

压测5000线程10秒内循环5次&#xff0c;5台2核心4线程的机器&#xff0c;QPS2500&#xff0c;每台机器需要承受500的QPS 压测10000线程10秒内循环5次&#xff0c;10台2核心4线程的机器&#xff0c;QPS5000&#xff0c;每台机器需要承受500的QPS 压测200000线程10秒内循环5次&am…

Overloud TH-U Complete for Mac:演绎您的音乐世界

Overloud TH-U Complete for Mac是一款功能强大的吉他谱曲软件&#xff0c;可以让您在Mac电脑上轻松进行吉他模拟、录音和混音等操作&#xff0c;创作属于自己的音乐作品。 Overloud TH-U Complete for Mac提供了丰富的吉他模拟和音效库&#xff0c;涵盖了多种吉他放大器、箱体…