Servlet实践操作

Servlet运行原理

  1. Tomcat 的代码内置了 main 方法,当我们启动 Tomcat 的时候,就是从 Tomcat 的 main 方法开始执行的

  2. 被 @WebServlet 注解修饰的类会在 Tomcat 启动的时候就被获取并集中管理

  3. Tomcat 通过反射这样的语法机制来创建被 @WebServlet 注解修饰的类的实例

  4. 这些实例被创建完之后,就会调用其中的 init 方法进行初始化

  5. 这些实例被销毁之前,就会调用其中的 destory 方法进行收尾工作

  6. Tomcat 内部也是通过 Socket API 进行网络通信

  7. Tomcat 为了能够同时处理多个 HTTP 请求,采取了多线程的方式实现,因此 Servlet 是运行在多线程环境下的

 Post请求测试

浏览器直接发送的是get请求,这里使用Postman进行接口测试

@WebServlet("/testDoPost")
public class TestDoPostServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("testPost success!");
    }
}

 Response重定向到其他页面

public class RedirectServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("https://blog.csdn.net/weixin_44610169");
    }
}

post请求体body中携带信息获取

@WebServlet("/postParameter")
public class PostParameterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        resp.getWriter().write("username = " + username + " password = " + password);
    }
}

body内容格式为JSON数据获取

JSON格式的数据需要解析,Java内置库没有对JSON的解析,所以这里导入第三方数据库jackson,使用jackson解析读取请求中body内的数据.

        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.17.1</version>
        </dependency>

 

//定义一个JavaBean类
class UserInfo{
    public String username;
    public String password;
}
//读取请求中所有body
    public String readBody(HttpServletRequest req) throws IOException {
        //获取请求体长度
        int contentLength = req.getContentLength();
        //获取请求体内容
        byte[] bytes = new byte[contentLength];
        //读取请求体内容
        ServletInputStream inputStream = req.getInputStream();
        //将请求体内容读取到bytes中
        inputStream.read(bytes);
        //将bytes转换为字符串返回
        return new String(bytes, StandardCharsets.UTF_8);
    }
@WebServlet("/jsonParameter")
public class JsonParameterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        //读取请求体内容
        String body = readBody(req);
        //将请求体内容转换为JavaBean对象
        UserInfo userInfo = new ObjectMapper().readValue(body, UserInfo.class);
        //输出解析结果
        resp.getWriter().write("username: " + userInfo.username);
        resp.getWriter().write("password: " + userInfo.password);
    }
}

 Cookie

  • Cookie 是什么?

Cookie 是浏览器提供的在客户端存储数据的一种机制(由于浏览器禁止了网页中的代码直接访问本地磁盘的文件,因此想要在网页中实现持久化存储,就可以通过 Cookie 这样的机制)

  • Cookie 里面存什么?

Cookie 存储的数据都是程序员自定义的,存储的数据是一个字符串,是键值对结构的,键值对之间使用 ; 分割,键和值之间使用 = 分割

  • Cookie 从哪里来?

服务器返回响应的时候,可以把要在客户端保存的数据以 Set-Cookie 这个 header 的方式返回给浏览器

  • Cookie 到哪里去?

客户端下次访问服务器的时候,就会把之前保存好的 Cookie 再发送给服务器

  • Cookie 的典型应用场景:

可以使用 Cookie 来保存用户的登录信息。比如我们登录过某个网站后,下次登录时就不需要重新输入用户和密码了

  • Cookie 的缺陷:

每次请求都要把该域名下所有的 Cookie 通过 HTTP 请求传给服务器,因此 Cookie 的存储容量是有限的。

Session

在计算机中,尤其是在网络应用中,Session 称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在 Session 对象中。注意会话状态仅在支持 Cookie 的浏览器中保留。

session的本质

  • 会话的本质就是一个哈希表,其中存储了一些键值对结构,key 叫做 sessionId,是一个不随机的、不重复的、唯一的字符串,value 就是要保存的身份信息,通过 HttpSession 对象来保存。key 和 value 都是 Servlet 自动创建的。

  • 每个用户登录都会生成一个会话,服务器会以哈希表的方式将这些会话管理起来

  • 一个会话的详细数据通过一个 HttpSession 对象来存储,并且 HttpSession 对象中存储的数据也是键值对结构,key 和 value 都是程序员自定义的

  • 当用户成功登录之后,服务器在 Session 中会生成一个新的记录,并把 sessionId 返回给客户端(例如 HTTP 响应中可以通过 Set-Cookie 字段返回,其中 Cookie 的 key 为 “JSESSION”,value 为服务器生成的 sessionId 的具体的值)

  • 然后客户端只需要保存这个 sessionId ,当后续再给服务器发送请求时,请求中就会带上 sessionId(例如 HTTP 请求中会带上 Cookie 字段用于传递 Session)

  • 服务器收到请求后,就会根据请求中的 sessionId 在 Session 中查询对应用户的身份信息,在进行后续操作

 Servlet实现登录测试

前端页面login.html使用form表单发送数据,servlet接收后进行操作

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <form action="/servlet_test/login1" method="post">
        <input type="text" placeholder="用户名" name="username"/>
        <input type="password" placeholder="密码" name="password"/>
        <input type="submit" value="登录">
    </form>

</body>
</html>
@WebServlet("/login1")
public class loginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        if (username == null || username.isEmpty() || password == null || password.isEmpty()){
            resp.getWriter().write("<h3>用户名或密码不能为空</h3>");
            return;
        }
        if (!username.equals("root") && !password.equals("root")){
            resp.getWriter().write("<h3>用户名或密码错误</h3>");
            return;
        }
        if (username.equals("root") && password.equals("root")){
            // 登录成功后创建session
            HttpSession session = req.getSession(true);
            session.setAttribute("visitCount", 0);
            // 登录成功后跳转页面
            resp.sendRedirect("index");
        }

    }
}
@WebServlet("/index")
public class LoginSuccessServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        HttpSession session = req.getSession(false);
        if(session == null){
            // 如果为空重定向到登录页面
            resp.sendRedirect(req.getContextPath() + "/login.html");
            return;
        }
        // 登录成功后获取session中的数据
        Integer visitCount = (Integer) session.getAttribute("visitCount");
        visitCount += 1;
        session.setAttribute("visitCount", visitCount);
        resp.getWriter().write("登录成功,欢迎回来!您已经登录" + visitCount + "次!");
    }
}

文件上传

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件</title>
</head>
<body>
<!--通过 form 表单构造上传文件,要加上一个 enctype 字段,
    它表示 body 中的数据格式,它的默认值为:x-www-form-urlencoded,
    这里要修改成:multipart/form-data,它是上传文件或者图片的数据格式-->
  <form action="/servlet_test/uploadFile" method="post" enctype="multipart/form-data">>
    <input type="file" name="file1">
    <input type="submit" value="上传">
  </form>
</body>
</html>
@MultipartConfig
@WebServlet("/uploadFile")
public class uploadFileServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        Part file1 = req.getPart("file1");
        String fileName = file1.getSubmittedFileName();
        String contentType = file1.getContentType();
        long size = file1.getSize();
        System.out.println("文件名:" + fileName + ",文件类型:" + contentType + ",文件大小:" + size + "字节");
        file1.write("C:\\Users\\86152\\Desktop\\" + fileName);

        resp.getWriter().write("文件上传成功");
    }
}
传文件操作还需要给 Servlet 加上一个 @MultipartConfig 注解,否则服务器代码无法使用 getPart() 方法

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

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

相关文章

【机器学习300问】114、什么是度量学习?三元组损失又是什么?

这些天都在加强自己的CV基本功&#xff0c;之前做过的人脸识别项目里有很多思考&#xff0c;在学习了这些基础知识后&#xff0c;我再次回顾了之前的人脸识别项目。我发现&#xff0c;很多之前困惑不解的问题现在都有了清晰的答案。 一、什么是度量学习&#xff1f; 度量学习也…

Day 27:2596. 检查骑士巡视方案

Leetcode 2596. 检查骑士巡视方案 骑士在一张 n x n 的棋盘上巡视。在 **有效 **的巡视方案中&#xff0c;骑士会从棋盘的 左上角 出发&#xff0c;并且访问棋盘上的每个格子 恰好一次 。 给你一个 n x n 的整数矩阵 grid &#xff0c;由范围 [0, n * n - 1] 内的不同整数组成&…

小米SU7遇冷,下一代全新车型被官方意外曝光

不知道大伙儿有没有发现&#xff0c;最近小米 SU7 热度好像突然之间就淡了不少&#xff1f; 作为小米首款车型&#xff0c;SU7 自上市以来一直承载着新能源轿车领域流量标杆这样一个存在。 发售 24 小时订单量破 8 万&#xff0c;2 个月后累计交付破 2 万台。 看得出来限制它…

Blender渲染模糊?掌握这些技巧,提升你的渲染质量!

随着Blender生态链越来越完善,越来越多的人开始学习Blender。然而&#xff0c;在使用Blender的过程中&#xff0c;许多小伙伴遇到了各种问题。比如&#xff1a; 为什么blender渲染物品很糊?能让它们变得清晰吗&#xff1f; Blender渲染不出来&#xff0c;有时渲染出来了就闪…

基本循环神经网络(RNN)

RNN背景&#xff1a;RNN与FNN 在前馈神经网络中&#xff0c;信息的传递是单向的&#xff0c;这种限制虽然使得网络变得更容易学习&#xff0c;但在一定程度上也减弱了神经网络模型的能力。 在生物神经网络中&#xff0c;神经元之间的连接关系要复杂的多。前馈神经网络可以看着…

使用fetch加载阿里云的在线json 出现403错误

在做地图项目的时候&#xff0c;引用了阿里云的在线JSON地图数据。 问题描述&#xff1a; 但是本地开发使用fetch请求json地址的时候接口却出现了403错误&#xff0c;把地址直接复制到浏览器上却能正常打开。 https://geo.datav.aliyun.com/areas_v3/bound/330000_full.json …

[学习笔记]-MyBatis-Plus简介

简介 Mybatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window)的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 简言之就是对单表的增删改查有了很好的封装。基本不用再单独写sql语句了。目前此类…

【华为HCIA数通网络工程师真题-数据通信与网络基础】

文章目录 选择题判断题 选择题 1、在 VRP 平台上&#xff0c;可以通过下面哪种方式访向上条历史命令&#xff1f; 上光标 &#xff08;ctrlU 为自定义快捷键&#xff0c;ctrlP 为显示历史缓存区的前一条命令&#xff0c;左光标为移动光标&#xff09; 2、主机 A &#xff08;1…

UI设计速成课:理解模态窗口与非模态窗口的区别

我们日常所说的弹性框架是非常笼统的概念。我们习惯性地称之为对话框架、浮动层和提示条。弹性框架可以分为两种:模态弹性框架和非模态弹性框架。产品需要弹性框架来传递信息&#xff0c;用户需要弹性框架来接受反馈&#xff0c;但是没有经过推敲的弹出窗口设计很容易让用户感到…

mamba模型原理解读

本文主要讲解我对于2023年提出的mamba模型的理解和解读&#xff0c;mamba模型的提出为transformer模型存在的计算效率低下&#xff0c;需要大量时间运行程序提出了解决方案。提高了模型的运行效率和计算效率。我主要是根据下面这篇文章入手&#xff1a; 1.mamba模型是通过堆叠多…

STM32人工智能检测-筛选机器人

前言 本文描述了一种使用STM32进行机器人筛选的办法。筛选对象是我的粉s&#xff0c;删选办法是瞪眼法。 问题现象 每次当我的STM32 向外界发出一篇新的的报文&#xff0c;总能在1H之内得到focus&#xff0c;格式如下 [title][body][tail]于是我对各个focus 我报文的对象进…

香港身份的好处有哪些?这3个福利卷得内地人都在申请香港身份!

截止近期数据&#xff0c;香港身份申请人数达到29万&#xff0c;可见香港魅力依旧&#xff01; 我也是其中之一&#xff0c;去年才把香港优才临时身份卷下来的糖爸~ 我身边不少符合条件的朋友都想润去香港了&#xff0c;接近国际&#xff0c;又离家门近&#xff0c;谁不想去啊…

嵌入式技术学习——Linux环境编程(高级编程)——shell编程

一、shell编程的基础介绍 1.为什么要进行shell编程? 在Linux系统中&#xff0c;虽然有各种各样的图形化接口工具&#xff0c;但是shell仍然是一个非常灵活的 工具。 Shell不仅仅是命令的收集&#xff0c;而且是一门非常棒的编程语言。 您可以通过使用shell使大量的任务自动化…

QTday5 2024-06-19

作业要求&#xff1a; 1.思维导图 2.整理代码&#xff1a;TCP服务器 作业1&#xff1a;思维导图 作业2&#xff1a;整理代码 运行代码&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> #include <QList>…

Python 迭代器与生成器

迭代器 迭代器&#xff08;Iterator&#xff09;是一个可以记住遍历的位置的对象&#xff0c;该对象包含值的可计数数字&#xff0c;在Python当中&#xff1a;迭代器是实现迭代器协议的对象&#xff0c;它包含方法__iter__() 和 __next__() __iter__()方法 作用&#xff1a;…

Java语法糖写法

一、函数式接口 1、Function函数式接口&#xff1a;有一个输入参数&#xff0c;有一个输出 2、断定型接口&#xff1a;有一个输入参数&#xff0c;返回值只能是布尔值&#xff01; 3、Consumer 消费型接口&#xff1a;只有输入&#xff0c;没有返回值 4、Supplier供给型接口&a…

目标检测讲解

环境准备 pip install scikit-image -i https://pypi.tuna.tsinghua.edu.cn/simple图片读取&画框 from skimage import io import matplotlib.pyplot as plt import matplotlib.patches as mpss io.imread(dogs.jpg)_, ax plt.subplots(ncols1, nrows1, figsize(6, 6))…

关于Java

关于Java Java语言关于并发JVM调优工具写在最后 Java语言 Java语言作为当下主流开发语言&#xff0c;其面向对象的开发模式以及一次编译多次运行&#xff0c;跨平台运行以及自动的垃圾回收机制可以说是给开发者节省了很大的时间用于逻辑功能的开发&#xff0c;那么在开发过程中…

通信系统的最佳线性均衡器(1)---维纳滤波线性均衡

本篇文章是博主在通信等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对通信等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在通信领域笔记&#xff1a;…

windows cmd bat 批处理脚本找到监听端口并并杀掉进程 nestat -ano

echo off rem 终止正在监听在端口8888上的进程 rem tokens5 表示第五个token for /f tokens5 %%p in (netstat -ano ^| findstr 8888) do ( set pid%%p ) echo xxxx %pid% rem xxxx TCP [::]:8888 [::]:0 LISTENING 2720 taskkill /pid %pid% /f if %errorlevel% equ 0 ( echo …