整合多方大佬博客以及视频 一文读懂 servlet

参考文章以及视频

文章:

都2023年了,Servlet还有必要学习吗?一文带你快速了解Servlet_servlet用得多吗-CSDN博客

【计算机网络】HTTP 协议详解_3.简述浏览器请求一个网址的过程中用到的网络协议,以及协议的用途(写关键点即可)-CSDN博客

【从理论到应用】HTTP请求响应详解 (请求数据格式,请求方式,Web开发中的体现)_apifox 如何转换htt请求-CSDN博客

HTTP响应是什么?_响应内容-CSDN博客

Servlet的生命周期-CSDN博客

HttpServletRequest介绍和使用-CSDN博客

【Servlet】请求转发与重定向_servlet请求转发可以访问其它应用的资源吗-CSDN博客

https://blog.csdn.net/qq_41264674/article/details/80472666

cookie详解-CSDN博客

什么是Session的销毁方式?_销毁session-CSDN博客

ServletContext详解-CSDN博客

【JavaWeb】会话管理 cookie session 三大域对象总结_cookie登录时效性-CSDN博客

视频:

【可能是B站讲的最好的Servlet教程,一天打通Servlet全套教程丨2022最新版,轻松掌握servlet基础+案例实操】https://www.bilibili.com/video/BV1kt4y157xd?p=15&vd_source=bb412cc25ca27e171f8e17085daad038

1、主旨大纲

在这里插入图片描述

2、Http协议

介绍

在这里插入图片描述

浏览器的书写格式

在这里插入图片描述

Http之url

在这里插入图片描述

Http请求

介绍

HTTP请求格式是由三部分组成:

  • 请求行(Request line):包括请求方法、URL和协议版本。
  1. 请求方法(Request method):表示要执行的操作,常见的方法有GET、POST、PUT、DELETE等。
  2. URL(Uniform Resource Locator):表示要访问的资源路径。
  3. 协议版本(Protocol version):表示使用的HTTP协议版本,如HTTP/1.1。
  • 请求头部(Request headers):包括一些关于请求的额外信息,如User-Agent、Content-Type、Authorization等。
  • 请求体(Request body):用于传输请求的数据,对于GET请求来说,请求体通常为空。

示例

以下是一个示例HTTP请求的格式:

GET /index.html HTTP/1.1    
​
Host: www.example.com
​
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 
Safari/537.3
​
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
​
Accept-Encoding: gzip, deflate, br
​
Accept-Language: en-US,en;q=0.9

在这个示例中:

请求行包括GET方法URL为/index.html协议版本为HTTP/1.1

请求头部包括HostUser-AgentAcceptAccept-EncodingAccept-Language等字段。

请求体为空,因为这是一个GET请求。

在上述实例中,申明了该请求是GET请求,我们最常用的请求方式就是GET和POST请求,二者在请求参数的传递中有很大不同,正如上述实例中所说:

GET请求的请求参数在请求行中,没有请求体

POST请求的请求参数在请求体中

格式

在这里插入图片描述

Http响应

介绍

当客户端发起一个请求后,一般都会得到一个服务器的响应,断网或者服务器宕机的情况下除外。服务器发送给客户端的 HTTP 响应用于向客户端提供其请求的资源,以及客户端请求的执行结果。

与请求类似,HTTP 响应同样由四个部分组成,分别为响应行(状态行)、响应头、空行和响应体,如下图所示:

在这里插入图片描述

响应行

响应行以 HTTP 协议版本表示响应状态的状态码形容这个状态的一个短语组成,每个部分使用空格分隔,如下所示:

HTTP/1.1 200 OK

其中,HTTP/1.1 为 HTTP 协议版本,200 为响应的状态码,OK 为状态文本。注意:响应行中的字母都是大写的。

HTTP 响应的状态码是一个三位的整数,其中状态码的第一位用来表示响应的类别,状态码一共有 5 类,如下表所示;
在这里插入图片描述

响应头

响应头与 HTTP 请求中的请求头类似,同样由头部字段名、冒号、空格和值组成,例如Date: Tue, 22 Sep 2020 02:00:55 GMT。响应头中包含了一系列服务器的信息,以及服务器对请求的响应。

HTTP 协议的响应头中常用的头部字段名以及含义如下表所示:

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

空行与响应体

与 HTTP 请求中的空行相同,HTTP 响应中同样使用空行来表示响应头结束。响应体则是服务器根据客户端的请求返回给客户端的具体数据。

示例

HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache/2.2.14 (Win32)
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
Content-Length: 88
Content-Type: text/html
Connection: Closed
​
<html>
<body>
<h1>Hello, CSDN!</h1>
</body>
</html>

3、Servlet

介绍

Servlet 是 JavaEE 的规范之一,通俗的来说就是 Java 接口,将来我们可以定义 Java 类来实现这个接口,并由 Web 服务器运行 Servlet ,所以 TomCat 又被称作 Servlet 容器。

Servlet 提供了动态 Web 资源开发技术,一种可以将网页数据提交到 Java 代码,并且将 Java 程序的数据返回给网页的技术,使用 Servlet 技术实现了不同用户登录之后在页面上动态的显示不同内容等的功能。

简单实现Servlet


@WebServlet("/servlet01")
public class servlet01 extends HttpServlet {@Overrideprotected void service(HttpServletRequest rep, HttpServletResponse resp) throws IOException {System.out.println("hello servlet");resp.getWriter().write("hello servlet?");}
}

在这里插入图片描述

  • 1、创建普通的类
  • 2、继承HttpServlet
  • 3、重写service方法,用来处理请求
  • 4、设置@WebServlet注解,指定访问路径

Servlet的工作流程

在这里插入图片描述

Servlet的实现方式

第一种:继承HttpServlet

@WebServlet("/servlet01")
public class servlet01 extends HttpServlet {@Overrideprotected void service(HttpServletRequest rep, HttpServletResponse resp) throws IOException {System.out.println("hello servlet");resp.getWriter().write("hello servlet?");}
}

第二种:继承GenericServlet

@WebServlet("/serlet02")
public class servlet02 extends GenericServlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
​}
}

第三种:实现Servlet接口

在这里插入图片描述

补充:

除了去实现相应的service方法,实际上我们还可以直接去使用doget,dopost等方法

我们查看Httpservice的源码,看看它的service方法

  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String method = req.getMethod();long lastModified;if (method.equals("GET")) {lastModified = this.getLastModified(req);if (lastModified == -1L) {this.doGet(req, resp);<---------------------------------------------} else {long ifModifiedSince;try {ifModifiedSince = req.getDateHeader("If-Modified-Since");} catch (IllegalArgumentException var9) {ifModifiedSince = -1L;}
​if (ifModifiedSince < lastModified / 1000L * 1000L) {this.maybeSetLastModified(resp, lastModified);this.doGet(req, resp);<--------------------------------------} else {resp.setStatus(304);}}} else if (method.equals("HEAD")) {lastModified = this.getLastModified(req);this.maybeSetLastModified(resp, lastModified);this.doHead(req, resp);<-------------------------------} else if (method.equals("POST")) {this.doPost(req, resp);<--------------------------------------} else if (method.equals("PUT")) {this.doPut(req, resp);<---------------------------------------} else if (method.equals("DELETE")) {this.doDelete(req, resp);<----------------------------------} else if (method.equals("OPTIONS")) {this.doOptions(req, resp);<------------------------------------} else if (method.equals("TRACE")) {this.doTrace(req, resp);<-------------------------------------} else {String errMsg = lStrings.getString("http.method_not_implemented");Object[] errArgs = new Object[]{method};errMsg = MessageFormat.format(errMsg, errArgs);resp.sendError(501, errMsg);<----------------------------------}}

我打标记,这里发现,实质就是先去获取你是什么请求方法,然后去调用对应的doget,dopost等方法

Servlet的生命周期

介绍

在这里插入图片描述

Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

  • Servlet 初始化后调用 init () 方法。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 销毁前调用 destroy() 方法。
  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

架构图:

下图显示了一个典型的 Servlet 生命周期方案。

  • 第一个到达服务器的 HTTP 请求被委派到 Servlet 容器。

  • Servlet 容器在调用 service() 方法之前加载 Servlet。

  • 然后 Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的 service() 方法。

在这里插入图片描述

init() 方法

init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。

Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但是您也可以指定 Servlet 在服务器第一次启动时被加载。

当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。

init 方法的定义如下:

public void init() throws ServletException {// 初始化代码...
}

service() 方法

service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。

每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。

下面是该方法的特征:

public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException{
}

service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,您只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。

doGet() 和 doPost() 方法是每次服务请求中最常用的方法。下面是这两种方法的特征。

doGet() 方法

GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。

public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {// Servlet 代码
}
doPost() 方法

POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。

public void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {// Servlet 代码
}

destroy() 方法

destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。

在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。destroy 方法定义如下所示:

  public void destroy() {// 终止化代码...}

补充:tomocat与servlet工作的时序

在这里插入图片描述

HttpservletRequest

介绍:

httpServletRequest对象对http请求进行了封装,我们使用这个对象就可以方便快捷的获取http中的信息。HttpServletRequest 对象代表客户端的请求,在里面就包含了所有的客服端信息,我们通过这个对象的方法便可以获取所有的客服端信息,包括请求头和请求体中的所有数据。

常见方法:

  1. getRequestURL():得到请求的URI
  2. getRequestURL():得到请求的URL
  3. getHeader(String s):getHeader表示得到请求头,参数s表示想要获取请求头中的什么数据
  4. getHeader("Host"):获取请求的主机
  5. getHeader("Referer"):获取请求来自于哪里,一般用来做防盗链
  6. getRemotetAddr():得到请求的ip
  7. getParameter(String s):得到请求参数的值
  8. getParameterValues(String s):得到请求参数的值,用于参数有多个值,返回一个数组

案例演示:

前端:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>登录</title>
</head>
<body>
<form action="http://localhost:8080/servlet/requestTest" method="post">用户名:<input type="text" name="username"> <br>密 码:<input type="password" name="password"><br>爱好 <input type="checkbox" name="hobby" value="lq">篮球<input type="checkbox" name="hobby" value="zq">足球<input type="checkbox" name="hobby" value="pq">排球<br><input type="submit" value="注册">
</form>
</body>
</html>
后端:
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.Arrays;@WebServlet("/requestTest")
public class HttpServletRequestTest extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//得到请求URLStringBuffer requestURL = request.getRequestURL();System.out.println("请求的URL是:" + requestURL);//得到请求URIString requestURI = request.getRequestURI();System.out.println("请求的URI是:" + requestURI);//得到主机名HostString host = request.getHeader("Host");System.out.println("请求的主机名是:" + host);//得到请求的ipString ip = request.getRemoteAddr();System.out.println(ip);//得到请求参数,分别得到用户名,密码还有爱好//如果参数中有中文,需要设置编码request.setCharacterEncoding("utf-8");String username = request.getParameter("username");String password = request.getParameter("password");String[] hobbies = request.getParameterValues("hobby");System.out.println("用户名为:" + username);System.out.println("密码:" + password);System.out.println("爱好为:" + Arrays.toString(hobbies));//得到访问来自哪里String referer = request.getHeader("Referer");System.out.println("请求来自于:" + referer);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
发送请求

在这里插入图片描述

抓包

请求头:


POST /servlet/requestTest HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 60
Cache-Control: max-age=0
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/servlet/register_request.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=ABEC5EA43080A0BFA70C2AABDF39BB7C; Pycharm-cb145b54=bac13d99-2d7f-4b5f-9c85-e783571ee72d; Idea-8cd34e8b=1bf6d6e0-14ee-4950-96ec-48105743bb40

请求体:
在这里插入图片描述

控制台输出:

在这里插入图片描述

请求转发

介绍

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

request作用域(实际就是service方法里面的HttpServletRequest rep)

在这里插入图片描述


@WebServlet("/s05")
public class servlet03 extends HttpServlet {@Overrideprotected void service(HttpServletRequest rep, HttpServletResponse resp) throws IOException, ServletException {System.out.println("Servlet05");rep.setAttribute("name","admin");rep.getRequestDispatcher("s06").forward(rep,resp);}
}

@WebServlet("/s06")
public class servlet04 extends HttpServlet {@Overrideprotected void service(HttpServletRequest rep, HttpServletResponse resp) throws IOException {System.out.println("Servlet06");String name =(String) rep.getAttribute("name");System.out.println("name"+name);}
}

当我们访问/s05时,请求转发会去跳转到/s06/s06获取到/s05的传送过来的rep里面的name对应的数据

在这里插入图片描述

HttpServletResponse

介绍

在这里插入图片描述

响应数据

响应字符数据

通过response对象,将你想要响应到客户端的字符型数据发送到浏览器里面。只用两步就可以实现:1、先通过response对象获取字符输出流:PrintWriter writer = resp.getWriter();2、将你想要写的数据通过write()方法响应到客户端:writer.write()。

public class HttpServletResponse001 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {PrintWriter writer = resp.getWriter();writer.write("hello servlet!!!");}
}

在这里插入图片描述

需要注意的几点:

1.response不仅可以返回纯文本,还可以HTML的各个标签。在返回标签时要注意先把响应响应头的ContentType属性改成text/html格式,不然浏览器会默认把相应的内容当成纯文本解析。


public class HttpServletResponse001 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html");PrintWriter writer = resp.getWriter();writer.write("hello servlet!!!");writer.write("<br/>name:<input type = 'text'/>");}
}

在这里插入图片描述

2.如果响应的是中文的内容,需要把响应头字体类型改成UTF-8。因为服务器默认的字体类型是ISO-8859-1,如果不修改会导致浏览器解析乱码。
在这里插入图片描述


public class HttpServletResponse001 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        resp.setContentType("text/html");resp.setContentType("text/html;charset=utf-8");PrintWriter writer = resp.getWriter();writer.write("我的servlet程序!!!");writer.write("<br/>姓名:<input type = 'text'/>");}
}

3.修改响应头等信息需要在通过response对象获取字符输出流就完成,在后面才修改没有效果。

4.响应结束后,相应的字符流不需要关闭。他不需要向像Java基础里面字节输入流那种最后需要手动关闭流节省资源。因为在响应结束后,response对象自动销毁,服务器会对其关闭。

响应字节数据

通过response对象,将你想要响应到客户端的字符型数据发送到浏览器里面。大致需要3步完成:1、读取文件(图片,音频,视频等二进制输入输出数据)2、获取字节输出流3、通过write()方法响应给客户端


public class HttpServletResponse002 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1.读物文件FileInputStream inputStream = new FileInputStream("C:\Users\cx\Desktop\1.png");//2.获取字节输出流ServletOutputStream outputStream = resp.getOutputStream();//3.打印文件byte []b = new byte[2048];int len = 0;while ((len = inputStream.read(b))!=0){outputStream.write(b,0,len);}inputStream.close();}
}
补充:响应乱码问题

在这里插入图片描述

重定向

介绍

在这里插入图片描述

注:通常服务器发送一个302状态码以及一个Location消息头(该消息头的值是一个地址,即重定向地址),浏览器收到之后,会立即向重定向地址发送请求。

如何重定向

response.sendRedirect(String url)。
注:url即重定向地址。

重定向与请求转发

重定向:

在这里插入图片描述

请求转发:

在这里插入图片描述

不同:

在这里插入图片描述

Cookie

介绍:

cookie用户标记用户信息,现代浏览器有时会有这样的功能,当我们第一次登录某个系统后,再次登录时,就会直接进入到系统内部,不需要再次输入用户名和密码,就可以直接登录。这是因为我们的浏览器存储了该网站的cookie,当我们向网站发送请求时,网站检测到了cookie,识别出我们的身份,于是就不需要我们再次输入用户名和密码认证了。除此之外,我们在登录网站后,进行一些操作的时候,也会在请求数据包中携带cookie信息,这样可以帮助网站识别这些操作究竟是哪个用户的操作。使用cookie(或者session)识别用户身份是当前网站使用的主流手段。目前网站使用的HTTP协议,是一种无状态的协议,简单来说,就是客户端发送请求,服务器根据请求处理后给予应答。因此,服务器很难判断这些请求究竟是哪个用户发送过来的,通过IP地址等方式无法真正的区分不同的用户,因此我们必须使用cookie(或者session)。

事实上,cookie由服务器产生,发送给客户端,并且要求客户端保留cookie,并且在数据包发送时携带。如下所示:

在这里插入图片描述

上图中的set-cookie属性,就是服务器给客户端发送的cookie。

当然你也可以通过一下路径查看cookie
在这里插入图片描述

Cookie的表示

一般情况下,cookie是以键值对进行表示的(key-value),例如name=jack,这个就表示cookie的名字是name,cookie携带的值是jack。

Cookie的创建与发送

在这里插入图片描述


@RestController
public class servlet05 extends HttpServlet {@GetMapping("/cook01")protected void service(HttpServletRequest rep, HttpServletResponse resp) throws IOException {//Cookie的创建Cookie cookie = new Cookie("name","admin");//发送和响应Cookie对象resp.addCookie(cookie);}
}

在这里插入图片描述

Cookie的获取

在这里插入图片描述


@RestController
public class servlet06 extends HttpServlet {@GetMapping("/cook02")protected void service(HttpServletRequest rep, HttpServletResponse resp) throws IOException {//获取Cookie数组Cookie[] cookies = rep.getCookies();//判断Cookie是否为空if(cookies !=null&&cookies.length>0){//遍历for(Cookie cookie:cookies){//获取名称和值String name = cookie.getName();String value = cookie.getValue();System.out.println(name);System.out.println(value);}}}
}

注意:因为我没有本地自己装tomcat,所以我就换了种方法实现

Cookie设置到期时间

介绍

除了Cookie的名称和内容外,我们还需要关心一个信息,到期时间,到期时间用来指定该cookie 何时失效。默认为当前浏览器关闭即失效。我们可以手动设定cookie的有效时间(通过到期时间计算),通过setMaxAge(int time);方法设定 cookie 的最大有效时间,以秒为单位。

到期时间的取值
负整数

若为负数,表示不存储该 cookie。cookie的 maxAge 属性的默认值就是-1,表示只在浏览器内存中存活,一旦关闭浏览器窗口,那么 cookie 就会消失。

正整数

若大于0的整数,表示存储的秒数。表示cookie对象可存活指定的秒数。当生命大于O时,浏览器会把Cookie保存到硬盘上,就算关闭浏览器,就算重启客户端电脑,cookie也会存活相应的时间。

若为0,表示删除该 cookie。cookie 生命等于0是一个特殊的值,它表示cookie被作废!也就是说,如果原来浏览器已经保存了这个Cookie,那么可以通过Cookie的 setMaxAge(O)来删除这个Cookie。无论是在浏览器内存中,还是在客户端硬盘上都会删除这个Cookie。

实战

@RestController
public class servlet07 extends HttpServlet {@GetMapping("/cook03")protected void service(HttpServletRequest rep, HttpServletResponse resp) throws IOException {//Cookie的创建Cookie cookie = new Cookie("name1","admin1");//Cookie到期时间设置cookie.setMaxAge(-1);//关闭浏览器失效//发送和响应Cookie对象resp.addCookie(cookie);
​//Cookie的创建Cookie cookie2 = new Cookie("name2","admin2");//Cookie到期时间设置cookie2.setMaxAge(30);//存活30秒//发送和响应Cookie对象resp.addCookie(cookie2);
​//Cookie的创建Cookie cookie3 = new Cookie("name3","admin3");//Cookie到期时间设置cookie3.setMaxAge(0);//删除cookie3//发送和响应Cookie对象resp.addCookie(cookie3);
​}
}

分析:

在这里插入图片描述

你发现只有两个,原因就是当到期时间设置为0时,就是删除了这个cookie

当我们30s后重新去访问(Cookie的获取哪里写的路径:目的时后台打印)时会发现,只剩下

在这里插入图片描述

当我们关闭浏览器后,再次去访问(Cookie的获取哪里写的路径:目的时后台打印)时会发现,全没了

在这里插入图片描述

注意:之前在Cookie的创建与发送标题中的Cookie这里已经被我提前删除了,所以并没有它。

Cookie的注意点

1、Cookie保存在当前浏览器中。在一般的站点中常常有记住用户名这样一个操作,该操作只是将信息保存在本机上,换电脑以后这些信息就无效了。而且cookie 还不能跨浏览器。

2、Cookie存中文问题Cookie 中不能出现中文,如果有中文则通过URLEncoder.encode()来进行编码,获取时通过URLDecoder.decode()来进行解码。


String name = “姓名"
String value = "张三";
// 通过 URLEncoder.encode()来进行编码
name = URLEncoder.encode(name);
value = URLEncoder.encode(value) ;
// 创建cookie对象
Cookie cookie = new Cookie(name,value) ;
//发送cookie对象response.addcookie(cookie);

//获取时通过uRLDecoder.decode()来进行解码
URLDecoder.decode(cookie.getName()) ;
URLDecoder.decode(cookie.getValue()) ;

3、同名Cookie问题如果服务器端发送重复的Cookie那么会覆盖原有的Cookie。

4、浏览器存放Cookie的数量不同的浏览器对Cookie也有限定,Cookie的存储有是上限的。Cookie是存储在客户端(浏览器)的,而且一般是由服务器端创建和设定。后期结合Session来实现回话跟踪。

Cookie的路径

介绍:

Cookie的setPath设置cookie的路径,这个路径直接决定服务器的请求是否会从浏览器中加载某些cookie。

情景一:当前服务器下任何项目的任意资源都可获取Cookie对象

/*当前项目路径为:s01*/
Cookie cookie = new Cookie("xxx","xxx");
//设置路径为"/",表示在当前服务器下任何项目都可访问到cookie对象
cookie.setPath("/");
response.addcookie(cookie) ;
情景二:当前项目下的资源可获取Cookie对象(默认不设置Cookie的path)

/*当前项目路径为:s01*/
Cookie cookie = new Cookie("xxx","xxx") ;
//设置路径为"/s01",表示在当前项目下任何项目都可访问到cookie对象
cookie.setPath("/s01");//默认情况,可不设置path的值
response.addcookie(cookie) ;
情景三:指定项目下的资源可获取Cookie对象

/*当前项目路径为:s01*/
Cookie cookie = new Cookie("xxx","xxx");
//设置路径为"/s02",表示在s02项目下才可访问到cookie对象
cookie.setPath("/s02");//只能在s02项目下获取cookie,就算cookie是s01产生的,s01也不能获取它
response.addcookie(cookie) ;
情景四:指定目录下的资源可获取Cookie对象

/*当前项目路径为:s01*/
Cookie cookie = new Cookie("xxx","xxx");
//设置路径为"/s01/cook",表示在s02/cook目录下才可访问到cookie对象
cookie.setPath("/s01/cook") ;response.addcookie(cookie) ;
总结:

如果我们设置path,如果当前访问的路径包含了cookie的路径(当前访问路径在cookie路径基础上要比cookie的范围小)cookie就会加载到request对象之中。cookie的路径指的是可以访问该cookie的顶层目录,该路径的子路径也可以访问该cookie。总结:当访问的路径包含了cookie的路径时,则该请求将带上该cookie;如果访问路径不包含cookie路径,

HttpSession

介绍

Session技术是将数据存储在服务器端的技术,会为每个客户端都创建一块内存空间 存储客户的数据,但客户端需要每次都携带一个标识ID去服务器中寻找属于自己的内 存空间。所以说Session的实现是基于Cookie,Session需要借助于Cookie存储客 户的唯一性标识JSESSIONID;

使用场景

我们先来想一个问题,这个问题就是我们在游览购物网站时,我们并没有登录,但是我们任然可以将商品加入购物车,并且进行查看,当我们退出游览器后再打开游览器进行查看时,购物车中依然有我们选择的商品,这该怎么实现呢?

​ 当然,我们可以使用cookie,但是cookie能存放大量数据吗?这时,我们就需要一种新的技术,Session。session是存储于服务器端的特殊对象,服务器会为每一个游览器(客户端)创建一个唯一的session。这个session是服务器端共享,每个游览器(客户端)独享的。我们可以在session存储数据,实现数据共享。

原理示意图

在这里插入图片描述

简单使用


@RestController
public class servlet08 extends HttpServlet {@GetMapping("/session01")protected void service(HttpServletRequest rep, HttpServletResponse resp) throws IOException {//获取session对象HttpSession session = rep.getSession();//获取session的会话标识符String id =session.getId();System.out.println(id);//获取session创建时间long creationTime = session.getCreationTime();System.out.println(creationTime);//获取最后一次访问时间long lastAccessedTime = session.getLastAccessedTime();System.out.println(lastAccessedTime);// 判断是否是新的session对象boolean aNew = session.isNew();System.out.println(aNew);}
}

在这里插入图片描述

标识符JSESSIONID

​ Session既然是为了标识一次会话,那么此次会话就应该有一个唯一的标志,这个标志就是sessionld。

每当一次请求到达服务器,如果开启了会话(访问了session),服务器第一步会查看是否从客户端回传一个

名为JSESSIONID的cookie,如果没有则认为这是一次新的会话,会创建一个新的 session对象,并用唯一的

seSSionld为此次会话做一个标志。如果有JESSIONID这个cookie回传,服务器则会根据JSESSIONID 这个值去查

看是否含有id为JSESSION值的session对象,如果没有则认为是一个新的会话,重新创建一个新的session对象,

并标志此次会话;如果找到了相应的 session对象,则认为是之前标志过的一次会话,返回该session对象,数

据达到共享。

这里提到一个叫做JSESSIONID的cookie,这是一个比较特殊的cookie,当用户请求服务器时,如果访问了

session,则服务器会创建一个名为JSESSIONID,值为获取到的 session(无论是获取到的还是新创建的)的

sessionld 的 cookie 对象,并添加到 response 对象中,响应给客户端,有效时间为关闭浏览器。

所以 Session的底层依赖Cookie来实现。

Session域对象


@RestController
public class servlet09 extends HttpServlet {@GetMapping("/session02")protected void service(HttpServletRequest rep, HttpServletResponse resp) throws IOException {//获取session对象HttpSession session = rep.getSession();//获取域对象session.setAttribute("uname","upwd");session.setAttribute("uname1","upwd1");//移除域对象session.removeAttribute("uname");}
}

Session对象的销毁

大纲
  • 默认时间到期
  • 自己设定到期时间
  • 立刻失效
  • 关闭浏览器
  • 关闭服务器
默认时间到期

当客户端第一次请求 servlet 并且操作 session 时,session 对象生成,以 Tomcat 为例,Tomcat 中 session 默认的存活时间为 30min,即你不操作界面的时间,一旦有操作,session 会重新计时。那么 session 的默认时间可以改么?答案是肯定的。可以在 Tomcat 中的 web.xml 文件中进行修改。如下图:

在这里插入图片描述

自己设定到期时间

当然除了以上的修改方式外,我们也可以在程序中自己设定 session 的生命周期,通过 session.setMaxInactiveInterval(int); 来设定 session 的最大不活动时间,单位为秒。

HttpSession session = req.getSession();
session.setMaxInactiveInterval(5);

当然我们也可以通过 getMaxInactiveInterval(); 方法来查看当前 Session 对象的最大不活动时间。

立刻失效

或者我们也可以通过 session.invalidate(); 方法让 session 立刻失效。

session.invalidate();
关闭浏览器

session 的底层依赖 cookie 实现,因为不同用户访问服务器要判别到底是使用哪个 session,所以当用户第一次访问服务器的时候往往会把一个 session id 通过 cookie 存储到用户端,并且该 cookie 的有效时间为关闭浏览器,从而 session 在浏览器关闭时也相当于失效了(因为没有 session id 再与之对应)。如下图,关闭后再打开,重新给浏览器分配了个 session id。

在这里插入图片描述

需要注意的是这里只是 cookie 失效了,你再访问相当于服务器把你当成了新用户,又给你创建了一个 session,并没有把之前的 session 对象销毁。

关闭服务器

当非正常关闭服务器时,session 销毁;当正常关闭服务器时,session 将被序列化到磁盘上,在工作空间 work 目录下的 SESSION.ser 文件中,如果对象被保存在了 session 中,服务器在关闭时要把对象序列化到硬盘,这个对象就必须实现 Serializable 接口,下次启动服务时,自动加载到内存。如下图,正常关闭后可以看到文件夹中多了一个 SESSIONS.ser 文件,再次启动服务器则文件消失。

在这里插入图片描述

ServletContext

介绍:

ServletContext是Servlet规范中的一个对象,它代表了当前Web应用程序的上下文(Context)。这个上下文包括了整个Web应用程序的信息,可以被Web应用中的所有Servlet共享。可以将ServletContext看作是一个全局存储区,用于存储和访问Web应用中的全局数据和资源。

我们将ServletContext和Cookie、Session做一个简单对比,如下图:
在这里插入图片描述

我们可以把ServletContext当成一个公用的空间,可以被所有的客户访问,如上图,A、B、C三个客户端都可以访问。WEB容器在启动时,它会为每个Web应用程序都创建一个对应的ServletContext,它代表当前Web应用,并且它被所有客户端共享。

由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。公共聊天室就会用到它。

当web应用关闭、Tomcat关闭或者Web应用reload的时候,ServletContext对象会被销毁。

获取ServletContext

在这里插入图片描述

常用方法

获取当前服务器信息:
在这里插入图片描述

获取项目的真实路径:
在这里插入图片描述

效果:

在这里插入图片描述

三大域对象

在这里插入图片描述

三大域对象的数据作用范围图解 :

  • 请求域

客户端发送一次的请求,以及,请求转发

在这里插入图片描述

  • 会话域 :

同一个客户端,跨多个请求 传递信息,举例:servletA可以servletB、C、D也可以接受信息,只要拿到session对应的cookie

在这里插入图片描述

  • 应用域

跨客户端 , 另一个客户端也能取到数据
在这里插入图片描述

  • 所有域 合体

在这里插入图片描述

结言:

你好,我是Blue. 为帮助别人少走弯路而写博客 !!!

如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 😄 (^ ~ ^) 。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。

如果你遇到了问题,自己没法解决,可以私信问我。

感谢订阅专栏 三连文章!!

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

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

相关文章

大数据可视化-三元图

三元图是一种用于表示三种变量之间关系的可视化工具&#xff0c;常用于化学、材料科学和地质学等领域。它的特点是将三个变量的比例关系在一个等边三角形中展示&#xff0c;使得每个点的位置代表三个变量的相对比例。 1. 结构 三个角分别表示三个变量的最大值&#xff08;通常…

TikTok流量不佳:是网络环境选择不当还是其他原因?

TikTok&#xff0c;作为全球短视频社交平台的佼佼者&#xff0c;每天都有海量的内容被上传和分享。然而&#xff0c;很多用户和内容创作者发现&#xff0c;他们的TikTok视频流量并不理想。这引发了一个问题&#xff1a;TikTok流量不佳&#xff0c;是因为网络环境选择不当&#…

Lumos学习王佩丰Excel第十五讲:条件格式与公式

一、使用简单的条件格式 1、为特定范围的数值标记特殊颜色 条件格式-需选择设定范围&#xff08;大于/小于/介于/......&#xff09;&#xff1a; 数值会动态根据条件判断更新颜色&#xff1a; 模糊匹配&#xff0b;条件格式&#xff1a;选择包含部分文本的特殊值 2、查找重复…

【BurpSuite】Cross-site scripting (XSS 学徒部分:1-9)

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【BurpSuite】Cross-site scripting (XSS 学徒部分:1-9&#xff09; 实验一 Lab: Reflected XSS into HTML context with nothing…

国自然基金项目撰写技巧、技术路线与ChatGPT融合应用

随着社会经济发展和科技进步&#xff0c;基金项目对创新性的要求越来越高。申请人需要提出独特且有前瞻性的研究问题&#xff0c;具备突破性的科学思路和方法。因此&#xff0c;基金项目申请往往需要进行跨学科的技术融合。申请人需要与不同领域结合&#xff0c;形成多学科交叉…

一款批量下载 B 站动态页图片的脚本

在逛 B 站的时候&#xff0c;总能看到不少 UP 会发很多图片&#xff0c;此时一个一个保存非常麻烦&#xff0c;而且文件名都是随机的字符串&#xff0c;还得手工重命名。 为此&#xff0c;特地搜索了下有没相关的浏览器插件或油猴脚本&#xff0c;还真给我找到一个。 脚本地址…

图解 TCP 四次挥手|深度解析|为什么是四次|为什么要等2MSL

写在前面 今天我们来图解一下TCP的四次挥手、深度解析为什么是四次&#xff1f; 上一片文章我们已经介绍了TCP的三次握手 解析四次挥手 数据传输完毕之后&#xff0c;通信的双方都可释放连接。现在客户端A和服务端B都处于ESTABLISHED状态。 第一次挥手 客户端A的应用进…

计算机网络-小型综合网络的搭建涉及到无线路由交换安全

目录 1 拓扑架构 2 做项目的思路 3 做配置 3.1先做核心交换 3.2 防火墙的配置 4 ac 和ap 的配置 4.1 ac上配置安全的东西 5.1 测试​编辑 1 拓扑架构 要求看上面的图 2 做项目的思路 这张网很明显是一个小综合&#xff0c;设计到我们的无线交换&#xff0c;路由…

MISC - 第二天(wireshark,base64解密图片,zip文件伪加密,LSB二进制最低位,ARCHPR工具)

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天给大家讲解杂项 乌镇峰会种图 使用了stegsolve工具&#xff0c;查看更多信息 发现flag信息 更改为html后缀flag{97314e7864a8f62627b26f3f998c37f1} wireshark 看题目是 分析pacp数据包&#xff0c;通过网站登录…

HarmonyOS应用开发(组件库)--组件模块化开发、工具包、设计模式(持续更新)

致力于&#xff0c;UI开发拿来即用&#xff0c;提高开发效率 正则表达式...手机号校验...邮箱校验 文件判断文件是否存在 网络下载下载图片从沙箱中图片转为Base64格式从资源文件中读取图片转Base64 组件输入框...矩形输入框...输入框堆叠效果&#xff08;用于登录使用&#xf…

基于ECC簇内分组密钥管理算法的无线传感器网络matlab性能仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于ECC簇内分组密钥管理算法的无线传感器网络matlab性能仿真&#xff0c;对比网络通信开销&#xff0c;存活节点数量&#xff0c;网络能耗以及数据通信量四个指标…

C语言的文件函数

此篇文章主要对C语言中的" 文件读写函数 "进行详细的刨析~通过此篇文章能够了解并学习到&#xff1a;" 字符读写函数 "&#xff0c;" 文本行读写函数 "&#xff0c;" 格式化读写函数 "&#xff0c;" 二进制读写函数 "&#…

深度学习与应用:人体关键点检测

实验二 深度学习与应用&#xff1a;人体关键点检测 1、 实验目的 了解人体关键点检测基础流程熟悉YOLOV7-pose模型结构掌握 YOLOv7-pose 模型的训练、Fine-tuning 以及推理的能力掌握YOLOV7-pose模型对实际问题的应用能力&#xff0c;了解如何在特定的场景和任务中应用该模型…

【机器学习】——线性回归(自我监督学习)

文章目录 1. 线性回归的定义2. 线性回归的模型3. 线性回归的核心思想4. 线性回归的求解5. 线性回归的假设6. 模型评估7. 线性回归的优缺点8. 线性回归的扩展9. 线性回归的实际应用10. 示例代码&#xff08;Python实现&#xff09; 线性回归详细介绍 1. 线性回归的定义 线性回归…

53 语言模型(和之后用来训练语言模型的数据集)_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录理论部分使用计数来建模N元语法总结 代码读取长序列数据随机采样顺序分区 小结练习 理论部分 在上一部分中&#xff0c;我们了解了如何将文本数据映射为词元&#xff0c;以及将这些词元可以视为一系列离散的观测&#xff0c;例如单词或字符…

.bixi勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复

导言 在当今数字化时代&#xff0c;勒索软件已成为企业和个人面临的重大安全威胁。.bixi勒索病毒作为其中一种新型恶意软件&#xff0c;以其快速加密文件的能力和高效传播机制引发了广泛关注。该病毒不仅能够迅速锁定用户的关键数据&#xff0c;还常常在感染后施加极大的心理压…

邀请功能的实现分析

邀请功能 功能分析 场景&#xff1a;项目中出现用户邀请其他用户加入群组的功能 需求&#xff1a;用户点击生成邀请链接可以生成一个url&#xff0c;将这个url分享给其他用户&#xff0c;其他用户点击后对用户登录状态进行校验&#xff0c;校验通过即可加入群组&#xff0c;未…

江协科技STM32学习- P16 实验-TIM输出比较(PWD驱动LED呼吸灯,舵机,直流电机)

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

如何访问字符串中某个字符

在Java中&#xff0c;你可以使用字符串的charAt(int index)方法来查看字符串中第index个位置的字符。index是从0开始的&#xff0c;也就是说&#xff0c;字符串的第一个字符的索引是0&#xff0c;第二个字符的索引是1&#xff0c;以此类推。如果索引超出了字符串的长度&#xf…

IO多路转接:select、poll、epoll

目录 非阻塞读取 fcntl函数 I/O多路转接之select select函数 fd_set结构 select的模拟实现 select的优缺点 I/O多路转接之poll poll函数 struct pollfd结构体 poll函数的使用示例 poll的模拟实现 poll的优缺点 I/O多路转接之epoll epoll的三个系统调用 epoll的…