【JavaEE初阶】Servlet (二) Servlet中常用的API

文章目录

  • HttpServlet
    • 核心方法
  • HttpServletRequest
    • 核心方法
  • HttpServletResponse
    • 核心方法

Servlet中常用的API有以下三个:

  • HttpServlet
  • HttpServletRequest
  • HttpServletResponse

HttpServlet

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

核心方法

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

说明:

  • init:tomcat首次收到和该类相关联的请求时触发.(类似于前面学的懒汉模式).例如:在这里插入图片描述
    tomcat收到 /hello 的路径请求,就会调用到HelloServlet进行实例化,于是就需要先对helloServlet进行实例化.(实例化只进行一次). 后续再收到 /hello,就不必重复实例化了,直接复用之前的HelloServlet实例即可.
  • destroy:通过重写我们可以看到:在这里插入图片描述
  • service:收到http请求就会触发(路径匹配请求).

以上三个方式是HTTPServlet最关键的三个方法.

面试题:Servlet的声明周期是什么?

  1. 开始的时候,执行init
  2. 每次收到请求的时候,执行service
  3. 销毁之前,执行destroy

在这里插入图片描述
在浏览器中直接输入URL可以看到doGet请求:
在这里插入图片描述
那么其他请求怎么构造呢?

  1. 可以使用Postman.
    在这里插入图片描述
    同时我们可以服务器处看到日志:
    在这里插入图片描述
  2. 使用ajax构造请求
    注意文件创建位置.
    在这里插入图片描述
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <!-- 构造ajax请求访问服务器 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
    <script>
        $.ajax({
            type:'get',
            url:'method',
            success:function(body,status){
                console.log(body);
            }
        })
    </script>
</body>
</html>

在这里插入图片描述
上述代码中url:'method'相对路径.url:"/hello_servlet/method"绝对路径.(浏览器中的要求) 注意两种路径的写法.还有在@WebServlet("/hello")这个注解中,这个路径必须/开头,但是并非表示绝对路径(Servlet中的要求)

HttpServletRequest

HttpServletRequest表示的是HTTP请求. 这个对象是Tomcat自动构造的.Tomcat会实现监听端口,接受连接,读取请求,构造请求对象等工作.

核心方法

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

说明:

  • query String是键值对结构,使用getParameter就可以根据key获取到value.
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("/showRequest")
public class ShowRequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(req.getProtocol());
        stringBuilder.append("<br>");
        stringBuilder.append(req.getMethod());
        stringBuilder.append("<br>");
        stringBuilder.append(req.getRequestURI());
        stringBuilder.append("<br>");
        stringBuilder.append(req.getContextPath());
        stringBuilder.append("<br>");
        stringBuilder.append(req.getQueryString());
        stringBuilder.append("<br>");

        resp.getWriter().write(stringBuilder.toString());
    }
}

在这里插入图片描述
在这里插入图片描述

前端给后端传参的三种方式 :

  1. GET,queryString
  2. POST,from
  3. POST,json
  1. GET,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 GetParameterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 预期浏览器会发一个形如 /getParameter?studentId=10&classId=20 请求.
        // 借助 req 里的 getParameter 方法就能拿到 query string 中的键值对内容了.
        // getParameter 得到的是 String 类型的结果.
        String studentId = req.getParameter("studentId");
        String classId = req.getParameter("classId");
        resp.setContentType("text/html; charset=utf8");
        // resp.setCharacterEncoding("utf8");
        resp.getWriter().write("学生id = " + studentId + " 班级id = " + classId);
    }
}

在这里插入图片描述
在这里插入图片描述
如果key在queryString中不存在,此时就返回null.

  1. POST,from

对于前端from表单这样的数据结构,后端还是使用GetParameter来获取.注意,from表单也是键值对,和queryString的格式一样,只是这部分内容在body中

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <form action="postParameter" method="post">
        <input type="text" name="studentId">
        <input type="text" name="classId">
        <input type="submit" value="提交">
    </form>
    <!-- 构造ajax请求访问服务器 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <script>
        // $.ajax({
        //     type:'get',
        //     url:'method',
        //     success:function(body,status){
        //         console.log(body);
        //     }
        // })
    </script>

</body>
</html>

在这里插入图片描述
请添加图片描述
使用getparameter既可以获取到queryString键值对,也可以获取到form表单构造的body中的键值对.

上述过程,是前后端交互的过程.
在这里插入图片描述
在这里插入图片描述
3. POST,json
json是一种非常主流的数据结构,也是键值对结构
使用Postman构造POST:
在这里插入图片描述
下面写PostParameter2服务器代码:

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.io.InputStream;

@WebServlet("/postParameter2")
public class PostParameter2Servlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 通过这个方法来处理 body 为 json 格式的数据.
        // 直接把 req 对象里 body 完整的读取出来.
        // getInputStream
        // 在流对象中读多少个字节? 取决于 Content-Length
        int length = req.getContentLength();
        byte[] buffer = new byte[length];

        InputStream inputStream = req.getInputStream();
        inputStream.read(buffer);
        // 把这个字节数组构造成 String, 打印出来.
        String body = new String(buffer, 0, length, "utf8");
        System.out.println("body = " + body);
    }
}

打开Postman发送请求,在日志可以看到:
在这里插入图片描述
打开fiddler抓包可以看到:
在这里插入图片描述
小结:
在这里插入图片描述
当前通过json传递数据,但是服务器这边只是把整个body读取进来,并没有按照键值对的方式来处理(还不能根据key获取value),此时可以使用第三方库来解决这个问题.
打开maven中央仓库:
在这里插入图片描述
在这里插入图片描述

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;
import java.io.InputStream;

class Student {
    public int studentId;
    public int classId;

}
@WebServlet("/postParameter2")
public class PostParameter2Servlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 使用 jackson 涉及到的核心对象.
        ObjectMapper objectMapper = new ObjectMapper();
        // readValue 就是把一个 json 格式的字符串转成 Java 对象.
        Student student = objectMapper.readValue(req.getInputStream(), Student.class);
		System.out.println(student.studentId + ", " + student.classId);
        //resp.getWriter().write(body);

    }
}
  1. 会从body中读取json格式的字符串
  2. 根据第二个参数类对象,创建Student实例
  3. 解析上述json格式的字符串,处理成map键值对结构
  4. 遍历所有键值对,看键的名字和student实例中那个属性名字匹配,就把对应的value设置到该属性中.
  5. 返回该Student实例

在这里插入图片描述
如果请求中多一个参数,Student中没有,则会出现500 服务器内部错误.
在这里插入图片描述
如果请求中少一个参数,Student中有这个参数,则会返回默认值.
在这里插入图片描述

HttpServletResponse

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

核心方法

方法描述
void setStatus(int sc)为该响应设置状态码。
void setHeader(String name,String value)设置一个带有给定的名称和值的 header. 如果 name 已经存在,则覆盖旧的值.
void addHeader(Stringname, 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 中写入二进制格式数据.

说明:

  • sendRedirect重定向.
    两种写法:
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("https://www.baidu.com");
    }
}
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(302);
        resp.setHeader("Location","https://www.baidu.com");
    }
}

启动服务器,在地址栏中输入http://127.0.0.1:8080/hello_servlet/redirect可以看到网页跳转至百度页面:
在这里插入图片描述
使用fiddler可以看到:
在这里插入图片描述
上述GET请求触发resp.sendRedirect("https://www.baidu.com");代码,从而得到响应:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot+Prometheus+Grafana实现系统可视化监控

场景 SpringBoot中集成Actuator实现监控系统运行状态&#xff1a; SpringBoot中集成Actuator实现监控系统运行状态_springboot actuator 获取系统运行时长_霸道流氓气质的博客-CSDN博客 基于以上Actuator实现系统监控&#xff0c;还可采用如下方案。 Prometheus Prometheu…

「2024」预备研究生mem-带绝对值的方程高次方程替代降次法

一、带绝对值的方程 二、高次方程替代降次法

用VMware给运行在VMware上的CentOS7生成一个以SSH方式连接VMware上的CentOS7的运行在Windows上的命令行窗口

2023年7月27日&#xff0c;周四早上 目录 一个发现生成方法如果上面的方法连接失败&#xff0c;就采取这个方法 一个发现 今天早上无意间发现VMware可以生成一个以SSH方式连接着CentOS7的Windows命令行窗口&#xff0c; 这样做可以带来一定的便利性 &#xff1a; 方便复制、…

Django模板语法和请求

1、在django关于模板文件加载顺序 创建的django项目下会有一个seeetings.py的文件 如果在seeetings.py 中加了 os.path.join(BASE_DIR,‘templates’)&#xff0c;如果是pycharm创建的django项目会加上&#xff0c;就会默认先去根目录找templates目录下的html文件&#xff0c…

时间复杂度函数图像

复杂度一览 f(n)阶函数y1O(1)常数函数ylogxO(logn)对数函数yxO(n)线性函数yxlogxO(nlogn)线性对数函数yx^2O(n^2)二次函数yx^3O(n^3)三次函数y2^xO(2^n)指数函数 对比图一览 对比结果在线预览 参考 时间复杂度比较及时间复杂度对应函数&#xff0c;函数图像

【机器学习】 奇异值分解 (SVD) 和主成分分析 (PCA)

一、说明 在机器学习 &#xff08;ML&#xff09; 中&#xff0c;一些最重要的线性代数概念是奇异值分解 &#xff08;SVD&#xff09; 和主成分分析 &#xff08;PCA&#xff09;。收集到所有原始数据后&#xff0c;我们如何发现结构&#xff1f;例如&#xff0c;通过过去 6 天…

VirtualEnv 20.24.0 发布

导读VirtualEnv 20.24.0 现已发布&#xff0c;VirtualEnv 用于在一台机器上创建多个独立的 Python 运行环境&#xff0c;可隔离项目之间的第三方包依赖&#xff0c;为部署应用提供方便&#xff0c;把开发环境的虚拟环境打包到生产环境即可&#xff0c;不需要在服务器上再折腾一…

郑州Sectigo DV通配符SSL证书

我们在浏览器访问网页时或许不会注意到网站是http还是https链接&#xff0c;但是一定能注意到浏览器给我们展示的“不安全”警告&#xff0c;警告访问者网站未加密&#xff0c;访问网站会有泄露隐私的危险。SSL证书能将网站链接由http转为https&#xff0c;对网站传输数据加密&…

【redis】通过配置文件简述redis的rdb和aof

redis的持久化方式有2种&#xff0c;rdb&#xff0c;即通过快照的方式将全量数据以二进制记录在磁盘中&#xff0c;aof&#xff0c;仅追加文件&#xff0c;将增量的写命令追加在aof文件中。在恢复的时候&#xff0c;rdb要更快&#xff0c;但是会丢失一部分数据。aof丢失数据极少…

7.27 作业

1.闹钟 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);tid1 startTimer(1);//显示时间计时器ui->pushButton_2->setEnabled(false);//设置停止为不可用…

sketch如何在线打开?有没有什么软件可以辅助

Sketch 在线打开的方法有哪些&#xff1f;这个问题和我之前回答过的「Sketch 可以在线编辑吗&#xff1f;」是一样的答案&#xff0c;没有。很遗憾&#xff0c;Sketch 没有在线打开的方法&#xff0c;Sketch 也做不到可以在线编辑。那么&#xff0c;那些广告里出现的设计软件工…

【数据挖掘】PCA/LDA/ICA:A成分分析算法比较

一、说明 在深入研究和比较算法之前&#xff0c;让我们独立回顾一下它们。请注意&#xff0c;本文的目的不是深入解释每种算法&#xff0c;而是比较它们的目标和结果。 如果您想了解更多关于PCA和ZCA之间的区别&#xff0c;请查看我之前基于numpy的帖子&#xff1a; PCA 美白与…

LED芯片 VAS1260IB05E 带内部开关LED驱动器 汽车硬灯带灯条解决方案

VAS1260IB05E深力科LED芯片是一种连续模式电感降压转换器&#xff0c;设计用于从高于LED电压的电压源高效驱动单个或多个串联连接的LED。该设备在5V至60V之间的输入电源下工作&#xff0c;并提供高达1.2A的外部可调输出电流。包括输出开关和高侧输出电流感测电路&#xff0c;该…

Cesium态势标绘专题-进攻箭头(标绘+编辑)

标绘专题介绍:态势标绘专题介绍_总要学点什么的博客-CSDN博客 入口文件:Cesium态势标绘专题-入口_总要学点什么的博客-CSDN博客 辅助文件:Cesium态势标绘专题-辅助文件_总要学点什么的博客-CSDN博客 本专题没有废话,只有代码,代码中涉及到的引入文件方法,从上面三个链…

云计算迎来中场战役,MaaS或将成为弯道超车“新赛点”

科技云报道原创。 没有人能预见未来&#xff0c;但我们可以因循常识&#xff0c;去捕捉技术创新演进的节奏韵脚。 2023年最火的风口莫过于大模型。 2022年底&#xff0c;由美国初创企业OpenAI开发的聊天应用ChatGPT引爆市场&#xff0c;生成式AI成为科技市场热点&#xff0c…

【NLP】使用 Keras 保存和加载深度学习模型

一、说明 训练深度学习模型是一个耗时的过程。您可以在训练期间和训练后保存模型进度。因此&#xff0c;您可以从上次中断的地方继续训练模型&#xff0c;并克服漫长的训练挑战。 在这篇博文中&#xff0c;我们将介绍如何保存模型并使用 Keras 逐步加载它。我们还将探索模型检查…

MCP4725介绍和STM32模拟IC2驱动

一.MCP4725 简单总结为下面几个特点。 1路DAC输出 12位分辨率 I2C 接口&#xff08;标准&#xff0c;快速&#xff0c;高速支持&#xff09; 供电电压2.7-5.5 内部EEPROM存储设置 I2C地址可配置&#xff08;A0&#xff09;&#xff08;A1、A2内置&#xff0c;默认为‘00’&…

NAT详解(网络地址转换)

一句话说清楚它是干什么的&#xff1a; 网络地址转换&#xff1a;是指通过专用网络地址转换为公用地址&#xff0c;从而对外隐藏内部管理的IP地址&#xff0c;它使得整个专用网只需要一个全球IP就可以访问互联网&#xff0c;由于专用网IP地址是可以重用的&#xff0c;所以NAT大…

undefined reference to `__android_log_print‘

报错描述 在 Android NDK 相关的工程构建中&#xff0c;出现报错&#xff1a; undefined reference to __android_log_print’ 翻译成 QM 能理解的话&#xff1a; 在链接阶段&#xff0c; 遇到一个需要被链接的符号 __android_log_print, 但是没有在给出的依赖库里面找到 __an…

HCIP——OSPF优化、拓展配置及选路规则

OSPF优化以及拓展配置 一、OSPF的优化1、汇总域间路由汇总域外路由汇总 2、特殊区域末梢区域完全末梢区域 NSSA非完全末梢区域Totally NSSA(完全的非完全末梢区域) 二、OSPF的拓展配置1、手工认证2、加快收敛3、沉默接口缺省路由 4、路由过滤5、路由控制5.1 修改优先级5.2 修改…