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 {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("testPost success!");}
}

 Response重定向到其他页面

public class RedirectServlet extends HttpServlet {@Overrideprotected 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 {@Overrideprotected 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;
}
//读取请求中所有bodypublic 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 {@Overrideprotected 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 {@Overrideprotected 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")){// 登录成功后创建sessionHttpSession session = req.getSession(true);session.setAttribute("visitCount", 0);// 登录成功后跳转页面resp.sendRedirect("index");}}
}
@WebServlet("/index")
public class LoginSuccessServlet extends HttpServlet {@Overrideprotected 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 {@Overrideprotected 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() 方法

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

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

相关文章

PCB设计隐藏的陷进

1、BGA芯片的开窗和过油设计。 加工工艺中&#xff0c;范式过孔都需要盖油设计&#xff0c;实心焊盘需要开窗设计&#xff0c;坚决不能盖油。 2、通孔设计的互联连通性 比如H3芯片的wifi设计&#xff0c;实际上是没有联通的&#xff0c;虽然四层板的中间层有焊盘&#xff0c;但…

操作系统-进程调度

进程调度 文章目录 进程调度前言进程和作业区别CPU调度程序抢占调度调度程序上下文切换 调度准则调度算法 前言 对于单处理器系统&#xff0c;同一时间只能有一个进程可以运行&#xff0c;其他的进程都应该等待&#xff0c;知道CPU空闲可以调度为止。 多道程序的目标是&#…

lua的GC

关于lua的gc云风大佬在 Lua GC 的源码剖析 系列文章中讲得很清楚&#xff0c;这里做一下简单的记录。 分步gc lua使用的是一种三色标记清除算法&#xff08;tri-color incremental mark & sweep&#xff09;&#xff0c;大体步骤如下&#xff1a; 初始阶段&#xff0c;所…

【FreeRTOS】估算栈的大小

参考《FreeRTOS入门与工程实践(基于DshanMCU-103).pdf》 目录 估算栈的大小回顾简介计算说明估计函数用到的栈有多大合计 估算栈的大小 回顾 上一篇文章链接&#xff1a;http://t.csdnimg.cn/Cc8b4 传送门: 上一篇文章 上一篇文章创建的三个任务 /* 创建任务&#xff1a;声 *…

22.HandlerPipeline

ChannelHandler用来处理Channel上的各种事件,分为入站和出站两种。 所有的ChannelHandler被连成一串,就是Pipeline。 入站处理器通常是ChannelInboundHandlerAdapter的子类,主要用来读取客户端数据,写回结果。 出站处理器通常是ChannelOutboundHandlerAdapter的子类,主…

Uni-app x

uni-app x&#xff0c;是下一代 uni-app&#xff0c;是一个跨平台应用开发引擎。 uni-app x 是一个庞大的工程&#xff0c;它包括uts语言、uvue渲染引擎、uni的组件和API、以及扩展机制。 uts是一门类ts的、跨平台的、新语言。uts在iOS端编译为swift、在Android端编译为kotli…

LabVIEW开发为何仿制(致敬)经典成熟软件

​仿制&#xff08;致敬&#xff09;成熟软件进行LabVIEW开发更方便&#xff0c;因其提供了稳定的架构和结构、优化的用户体验和界面设计、技术规范和标准、稳定性和可靠性。结合用户手册和现有操作进行仿制&#xff0c;就像小米致敬保时捷一样&#xff0c;可以提高开发效率、降…

vivado SITE

描述 SITE是一个设备对象&#xff0c;表示许多不同类型的逻辑资源之一 可在目标Xilinx FPGA上获得。 SITE包括SLICE/CLB&#xff0c;它们是基本逻辑元件&#xff08;BEL&#xff09;的集合&#xff0c;如 查找表&#xff08;LUT&#xff09;、触发器、多路复用器&#xff0c;携…

QT/基于TCP的服务端实现

代码 widget.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget),p(new QTcpServer(this))//给服务器指针申请空间 {ui->setupUi(this); }Widget::~Widget() {delete ui; }void W…

实测:三款垃圾CPU推理Llama3 8B

经常有一些朋友问我本地运行大模型的电脑需要什么样的配置。其实一些常用大模型的运行需要的硬件并不像我们想象的那样高不可攀。不要被那些复杂的技术术语所吓倒&#xff0c;关键在于亲自动手尝试。 “不试&#xff0c;怎么知道呢&#xff1f;” 这句话道出了真理。今天&#…

【Linux】基础IO_1

文章目录 六、基础IO1. C语言的文件接口2. 系统文件I/O 未完待续 六、基础IO 1. C语言的文件接口 我们知道 文件 文件内容 文件属性 。即使是一个空文件&#xff0c;仍然会在磁盘中占据空间。那打开文件是什么意思呢&#xff1f;其实文件打开的意思就是&#xff1a;将文件从…

package cmp is not in GOROOT (/usr/local/go/src/cmp)

具体错误 env CGO_ENABLED0 go build -trimpath -ldflags "-s -w" -tags frpc -o bin/frpc ./cmd/frpcclient/admin_api.go:18:2: package cmp is not in GOROOT (/usr/local/go/src/cmp)pkg/util/util/util.go:23:2: package math/rand/v2 is not in GOROOT (/usr/…

力扣每日一题 6/19 排序+动态规划

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 2713.矩阵中严格递增的单元格数【困难】 题目&#xff1a; 给你一个下标从…

【学习DayNa】信息系统开发整理

✍&#x1f3fb;记录学习过程中的输出&#xff0c;坚持每天学习一点点~ ❤️希望能给大家提供帮助~欢迎点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;指点&#x1f64f; 结构化方法 结构是指系统内各个组成要素之间的相互联系、相互作用的框架。结构化开发方法就是…

Java应用打包成Docker镜像

# 使用官方的OpenJDK17镜像作为基础镜像 FROM openjdk:17 # 设置工作目录 WORKDIR /app # 复制本地的Java应用程序文件到镜像中的指定目录 COPY target/bear-module-system-0.0.1-SNAPSHOT.jar /app/bear-module-system-0.0.1-SNAPSHOT.jar # 暴露API端口 EXPOSE 8888 …

shell中的流程控制

条件判断在流程控制中的重要性 有了条件判断才能进行if判断即分支流程&#xff0c;才能进行case的多分支流程&#xff0c;才能进行for循环和while循环。 单分支流程判断 如上图所示&#xff0c;在shell编程中常使用英文状态下的分号来在Linux控制台一次性执行多条命令&#x…

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

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

运算放大器(运放)缓冲器(跟随器)电路

运算放大器(Operational Amplifier) 运算放大器(Operational Amplifier)是一种差分放大器&#xff0c;具有高输入电阻、低输出电阻、高开放增益&#xff08;开环增益&#xff09;&#xff0c;并具有可放大输入引脚与-输入引脚间的电压差的功能。 设计目标 输入输入输出输出频…

“打卡展示”后遗症如何解决

最近看了一本书&#xff0c;里边提到的学习打卡&#xff0c;健身打卡&#xff0c;早期打卡&#xff0c;不管是在家里&#xff0c;在学校&#xff0c;上班族&#xff0c;都在抓紧一切时间提升自己&#xff0c;为了实现目标出现了形形色色的打卡&#xff0c;只要你能想得到的领域…

HTML李峋同款跳动的爱心代码(双爱心版)

目录 写在前面 跳动的爱心 完整代码 代码分析 系列推荐 最后想说 写在前面 在浩瀚的网络世界中&#xff0c;总有一些小惊喜能触动我们的心弦。今天&#xff0c;就让我们用HTML语言&#xff0c;探索既神秘又浪漫的李峋同款跳动的爱心代码吧。 首先&#xff0c;让我们一起…