详解Servlet API

news2024/7/6 0:15:19

目录

前言

HttpServlet

HttpServletRequest

代码实例

打印请求信息

通过URL中的queryString进行传递。

通过post请求的body,使用form表单传递

通过POST 请求中的 body 按照 JSON 的格式进行传递

HttpServletResponse

核心方法代码实例

设置状态码

自动刷新

重定向

总结


前言

Servlet的API是非常多的,但是我们只需要重点掌握三个类即可!!!

  • HttpServlet
  • HttpServletRequest
  • HttpServletResponse

HttpServlet

我们在写Servlet代码的时候,第一步都是先创建一个类,然后让这个类去继承HttpServlet,并重写其中的某些方法。那么我们就需要知道,HttpServlet这个类中都有那些方法,都是干啥的。

方法名称调用时机
init在HttpServlet实例化之后被调用一次
destroy在HttpServlet实例之后不再使用的时候调用一次
service在收到HTTP请求时调用
doGet在收到get请求的时候由service调用
doPost在收到post请求的时候由service调用
doPut/doDlete/......在收到其他请求时由service调用
@WebServlet("/hello1")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("hello world");
        resp.getWriter().write("hello");
    }
}

init():

HttpServlet被实例化之后,会调用一次,使用这个方法来做一些初始化的工作。

需要注意的是,init方法不是被实例化的时候调用,而是首次收到请求的时候调用。

 

 

 这个请求就会触发HelloServlet类的doGet方法的执行。但是会在执行doGet方法之前,先调用init方法。

init方法的调用时机:

只会在首次收到请求的时候调用一次,等下次再次收到请求,就不会再调用init方法了。也就是说,init方法在Servlet整个生命周期中,只会调用一次。

destroy():

这个方法时在HttpServlet实例销毁之前调用一次,来做一些收尾工作。

这个方法需要注意的是,如果通过Servlet的管理端口8005来停止Servlet服务,此时的destroy方法就会执行,如果要是通过直接杀死进程的方式来停止Servlet服务,那么destroy就不会执行。

service():

service方法是当收到一个路径匹配的请求时,就会执行一次。

我们的doGet/doPost/doDelete....等方法,都是在service方法中进行调用的。

所以我们在重写方法的时候,一般不会去重写service方法,而是重写doXXX方法。

一道面试题:Servlet的生命周期?

上述方法的调用时机,就成为Servlet的生命周期。

 

HttpServletRequest

这个类对应一个HTTP请求,一个HTTP请求中有什么,这个类中就有什么。

这个类中的方法是比较多的,但是都比较清晰。

方法描述
String getProtocol()返回请求协议的名称和版本。
String getMethod()返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT。
String getRequestURI()从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请
求的 URL 的一部分。
String getContextPath()返回指示请求上下文的请求 URI 部分。
String getQueryString()返回包含在路径后的请求 URL 中的查询字符串。
Enumeration
getParameterNames()
返回一个 String 对象的枚举,包含在该请求中包含的参数的名
称。
String getParameter(String
name)
以字符串形式返回请求参数的值,或者如果参数不存在则返回
null。
String[]
getParameterValues(String
name)
返回一个字符串对象的数组,包含所有给定的请求参数的值,如
果参数不存在则返回 null。
Enumeration
getHeaderNames()
返回一个枚举,包含在该请求中包含的所有的头名。
String getHeader(String
name)
以字符串形式返回指定的请求头的值。
String
getCharacterEncoding()
返回请求主体中使用的字符编码的名称。
String getContentType()返回请求主体的 MIME 类型,如果不知道类型则返回 null。
int getContentLength()以字节为单位返回请求主体的长度,并提供输入流,或者如果长
度未知则返回 -1。
InputStream
getInputStream()
用于读取请求的 body 内容. 返回一个 InputStream 对象.

代码实例

打印请求信息

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

@WebServlet("/ShowRequest")
public class ShowRequest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        StringBuilder result = new StringBuilder();  //使用StringBuilder来显示请求的内容
        result.append(req.getProtocol());   //请求的协议和版本
        result.append("<br>");
        result.append(req.getMethod());   //请求的方法
        result.append("<br>");
        result.append(req.getRequestURI());   //请求的uri 唯一资源标识符
        result.append("<br>");
        result.append(req.getQueryString());   //请求的queryString
        result.append("<br>");
        result.append(req.getContextPath());   //请求URL的上下文路径
        result.append("<br>");
        result.append("=========================<br>");
        Enumeration<String> headerNames =  req.getHeaderNames();  //请求的header头名,返回值是一个枚举类型
        while (headerNames.hasMoreElements()) {   //遍历这个headerNames枚举对象
            //header中是一个个的键值对
            String headerName = headerNames.nextElement();   //获取到header中键值对的键
            String headerValue = req.getHeader(headerName);  //通过键值对中的键获取到对应的值
            result.append(headerName+": " + headerValue+"<br>");
        }
        //设置响应到浏览器的类型和字符格式
        resp.setContentType("text/html;charset=utf8");
        //把响应写会浏览器
        resp.getWriter().write(result.toString());
    }
}

上述在进行append的时候,我们并不是使用的\n来表示换行,因为我们返回的String在浏览器页面上是以HTML的格式进行解析的,所以我们要想换行,就得使用HTML中的换行标签。

Enumeration<String> headerNames =  req.getHeaderNames();  //请求的header头名,返回值是一个枚举类型
        while (headerNames.hasMoreElements()) {   //遍历这个headerNames枚举对象
            //header中是一个个的键值对
            String headerName = headerNames.nextElement();   //获取到header中键值对的键
            String headerValue = req.getHeader(headerName);  //通过键值对中的键获取到对应的值
            result.append(headerName+": " + headerValue+"<br>");
        }

上述代码则是把整个header中内容全部拼接到stringbuilder中 

下面来看看运行结果。

接下来介绍下一组API 

获取get请求中的值

前端先后端传递值的方法有多种。

通过URL中的queryString进行传递。

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/getParameter")
public class getParameter extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //前端通过URL中的query String 来传递username和password两个属性
        String username = req.getParameter("username");
        if (username == null) {
            System.out.println("username 这个key在queryString中不存在");
        }
        String password = req.getParameter("password");
        if (password == null) {
            System.out.println("password 这个key在queryString中不存在");
        }

        System.out.println("username " + username + "  password" + password);
        resp.getWriter().write("ok");
    }
}

我们知道QueryString是键值对的方式来向后端传递数据的。 

 比如前端通过QueryString的方式传递username和password两个属性。我们要获取这两个属性中对于的value。就可以通过getParameter()方法来获取键对应的值。

下面我们运行程序,来看效果。

我们在URL中通过QueryString的方法向后端传递了两个键值对,分别是username=zhangsan,

password=123。

 可以看出后端在控制台成功的输出了这两个键对应的值。

通过post请求的body,使用form表单传递

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/getParameter")
public class getParameter extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf8");
        //前端通过body  form表单 传递username和password
        String username = req.getParameter("username");
        if (username == null) {
            System.out.println("username 这个key在queryString中不存在");
        }
        String password = req.getParameter("password");
        if (password == null) {
            System.out.println("password 这个key在queryString中不存在");
        }
        System.out.println("username " + username + "  password" + password);
        resp.getWriter().write("ok");
    }
}

我们通过Postman来构造通过form表单传递数据的请求。

 

可以看出服务器成功的返回了一个ok。这个OK并不能代表什么,我们来看看服务器控制台的输出。

 

 服务器也成功的打印出来了对应的value。

通过POST 请求中的 body 按照 JSON 的格式进行传递

我们需要引入 Jackson 这个库, 进行 JSON 解析。

1:在Maven中央仓库搜索Jackson,选择Jackson Databind

 

 然后选择版本2.15.0

2:把中央仓库中的依赖配置添加到 pom.xml 中, 形如

<!--Jackson依赖用来前端通过JSON发送数据  后端进行JSON解析-->
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.15.0</version>
        </dependency>

然后就可以编写代码了。 

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

class User {
    public String username;
    public String password;
}
@WebServlet("/JSON")
public class JsonServlet extends HttpServlet {
// 创建 ObjectMapper 对象. 这个是 Jackson 中的核心类
    public ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //通过post请求的body传递过来一个JSON格式请求的字符串
// 通过 readValue 方法把 body 这个字符串转成 User对象
        User user = objectMapper.readValue(req.getInputStream(), User.class);
        System.out.println("username "+ user.username +", password"+user.password);
        resp.getWriter().write("ok");
    }
}

可以看出我们代码中用多了一个User类,这个类用于解析生成后的JSON对象,这个类中的属性名字要和传递过来的key对应。

User user = objectMapper.readValue(req.getInputStream(), User.class);

通过反射的机制把body中的key对应的value全部放在User对象中去,这就是为什么User类的属性和类型、名称都要和body中的key保持一致的原因。

然后就可以通过user对象来获取到username和password两个属性的value了。

下面我们运行代码看效果:

我们通过Postman构造了JSON的请求并发送,服务器也成功的响应了。

接下来我们看服务器控制台输出的内容。

 

服务器也是成功的获取到了key对应的value。

 

HttpServletResponse

这个类是一个HTTP的响应,一个响应中有什么,这个类中就有什么。

Servlet中的doXXX方法就是根据请求计算响应,然后把响应的数据写回到HttpServletResponse这个对象中。

然后Tomcat会把这个对象按照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 中写入二进制格式数据.

核心方法代码实例

设置状态码

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@WebServlet("/status")
public class Status extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(200);   //给响应设置状态码
        resp.setContentType("text/html; charset=utf8");
        resp.getWriter().write("返回设置状态码200");
    }
}

 服务器返回数据,下面我们通过fiddler来抓包看看。

可以看到,状态码确实设置为了200。

自动刷新

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/Refresh")
public class RefreshServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //在响应里面设置自动刷新字段 1秒刷新一次
        resp.setHeader("refresh","1");
        resp.getWriter().write("time"+ System.currentTimeMillis()); //记录当前时间戳
    }
}

此时就会每隔一秒刷新一次页面。

重定向

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/redirect")
public class Redirect extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //当用户访问这个路径的时候,自动重定向到百度的主页
        resp.setStatus(302);  //设置重定向状态码302
        resp.setHeader("location","https://www.baidu.com");
    }
}

当我们在地址栏输出URL时,就会重定向到百度的页面。

 

总结

以上就是Servlet API的讲解,不足之处,希望各位大佬多多指教。

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

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

相关文章

【C++初阶】string 类的认识与学习

在学习string类之前&#xff0c;先在这里推荐2个好用的网站&#xff0c;可以用来查阅C的相关知识 https://cplusplus.com https://en.cppreference.com/w/ 上面的是非官方的&#xff0c;下面的官方的&#xff0c;但是个人感觉还是上面的好用。 一.string 类是什么 简单来说&…

State of GPT (ChatGPT 原理及现状介绍)

State of GPT 演讲信息&#xff1a; 演讲人&#xff1a;Andrej Karpathy (现在OpenAI任职)&#xff0c;之前是特斯拉视觉研发负责人&#xff0c;斯坦福深度学习入门课程 CS231N 讲师演讲主题&#xff1a;受到微软 BUILD2023 邀请&#xff0c;介绍 GPT 的原理及研发现状&#x…

VMware虚拟机安装Ubuntu 22.04详细教程(2023年新版教程)

VMware虚拟机安装Ubuntu 22.04详细教程&#xff08;保姆级教程&#xff09; 大家好&#xff0c;我是洲洲&#xff0c;欢迎关注&#xff0c;一个爱听周杰伦的程序员。关注公众号【程序员洲洲】即可获得10G学习资料、面试笔记、大厂独家学习体系路线等…还可以加入技术交流群欢…

代码创作世界——pytorch深度学习框架数据类型

代码创作世界——pytorch深度学习框架数据类型 torch中的数据类型张量&#xff08;tensor&#xff09; pytorch中的 在数学中&#xff0c;一个单独的数可以成为标量&#xff0c;一行或者一列数组可以称为向量&#xff0c;一个二维数组称为一个矩阵&#xff0c;矩阵中的每一个元…

编译安装nginx服务

目录 编译安装nginx服务 1.关闭防火墙&#xff0c;将安装nginx所需软件包传到/opt目录下 2.安装依赖包 3.创建运行用户、组&#xff08;Nginx服务程序默认以nobody身份运行&#xff0c;建议为其创建专门的用户账号&#xff0c;以便更准确的控制访问权限&#xff09; 4.编译…

11.PasswordEncoder详解与实战

security/day07 这节课我们开始讲PasswordEncoder&#xff0c;如果大家还有印象的话&#xff0c;我们前面有提到过PasswordEncoder: 为什么密码使用{noop}开头呢&#xff1f;我们也做出了相应的解释&#xff0c;这节课开始带大家真正的了解PasswordEncoder, PassworderEncoder…

Android以aar包形式引入hunter-timing,Java(4)

Android以aar包形式引入hunter-timing&#xff0c;Java&#xff08;4&#xff09; &#xff08;1&#xff09;参照这篇文章&#xff1a; https://zhangphil.blog.csdn.net/article/details/130603231https://zhangphil.blog.csdn.net/article/details/130603231 生成.aar文件…

路径规划算法:基于象群优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于象群优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于象群优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法象群…

python基础知识(六):列表

目录 1. 列表及其创建2. 列表的特点3. 获取指定元素的索引4. 获取列表中指定索引的元素5. 列表的切片操作6. 列表元素的判断及遍历7. 列表元素的添加操作8. 列表的删除9. 列表元素的修改10. 列表元素的排序11. 列表生成式 1. 列表及其创建 列表由一系列按特定顺序排列的元素组…

如何设计一份优秀的 PPT 文档?

设计一份优秀的 PPT 需要考虑以下几个方面&#xff1a; 目标和受众&#xff1a;明确你的 PPT 的目标是什么&#xff0c;以及你的受众是谁。这将帮助你确定内容的重点和风格。结构和流程&#xff1a;确定清晰的结构和流程&#xff0c;使你的 PPT 有逻辑性。使用标题、副标题和分…

算法与数据结构(三)——排序算法大总结

六大排序算法&#xff1a;插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序 一、插入排序二、选择排序三、冒泡排序四、归并排序 一、插入排序 1.从第一个元素开始&#xff0c;该元素可以认为已经被排序 2.取下一个元素tem&#xff0c;从已排序的元素序列从后往前扫…

三、DMSP/OLS、NPP/VIIRS等夜间灯光数据能源碳排放空间化——灯光指数计算(二)

一、前言 续上一节,建成区提取方式有很多种,本文主要介绍一种区别于参考比较法、突变检测法等的领域分析提取建成区范围。 本文以广州市为例,基于领域分析提取2020年广州市建成区范围。 二、具体步骤 (1)加载数据并将广州市夜间灯光数据提取出来 (2)搜索"邻域…

【前端】Vue项目中 JSON 编辑器的使用

Vue项目中 JSON 编辑器的使用 一、背景描述二、vue-json-edit2.1 依赖安装2.2 示例代码2.3 效果图 三、vue-json-pretty3.1 依赖安装3.2 示例代码3.3 效果图 四、bin-code-editor4.1 依赖安装4.2 示例代码4.3 效果图 五、vue-json-views5.1 依赖安装5.2 示例代码5.3 效果图5.4 …

json库——jsoncpp

一、jsoncpp简介 JsonCpp是一个开源的C库&#xff0c;用于解析和生成JSON&#xff08;JavaScript Object Notation&#xff09;数据格式。JSON是一种轻量级的数据交换格式&#xff0c;广泛用于各种应用程序和网络服务中。 JsonCpp提供了简单和易用的API&#xff0c;可以方便地解…

C Primer Plus第十七章编程练习答案

学完C语言之后&#xff0c;我就去阅读《C Primer Plus》这本经典的C语言书籍&#xff0c;对每一章的编程练习题都做了相关的解答&#xff0c;仅仅代表着我个人的解答思路&#xff0c;如有错误&#xff0c;请各位大佬帮忙点出&#xff01; 有些题目函数定义在书本存在&#xff…

路径规划算法:基于鸽群优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于鸽群优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于鸽群优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法鸽群…

Python编程面试题及答案(20例)

以下是一些常见的Python编程面试题以及它们的答案&#xff1a; 1.解释Python中的 GIL&#xff08;全局解释器锁&#xff09;是什么&#xff0c;它对多线程编程有什么影响&#xff1f; 答案&#xff1a;GIL是Python解释器中的一个机制&#xff0c;它确保在任何给定时间只有一个…

超详细Redis入门教程——Redis 主从集群(上)

前言 本文小新为大家带来 Redis 主从集群 相关知识&#xff0c;具体内容包括主从集群搭建&#xff08;包括&#xff1a;伪集群搭建与配置&#xff0c;分级管理&#xff0c;容灾冷处理&#xff09;&#xff0c;主从集群搭建&#xff08;包括&#xff1a;主从复制原理&#xff0c…

MySQL数据库从入门到精通学习第7天(表数据的增、删、改操作)

表数据的增、删、改操作 使用INSERT...VALUES语句插入数据修改数据删除数据 使用INSERT…VALUES语句插入数据 语法&#xff1a; INSERT [INTO] 数据表名[(字段名...)] VALUES ({值 | DEFAULT},...),()...; [INTO] 数据表名&#xff1a;可选项&#xff0c;用于指定被操作的数…

手把手教你rtsp流媒体分析(引导篇,欢迎订阅专栏)

系列音视频开发 文章目录 系列音视频开发前言一、RTSP是什么&#xff1f;二、RTP是什么&#xff1f;三、RTCP是什么&#xff1f;四、RTSP 源码学习五、H265 RTSP流总结 前言 在安防行业中&#xff0c;onvif协议与gb协议是两种标准&#xff0c;gb是国内安防行业的标准&#xff…