网站开发--详解Servlet

news2025/2/27 21:59:12

💕"Echo"💕
作者:Mylvzi
文章主要内容:网站开发–详解Servlet
在这里插入图片描述

一.基本介绍

tomcat是Java中开发服务器的重要的一个工具,任何开发的服务器都要部署在tomcat之上,可以说tomcat是所有服务器的底座,为了更好的操作http,tomcat对原生的api进行了封装,封装为Servlet*,通过servlet就可以非常方便的完成和http协议的祥光操作

关于Servlet的学习,主要学习以下三个类即可:

  1. HttpServlet
  2. HttpRequestServlet
  3. HttpResponseServlet

掌握好这三个类,就能很好的使用Servlet

二.HttpServlet

HttpServlet是Servlet中最核心的一个类,我们创建的用于进行交互的类都必须要继承于HttpServlet

在这里插入图片描述

HttpServlet中常用方法
在这里插入图片描述

  1. init()方法会在一个Servlet对象被创建好之后,自动的调用这个方法,完成初始化操作
  2. destroy()方法会在Servlet对象被销毁之前进行调用,完成一些释放资源的工作
  3. service()方法实际上并不会直接使用到,而是被doGet(),doPost()给替代

init(),destroy(),service()这三个方法在实际的开发中很少用到,都是tomcat自动的在合适的时机帮助我们调用的,这三个方法经常会出现到一个经典的面试题中:

经典面试题:Servlet的生命周期

Servlet的生命周期是指Servlet实例被创建出来到被销毁的过程,具体来说可以分为以下几点:

  1. Servlet实例的创建:当客户端发送请求,服务器就要创建出一个Servlet实例来处理请求,通过构造方法创建出一个Servlet实例
  2. 初始化:在实例被创建好之后,会自动调用init()方法,来完成一些初始化操作,比如:读取配置文件,数据库的连接,一些资源的初始化
  3. 处理请求:当有客户端的http请求发送到服务器时,Servlet会先调用service()方法,判断请求的具体类型(根据请求的方法),service()方法就像是火车的中转站一样,看你的目的是什么,再给你对应的路线.这里也是一样,如果请求是GET方法,就会交给代码中的doGet()方法处理,如果是POST请求,就会交给doPost()方法
  4. 实例的销毁:当我们不再使用Servlet实例时(客户端不再有请求发送过来/人为关闭),先调用destroy()方法,做一些清理工作,比如数据库的断开,资源释放等

这个过程类似于生命周期中的起始、成长、运行和结束阶段,每个阶段都有其特定的任务和目的。

总的来说,我们所写的代码都要继承于HttpServlet这个类,重写里面的方法,并将重写的方法插入到tomcat已有的框架之中,我们只需关注数据处理部分,其余操作都是tomcat自动帮助我们完成

二.HttpServletRequest

1.介绍

HttpServletRequest表示一个Http请求类,用于接受从客户端传输过来的http请求

HttpServletRequest中的很多属性和请求头的相关属性相同,理解好请求头中的相关属性有助于学习HttpServletRequest类

一个Http请求由四部分组成:

  1. 首行 = 方法 + URL + 版本号
  2. 请求头:由键值对组成
  3. 空行
  4. body

2.HttpServletRequest常用方法介绍

在这里插入图片描述

在这里插入图片描述

1.获取首行信息和header中的数据**

@WebServlet("/request1")
public class RequestParameter extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 尝试获取请求报文中的详细信息
        StringBuffer stringBuffer = new StringBuffer();// 这个是线程安全的

        // 1.获取首行信息
        stringBuffer.append(req.getMethod());
        stringBuffer.append("<br>");// <br>是html中的换行标签
        stringBuffer.append(req.getRequestURI());
        stringBuffer.append("<br>");
        stringBuffer.append(req.getProtocol());
        stringBuffer.append("<br>");
        
        // 2.获取请求头信息
        Enumeration<String> enumeration = req.getHeaderNames();
        while (enumeration.hasMoreElements()){// 利用迭代器访问每一个头部key
            String key = enumeration.nextElement();
            String val = req.getHeader(key);// 获取key的值
            stringBuffer.append(key + ":" + val + "<br>");
        }

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

获取结果:
在这里插入图片描述

总结:
对于请求报文来说,获取首行中的信息(版本号/方法/URL),可以直接通过指定的get方法来获取,获取请求头(header)中内容,可以利用迭代器,将请求头中的所有键值对都存储到一个集合之中,再利用getHeader方法,指定参数,来获取对应的value值

2.获取请求报文中的query string**

query string,译为查询字符串,往往和用户的关键信息相关(登录密码),在日常的开发中,我们也经常利用到query string来完成一些业务上的逻辑,所以获取请求报文中的query string是一个很频繁且重要的操作

query string在请求报文中的位置是不固定的,具体位置取决于请求报文中的方法(method),如果方法是Get,query string就位于URL之中,如果方法是Post,query string就位于body之中

注意:实际上URL中是包含query string的,但是在servlet的getURL类似的方法中返回的是一个不携带query string的URL(可能是因为查询字符串这个操作过于频繁,就单独拿出来进行包装了)

1.方法为Get

说明:前后端交互的一个关键点在于前端和后端要对传输内容的格式都了然于胸,后端要知道前端是如何组织数据进行传输的

比如,规定好客户端发送的请求报文中的query string的格式是类似于:

username=zhangsan&password=123456

那么服务器这边就可以规定好的格式进行解析

代码演示:

@WebServlet("/request2")
public class GetRequestParameter extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取用户传输过来的query string
        // 假设用户传输过来的query string的格式是形如 username='lisi'&password='123'这样的形式
        // servlet会自动将query string中的所有内容存储到一个Map结构之中(键值对都存储到其中
        // 后端程序员只需通过getParameter()方法来获取具体的值即可
        // 注意你构造的query string内部不需要有引号!!!
        // 可以根据这个特性来完成很多操作  比如判断用户名是否正确
        // 在传输中文的时候最好传输urlencode之后的内容

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("username=" + username);
        System.out.println("password=" + password);
        
    }
}

在这里插入图片描述

当在浏览器中输入:“http://127.0.0.1:8080/testsevlet/request2?username=zh&password=123”

在终端上显示:
在这里插入图片描述

如果不添加query string,显示的结果就是null

在这里插入图片描述

总结:

对于Get方法的请求,query string位于首行中,直接使用getParameter方法,并制定参数,就能获取到对应的值

2.方法为Post

此时query string位于body之中,而body的传输是有不同的格式的,对于不同格式的body,要采用不同的方法来进行解析,获取query string,常用的body格式有两种:

  1. form表单
  2. json
1.form表单格式

body通过form表单来进行数据的组织,内部是键值对,Content-Type:application/x-www-form-urlencoded

获取body中的内容和上面获取query string的方法一致

通过postman发送一个post请求
在这里插入图片描述
服务器的代码不变,打印结果为:
在这里插入图片描述

总结:如果body的格式是form表单,虽然此时query string位于body之中,但是也可以直接使用**getParameter()**方法,并指定参数来获取要查询的内容

2.json格式

如果body是通过json格式来进行组织,原生的Servlet是不支持解析json格式的数据的,此时需要进入第三方库jackson来帮助进行json格式数据解析(jackson也是spring官方推荐的用于解析JSON格式数据的第三方库)

准备:引入jackson依赖

在maven中找到jackson,选择合适的版本进行路径的复制,并在项目中的pom.xml中引入

        <!-- 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>

在这里插入图片描述

在这里插入图片描述
引入好依赖之后就可以使用jackson中的api解析json格式的数据

具体的操作依赖于一个类和两个核心方法:
在这里插入图片描述
ObjectMapper(对象映射器),是JSON数据与Java对象转换的核心枢纽,在交互时,通过JSON字符串进行网络传输,处理逻辑,使用Java对象

站在服务器的角度,我们收到的数据是JSON字符串,需要将其转化为Java对象(read放哪发),来完成一些业务上的逻辑,完成后,还需要将处理好的Java对象转化为JSON字符串(write方法)

1.创建一个类 用于接收JSON字符串

// 创建一个类  用于接收JSON字符串
class Request {
    public String username;
    public String password;
}

2.交互

    // 创建出ObjectMapper实例
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1.将JSON字符串转化为Java对象
        Request request = objectMapper.readValue(req.getInputStream(),Request.class);

        // 2.获取query string
        String username = request.username;
        String password = request.password;

        // 3.打印
        String user = "username=" + username + "<br>password=" + password;
        System.out.println(user);

        // 4.将打印的结果传输给客户端
        // 这个方法就是和上面的read方法相反
        // 这里把Java对象转化为json字符串,传输给客户端
        String respBody = objectMapper.writeValueAsString(user);
        resp.getWriter().write(respBody);
    }

3.发送请求并打印结果

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

objectMapper.readValue()内部做了很多工作,最终的结果是把JSON字符串转化为Request的Java对象,内部具体实现细节为:

  1. 根据请求报文的输入流(就是方法的第一个参数)获取到请求报文中的body部分的所有内容
  2. 按照JSON格式进行解析,并把解析出来的所有的键值对都存储到一个Map之中
  3. 通过第二个参数(反射)来明确要转化的Java对象,拿着Java对象中的属性从Map之中寻找对应的值,并把对应的值赋给赋给创建出来的Java对象

通过以上三步就完成了JSON字符串到Java对象的转化,举一个简单的例子
在这里插入图片描述

以上就是关于HttpRequestServlet的所有内容,可以观察到,这个类中大部分方法都是get方法,主要原因是因为我们是想通过这个类获取到客户端发送的请求报文,而不是去修改请求报文,所以不需要设置set方法,而在下面要介绍的HttpResponseServlet类中,更多的方法就是set方法(服务器这边要返回一个响应报文)

三.HttpResponseServlet

常用方法:
在这里插入图片描述

setStatus() 设置状态码

@WebServlet("/status")
public class StatusServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        resp.setStatus(404);// 此时响应报文的状态码就被设置为404

        // 如果只传输上述的状态码  浏览器是空白界面  不会有任何信息
        // 我们一般看到的都是有一个"错误界面"
        // 可以通过
        resp.sendError(404,"你小子搜的是什么资源???");
        // 这里面就比较的灵活了
        // 根据一定的逻辑  来灵活的输出状态码信息
    }
}

当需要发送报错信息时,更推荐使用第二种方式,更加灵活
结果显示:
在这里插入图片描述

setHeader 在头部中设置一些属性

自动刷新

每间隔1s就自动刷新界面,利用header中的refresh字段

@WebServlet("/refresh")
public class RefreshServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("refresh","1");// 1s 后自动刷新界面
        resp.getWriter().write("" + System.currentTimeMillis());
    }
}

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

sendRedirect() 构造重定向

当状态码是3xx时,就代表要进行重定向,利用sendRedirect方法可以直接跳转

@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        // 一个重定向的报文包含两部分:状态码 和 要跳转的界面
//        resp.setStatus(302);// 核心是要有对应的状态码(以3开头),以及要跳转的界面(Location字段)
//        resp.setHeader("Location","https://sogou.com");// 此时就会自动跳转到搜狗界面

        // 上述写法比较繁琐  一般来说会使用下面这个方法来设置一个跳转的响应报文
        resp.sendRedirect("https://sogou.com");
    }
}

不仅可以通过服务器这边设置跳转的界面,还可以在前端中使用JS定时器来实现相同的效果

<!DOCTYPE html>
<html>
<head>
    <title>页面跳转示例</title>
    <script>
        // 在页面加载后,等待 3 秒后跳转到新页面
        window.onload = function() {
            setTimeout(function() {
                window.location.href = "https://www.sogou.com";
            }, 3000); // 3 秒
        };
    </script>
</head>
<body>
    <h1>页面将在 3 秒后跳转到搜狗主页</h1>
</body>
</html>

以上就是<<网站开发–详解Servlet>>的所有内容,重点掌握三个类的api的基本用法,多多使用就能融会贯通,实现更复杂的交互!

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

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

相关文章

网络安全Web Hacking 101笔记,2023年最新整理!

在计算机技术如日中天的今天&#xff0c;Web安全问题也接踵而来。但Web安全却“入门简单精通难”&#xff0c;涉及技术非常多且广&#xff0c;学习阻力很大。 为此今天分享一份94页的《Web Hacking 101》笔记&#xff0c;包含Web安全知识&#xff0c;例如HTML注入、XSS、CSRF、…

MATLAB Function转C代码实战

文章目录 前言1. 准备工作2. 使用MATLAB Coder2.1 确定输入输出的类型2.2 MATLAB Coder过程 3. 代码调整和优化4. 编译和测试5. 性能分析和优化结语 前言 在科学与工程领域&#xff0c;MATLAB&#xff08;Matrix Laboratory&#xff09;是一种广泛使用的高级技术计算软件&…

Spring Boot 接口请求日志(基于AOP和自定义注解)

一、需求 在Spring Boot应用中&#xff0c;实现接口请求日志记录功能&#xff0c;要求能够记录包括请求方法、接口路径及请求参数等核心信息&#xff0c;并提供灵活的开关配置。 二、方案概述 采用AOP&#xff08;面向切面编程&#xff09;结合自定义注解的方式实现。 具体…

1904_ARM Cortex M系列芯片特性小结

1904_ARM Cortex M系列芯片特性小结 全部学习汇总&#xff1a; g_arm_cores: ARM内核的学习笔记 (gitee.com) ARM Cortex M系列的MCU用过好几款了&#xff0c;也涉及到了不同的内核。不过&#xff0c;关于这些内核的基本的特性还是有些不了解。从ARM的官方网站上找来了一个对比…

《游戏引擎架构》 -- 学习4

资源及文件系统 文件系统 游戏引擎的文件系统API通常提供以下功能&#xff1a; 搜需路径&#xff1a;是含一串路径的字符串&#xff0c;各路径之间以特殊字符&#xff08;如冒号或分号&#xff09;分隔&#xff0c;找文件时就会从这些路径进行搜寻。例如在命令行下执行程序&a…

2023年06月CCF-GESP编程能力等级认证Scratch编程一级真题解析

一、单选题&#xff08;共10题&#xff0c;共30分&#xff09; 第1题 以下不属于计算机输出设备的有&#xff08; &#xff09;。 A&#xff1a;麦克风 B&#xff1a;音箱 C&#xff1a;打印机 D&#xff1a;显示器 答案&#xff1a;A 第2题 点击下面哪个图标可以使舞台区…

真香!NineData SQL开发全面适配 GaiaDB

2 月&#xff0c;新年伊始&#xff0c;NineData 重磅发布&#xff0c;提供了对百度云原生关系型数据库 GaiaDB 的支持。 这一次的发布不仅仅是简单的数据源支持&#xff0c;而是覆盖了整个 SQL 开发能力的重要发布&#xff0c;意味着您已经可以完整地使用 NineData SQL 开发的…

Redis高并发分布锁实战

Redis高并发分布锁实战 问题场景 场景一: 没有捕获异常 // 仅仅加锁 // 读取 stock15 Boolean ret stringRedisTemplate.opsForValue().setIfAbsent("lock_key", "1"); // jedis.setnx(k,v) // TODO 业务代码 stock-- stringRedisTemplate.delete(&quo…

AI时代 编程高手的秘密武器:世界顶级大学推荐的计算机教材

文章目录 01 《深入理解计算机系统》02 《算法导论》03 《计算机程序的构造和解释》04 《数据库系统概念》05 《计算机组成与设计&#xff1a;硬件/软件接口》06 《离散数学及其应用》07 《组合数学》08《斯坦福算法博弈论二十讲》 清华、北大、MIT、CMU、斯坦福的学霸们在新学…

MySQL篇—持久化和非持久化统计信息介绍(第一篇,总共三篇)

☘️博主介绍☘️&#xff1a; ✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、Linux&#xff0c;也在积极的扩展IT方向的其他知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&#xff0c;并且也会默默的点赞收藏加关注❣…

Spring事务模板及afterCommit存在的坑

大家好&#xff0c;我是墨哥&#xff08;隐墨星辰&#xff09;。今天的内容来源于两个线上问题&#xff0c;主要和大家聊聊为什么支付系统中基本只使用事务模板方法&#xff0c;而不使用声明式事务Transaction注解&#xff0c;以及使用afterCommit()出现连接未按预期释放导致的…

科技云报道:黑马Groq单挑英伟达,AI芯片要变天?

科技云报道原创。 近一周来&#xff0c;大模型领域重磅产品接连推出&#xff1a;OpenAI发布“文字生视频”大模型Sora&#xff1b;Meta发布视频预测大模型 V-JEPA&#xff1b;谷歌发布大模型 Gemini 1.5 Pro&#xff0c;更毫无预兆地发布了开源模型Gemma… 难怪网友们感叹&am…

不可错过的Telegram神器:十个实用Telegram机器人介绍

Telegram机器人是基于Telegram平台上的自动化程序&#xff0c;通过Telegram Bot API来与用户交互&#xff0c;执行各种任务&#xff0c;大大拓宽了Telegram这个软件的功能。不只是可以进行简单的自动化任务如提醒服务、天气预报、个人助理&#xff0c;也可以完成复杂的商业行为…

SpringBoot自带的tomcat的最大连接数和最大的并发数

先说结果&#xff1a;springboot自带的tomcat的最大并发数是200&#xff0c; 最大连接数是&#xff1a;max-connectionsaccept-count的值 再说一下和连接数相关的几个配置&#xff1a; 以下都是默认值&#xff1a; server.tomcat.threads.min-spare10 server.tomcat.threa…

基于Pytorch的猫狗图片分类【深度学习CNN】

猫狗分类来源于Kaggle上的一个入门竞赛——Dogs vs Cats。为了加深对CNN的理解&#xff0c;基于Pytorch复现了LeNet,AlexNet,ResNet等经典CNN模型&#xff0c;源代码放在GitHub上&#xff0c;地址传送点击此处。项目大纲如下&#xff1a; 文章目录 一、问题描述二、数据集处理…

【Vue3】学习watch监视:深入了解Vue3响应式系统的核心功能(上)

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

Linux基础命令—进程管理

基础知识 linux进程管理 什么是进程 开发写代码->代码运行起来->进程 运行起来的程序叫做进程程序与进程区别 1.程序是一个静态的概念,主要是指令集和数据的结合,可以长期存放在操作系统中 2.进程是一个动态的概念,主要是程序的运行状态,进程存在生命周期,生命周期结…

nginx.conf配置文件详解、案例,Nginx常用命令与模块

目录 一、Nginx常用命令 二、Nginx涉及的文件 2.1、Nginx 的默认文件夹 2.2、Nginx的主配置文件nginx.conf nginx.conf 配置的模块 2.2.1、全局块&#xff1a;全局配置&#xff0c;对全局生效 2.2.2、events块&#xff1a;配置影响 Nginx 服务器与用户的网络连接 2.2.3…

docker 容器访问 GPU 资源使用指南

概述 nvidia-docker 和 nvidia-container-runtime 是用于在 NVIDIA GPU 上运行 Docker 容器的两个相关工具。它们的作用是提供 Docker 容器与 GPU 加速硬件的集成支持&#xff0c;使容器中的应用程序能够充分利用 GPU 资源。 nvidia-docker 为了提高 Nvidia GPU 在 docker 中的…

Python爬虫-爬取豆瓣高分电影封面

本文是本人最近学习Python爬虫所做的小练习。如有侵权&#xff0c;请联系删除。 页面获取url 代码 import requests import os import re# 创建文件夹 path os.getcwd() /images if not os.path.exists(path):os.mkdir(path)# 获取全部数据 def get_data():# 地址url "…