浏览器缓存控制讲解
缓存的作用
在你访问互联网中的任何资源其所产生的任何链路中的每一个节点几乎都会进行缓存,整个缓存体系和细节十分复杂。比如浏览器缓存,服务器缓存,代理服务器缓存,CDN缓存等。
但是缓存又十分重要,不可缺少,为什么这么说呢?
由于HTTP请求的链路漫长,环境复杂,把一些必要的信息在关键的节点进行缓存,下次请求的时候可以尽可能的复用数据,就可以节省一部分资源的消耗,减少HTTP请求应答的成本,节约带宽,加快响应速度。
那么,基于请求-应答模式的特点,缓存大致可以分为服务器缓存和客户端缓存,而服务器缓存经常与代理服务关联在一起。这次我们主要关注浏览器是如何进行缓存的。
缓存的形式
Memory Cache(内存缓存)
- 时间间隔较短时, 重复请求相同的静态资源时, 一般情况下资源还在内存中, 那直接从内存中获取资源, 这种方式是最快的资源获取方式。
- 通常情况下, 关闭 tab 页签时, 会清除内存中的资源。
Disk Cache(硬盘缓存)
- 把资源存储到本机的硬盘上, 当再次需要数据时, 可以直接从硬盘上获取。
- 缓存的时间一般会根据响应头的设置而定。
CDN 缓存
- 当用户请求资源时会经过 CDN 服务器, 服务器会对可以缓存的资源进行缓存。
- 当有另外的用户也需要这个资源时, CDN 服务器就可以直接返回资源, 不需要再找原服务器要了。
服务端缓存
- 当一些数据需要服务端进行大量计算才能获得时, 服务端为了避免重复的处理影响服务器性能, 开发人员会对处理过的数据进行缓存, 下次再需要时直接取缓存中的数据。
- 服务端缓存一般是一些接口的缓存处理,缓存时效可能根据数据的性质不同而不同。
缓存控制
假设,现在没有缓存,我们想象一下获取资源的方式是什么样的?
客户端请求资源,服务器返回资源,等下一次想要获取同样资源的时候,哪怕服务器的资源并没有更新,还是要重新走一遍网络请求,然后服务器返回资源的完整链路。
那如果有了缓存,在客户端第一次获取到请求的资源后,把资源缓存到本地,下次再去请求的时候,发现本地有这个资源,直接拿来用就好了,完全不用去走网络请求。
HTTP缓存都是从第二次请求开始的,可以概述如下:
-
第一次请求资源时:
服务器返回资源,并在 response header(响应头) 中回传资源的缓存策略;
-
第二次请求时:
浏览器判断这些请求参数,击中强缓存就直接200;
否则就把请求参数加到request header(请求头)中传给服务器,看是否击中协商缓存,击中则返回304,否则服务器会返回新的资源。
我们仔细的阅读一下这个简单的缓存资源请求流程,发现其中有几个重要的节点。
首先,服务器在返回该资源时,要标记该资源的有效期。然后,浏览器初次请求肯定是没缓存的,再次请求的时候,它要根据该资源的有效期来判断下一步该怎么办。
我们再简单一点,如果我们试图去获取缓存资源,其实是要看服务器的标记的。那么换句话说,服务器标记缓存资源,浏览器会验证该缓存资源的标记。
浏览器每次发起请求时,会先在浏览器缓存中查找该请求的结果以及缓存标识,根据缓存标识来判断是否使用本地缓存。如果缓存有效,则使用本地缓存;否则,则向服务器发起请求并携带缓存标识。
根据是否需向服务器发起请求,将缓存过程划分为两个部分:强制缓存和协商缓存,强缓存优先于协商缓存。
浏览器缓存控制机制有两种:HTML Meta 标签 和 HTTP 头信息
使用HTML Meta 标签
HTML Meta标签是应用在HTML文件中的head头部分。
<meta http-equiv="Cache-Control" content="max-age=7200" />
// or
<meta http-equiv="Cache-Control" content="no-cache" />
主要作用就是告诉浏览器此HTML页面不被缓存,每次访问都去服务器上下载。
使用上很简单,但这个是 IE 时代的私有属性,在 IE9 以前支持的,而现在主流的 Chrome / Firefox / Safari,包括 IE9 ~ IE11 都不支持。而且所有缓存代理服务器都不支持。因为代理不解析HTML内容本身。
所以我们常说的浏览器缓存还是通过HTTP头信息来控制缓存。
http-equiv
倒确实在 HTML 规范中有几个值可以设(content-security-policy
、content-typ
e、default-style、x-ua-compatible
、refresh
),但都跟缓存无关,可以参阅文档 http-equiv。
使用HTTP头信息控制缓存
使用 HTTP 头信息进行缓存处理一般是通过设置相应的请求头/响应头实现的
常见的处理方式有 4 种
Cache-Control
Expires
Etag
/If-None-Match
Last-Modified
/If-Modified-Since
后3种是 http 1.0 就已经支持的,Cache-Control
是 http 1.1 支持的
缓存优先级: Cache-Control
> Expires
> Etag
> Last-Modified
Cache-Control
和 Expires
首部用于指定缓存时间,Last-Modified
和 ETag
首部提供验证机制。
通过浏览器开发者工具我们可以看到,浏览器请求服务器静态资源的响应状态码主要就是下图的四种:
强缓存
通过 Expires
(http1.0) 和 Cache-Control
(http1.1) 两个响应头字段来控制,如果同时存在,则后者优先级高于前者。
服务器通知浏览器一个缓存时间,在缓存时间内,下次请求直接从本地缓存中读取资源而不发起请求。不在时间内,执行比较缓存策略。
-
强缓存命中则直接读取浏览器本地的资源,在network中显示的是
from memory cache
或者from disk cache
。 -
Cache-Control
是一个相对时间,用以表达自上次请求正确的资源之后的多少秒的时间段内缓存有效。 -
Cache-Control
的出现是为了解决Expires
在浏览器时间被手动更改导致缓存判断错误的问题。
Expires 缓存过期时间
Expires
是http响应头字段,是一个绝对时间,用以告诉浏览器这个时间点之前发起请求可以直接从浏览器中读取数据,而无需发起请求。
Expires
字段为一个日期, 客户端请求该资源时将这个日期与客户端当前日期进行比对。- 如果当前时间小于这个日期, 则表示资源未过期, 使用缓存。
- 如果当前时间大于这个日期, 则表示资源已过期, 客户端就会重新请求该资源。
优势:
- HTTP 1.0 产物,可以在HTTP 1.0和1.1中使用,简单易用。
- 以时刻标识失效时间,简易易理解
劣势:
- 我们依赖客户端时间, 就会因为客户端的时间不准确导致判断错误,致使缓存失效。如果客户端时间早于服务器的时间, 会导致资源还未过期就重新请求。反之, 会导致客户端还在使用过期的旧资源。
Cache-Control 缓存控制
Cache-Control
通用消息头字段,被用于在 http 请求和响应中,通过指定指令来实现缓存机制。
缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中。
一般用在http响应中进行客户端缓存设置。
Cache-Control
是在 HTTP/1.1 中才有, 算是一个"新"的API (新是相对以前的处理, 因为现在已经有 HTTP3 了)
可选的参数有很多: max-age=
,no-store
,no-cache
,must-revalidate
,private
,public
等
在HTTP/1.1中增加的字段。属于相对时间。该字段表示资源缓存的最大有效时间,在该时间内,客户端不需要向服务器发送请求。比Expires
多了很多选项设置。
-
max-age
可以用来表示过期时长,单位是秒。表达式是这样子的:
Cache-Control: max-age=30
该资源的有效期是30秒。
这是一个相对时间,时间计算的起点是报文创建的时刻,也就是响应头Date字段的时间,是指资源离开服务器的时刻,而不是客户端收到报文的时候。
换句话说,假设我们设置的时间是5秒,但是链路请求很长,花费了4秒的时间,那么缓存对于浏览器的有效时间只是1秒。
那你可能会说,就这一秒有啥用啊~~假设你网站的访问量特别大,每秒有上百万的访问,那你可以想象到这仅仅一秒的时间能节省服务器多大的压力了吧。当然,只是举个极限的例子~
我们先搞个
max-age
的小例子,看看缓存能否生效:res.setHeader("Cache-Control", "max-age=20");
我们可以看到在响应头中返回了我们设置好的缓存字段:
除了max-age这个最常用的属性以外,还有三个属性可以更精确的指示浏览器如何使用缓存
-
no-store
浏览器和代理服务器禁止缓存,每次只能去服务器请求最新资源。用于某些变化非常频繁的页面,比如秒杀页面。
Cache-Control: no-store
-
no-cache
它的字面意思和
no-store
很容易搞混,实际上它的意思并不是不允许缓存,而是可以缓存,只是不使用强缓存,每次使用前必须要去服务器验证是否过期,是否有最新的版本。同时,代理服务器也不能对资源进行缓存。一般用于长期不变的资源,客户端只需要发送很小的信息跟服务端进行确认 (协商缓存验证)。 -
must-revalidate
和
no-cache
又很相似,它的意思是缓存不过期就可以继续使用,但是过期了如果还想用就必须去服务器验证一下。 -
private
只有浏览器可以缓存
-
public
浏览器,服务器,代理服务器都可以缓存
Cache-Control
时指定 no-cache
或 max-age=0, must-revalidate
表示客户端可以缓存资源,但每次使用缓存资源前都必须重新验证其有效性。这意味着每次都会发起 HTTP 请求,但当缓存内容仍有效时可以跳过 HTTP 响应体的下载。
Cache-Control: no-cache
# or
Cache-Control: max-age=0, must-revalidate
优势:
- HTTP 1.1 产物,以时间间隔标识失效时间,解决了
Expires
服务器和客户端相对时间的问题。 - 比
Expires
多了很多选项设置。
劣势:
- 存在版本问题,到期之前的修改客户端是不可知的。
协商缓存
协商缓存有 2 组字段(不是两个),控制协商缓存的字段有:Last-Modified
/ If-Modified-Since
(http1.0)和 Etag
/ If-None-Match
(http1.1)。如果同时存在,则后者优先级高于前者。
Last-Modified / If-Modified-Since
Last-Modified
很好理解,就是服务端返回最后一次修改文件的时间。
If-Modified-Since
(客服端发起): 本地文件的修改时间(可以理解为上次请求返回的 Last-Modified
的值),以后每次请求,请求头都会都带上。
如果强制缓存未命中,但协商缓存可用,需要第一次请求的时候,HTTP响应头中返回Last-Modified
或ETag
,当第二次请求的时候请求头会自动设置 If-Modified-Since
或者 If-None-Match
的值,服务端根据值,去决策验证是否命中协商缓存。
如果命中了协商缓存,那么服务器仅返回**304(不返回数据实体)**状态码,更新下资源的有效时间,使用本地缓存,因此在响应体体积上的节省是它的优化点。没有命中则返回200状态码。
优势:
- 不存在版本问题,每次请求都会去服务器进行校验。
劣势:
- 有新资源服务端却返回304,因为
Last-Modified
是以秒级为记录的,如果资源在1秒内改变的话,Last-Modified
是无感的。
Etag / If-None-Match
ETag
是 实体标签(Entity Tag) 的缩写。请求数据成功后, 服务端返回数据时响应头会携带 Etag
,他是根据文件内容生成的一个字符串, 当文件变化时他也会跟着改变,一般都是 hash 生成的,是资源的唯一标识。
If-None-Match
是客户端发起的上次返回的 Etag
值。服务器会将 If-None-Match
的值与自己本地资源的 ETag
的值进行对比。如果相等,则表示未修改,响应 304;反之,则表示修改了,响应 200 状态码,并返回最新数据。整个流程基本上和 (Last-Modified
/ If-Modified-Since
) 很类似。
ETag
主要是用来解决修改时间无法准确区分文件变化的问题。
比如,文件的修改时间是秒级甚至更短的,所以一秒内的新版本是无法区分的,再比如,一个文件定期更新,但有时内容没有变化,用修改时间就会以为发生了变化,发送给客户端以为是新的资源,浪费带宽。使用ETag
就可以精确的识别资源的变动情况,让浏览器更有效地利用缓存。
ETag
还有强弱之分。
强 ETag
要求资源在字节级别必须完全相符,弱 ETag
在值前有个W/
标记,只要求资源在语义上没有变化,但内部可能会有部分发生了改变(例如 HTML 里的标签顺序调整,或者多了几个空格)。至于是强还是弱,其实是由服务器自主决定的。弱也可以强,强也可以弱。
优势:
- 可以更加精确的判断资源是否被修改,可以识别一秒内多次修改的情况。
- 不存在版本问题,每次请求都会去服务器进行校验。
劣势:
- 计算
ETag
值需要性能损耗。 - 分布式服务器存储的情况下,计算
ETag
的算法如果不一样,会导致浏览器从一台服务器上获得页面内容后到另外一台服务器上进行验证时出现ETag
不匹配的情况。
浏览器自身的缓存控制
客户端也可以控制缓存,客户端是怎么控制的呢?
当你点击浏览器的刷新按钮的时候,实际上,浏览器就在HTTP请求中夹带了Cache-Control:max-age=0
,之前说过,max-age
是生存时间,纪录的是从服务器生成的那一刻的有效期,而浏览器本地的资源,肯定不可能是0,所以当浏览器加上了max-age=0
的时候,每次都会向服务器请求最新的资源。
而当你使用Control+F5强制刷新的时候其实是浏览器发了一个Cache-Control: no-cache
。基本上和max-age=0
差不多一样的效果,但是含义肯定是不一样的,就看服务器要怎么理解和处理不同的字段。
那么什么时候缓存才能派上用场呢?当我们点击浏览器的前进后退按钮的时候,就会直接从缓存中获取数据,另外,重定向的时候,也可能会使用到缓存。那这两类操作有啥区别呢。其实本质上来说,就是前进、后退、跳转这样的操作,浏览器不会私自加上Cache-Control
字段,并且会清空If-Modified-Since
和 If-None-Match
字段,所以就会检查缓存,直接利用之前的资源,不再进行网络通信。
大家还可以自己尝试设置no-store
,no-cache
等字段。当你设置了no-store
属性后,你会发现,哪怕使用浏览器的前进,后退按钮,每次也是重新从服务器获取资源,但是no-cache
和max-age
则会使用缓存。
哪些请求不会被缓存?
-
HTTP 信息头中包含
Cache-Control:no-cache,pragma:no-cache
,或Cache-Control:max-age=0
等告诉浏览器不用缓存的请求。 -
HTTP响应头中不包含
Cache-Control
/Expires
,也不包含Last-Modified
/ETag
的请求无法被缓存。 -
POST 请求无法被缓存
部署时缓存的问题
我们不仅要缓存代码,还需要更新代码。如果静态资源名字不变,怎么让浏览器既能缓存,又能在有新代码时更新?
最简单的解决方式就是静态资源路径添加一个版本值。
版本不变就走缓存策略,版本变了就加载新资源。如下:
<script src="xx/xx.js?v=24334452"></script>
然而这种处理方式在部署时有问题。
背景:静态资源和页面是分开部署的
无论是先部署页面,还是先部署静态资源,在特定的阶段访问,就会出现页面和js文件不匹配进而报错。
这些问题的本质是以上的部署方式是“覆盖式发布”,解决方式是“非覆盖式发布”。
即用静态资源的文件摘要信息给文件命名,这样每次更新资源不会覆盖原来的资源,先将资源发布上去。
这时候存在两种资源,用户用旧页面访问旧资源,然后再更新页面,用户变成新页面访问新资源,就能做到无缝切换。
简单来说就是给静态文件名加hash值。
那如何实现呢?使用webpack持久化缓存
现在前端代码都用webpack之类的构建工具打包。浏览器有其缓存机制,想要既能缓存又能在部署时没有问题,需要给静态文件名添加hash值。
相关文章:

浏览器缓存控制讲解
缓存的作用 在你访问互联网中的任何资源其所产生的任何链路中的每一个节点几乎都会进行缓存,整个缓存体系和细节十分复杂。比如浏览器缓存,服务器缓存,代理服务器缓存,CDN缓存等。 但是缓存又十分重要,不可缺少&…...

批量插入SQL 错误 [933] [42000]: ORA-00933: SQL 命令未正确结束
使用DBeaver向【oracle数据库】插入大量数据 INSERT INTO Student(name,sex,age,address,birthday) VALUES(Nike,男,18,北京,2000-01-01) ,(Nike,男,18,北京,2000-01-01) ,(Nike,女,18,北京,2000-01-01) ,(Nike,女,18,北京,2000-01-01) ,(Nike,男,18,北京,2000-01-01) ,(Nike…...

北京数字孪生赋能工业制造,加速推进制造业数字化转型
随着新一代信息技术与实体经济深度融合进程的加快,企业数字化转型需求的提升,政策的持续支持,数字孪生将为工业制造、未来生活带来无限的可能。在制造业数字化大变革时代,以5G、大数据、物联网、人工智能等为代表的工业4.0&#x…...

【NLP】GPT 模型如何工作
介绍 2021 年,我使用 GPT 模型编写了最初的几行代码,那时我意识到文本生成已经达到了拐点。我要求 GPT-3 总结一份很长的文档,并尝试了几次提示。我可以看到结果比以前的模型先进得多,这让我对这项技术感到兴奋,并渴望…...

Linux下安装Foldseek并从蛋白质的PDB结构中获取 3Di Token 和 3Di Embedding
0. 说明: Foldseek 是由韩国国立首尔大学 (Seoul National University) 的 Martin Steinegger (MMseqs2 和 Linclust 的作者) 开发的一款用于快速地从大型蛋白质结构数据库中检索相似结构蛋白质的工具,可以用于计算两个蛋白之间的结构相似性,…...

单元测试-java.lang.NullPointerException
报错信息 java.lang.NullPointerException 空指针异常 空对象引用 来源 对Controller层进行单元测试,解决完Spring上下文报错后继续报错。 解决 在测试方法执行前要为字段完成对象的注入,否则就报空指针异常。 测试例子 不完整启动Spring框架 pub…...
机器学习数据集整理:图像、表格
前言 如果你对这篇文章感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。 表格数据 Sklearn 提供了 13 个表格型数据,且数据处理接口统一;LIBSVM 提供了 131 个表格型数据&a…...
Vue: Cannot find module @/xx/xx/xx.vue or its corresponding type declarations.
编辑器:Webstorm项目技术栈:vitevuets解决 1.vite.config.js设置别名resolve: {alias: {: path.resolve(__dirname, ./src),}, }, 2.src下创建globals.d.ts//通用声明 // Vue declare module *.vue {import { DefineComponent } from vue;const componen…...

怎样自动把网页截图发到微信群里
现在很多公司都在使用企业微信了,不但方便公司内部交流和客户交流,还能组建各种小组群,业务群。企业微信群提供一个机器人的功能,方便我们把公司业务信息,或来自外部的信息自动发布到群里。 这里研究一下如何向微信群…...

Netty实现websocket且实现url传参的两种方式(源码分析)
1、先构建基本的netty框架 再下面的代码中我构建了一个最基本的netty实现websocket的框架,其他个性化部分再自行添加。 Slf4j public class TeacherServer {public void teacherStart(int port) throws InterruptedException {NioEventLoopGroup boss new NioEve…...
深入理解C语言指针:基础概念、语法和实际应用
导言: 在C语言编程中,指针是一个强大而灵活的概念,它直接涉及到内存的操作,为程序员提供了更多的控制权。本文将深入探讨C语言指针的基础概念、语法规则以及实际应用,帮助读者更好地理解和运用这一重要的编程工具。 1…...

百度云加速免费版下线,推荐几款目前仍旧免费的CDN
近日,百度云加速实施了新政策,将不再支持免费套餐服务。现在免费的CDN也越来越少了,推荐几款目前仍旧免费的CDN,大家且用且珍惜! 1、雨云【点此直达】 源站为雨云产品可以免费使用CDN,源站非雨云产品流量包…...

HarmonyOS(五)—— 认识页面和自定义组件生命周期
前言 在前面我们通过如何创建自定义组件一文知道了如何如何自定义组件以及自定义组件的相关注意事项,接下来我们认识一下页面和自定义组件生命周期。 自定义组件和页面的关系 在开始之前,我们先明确自定义组件和页面的关系 自定义组件:Co…...

DevExpress WinForms TreeMap组件,用嵌套矩形可视化复杂分层数据
DevExpress WinForms TreeMap控件允许用户使用嵌套的矩形来可视化复杂的平面或分层数据结构。 DevExpress WinForms有180组件和UI库,能为Windows Forms平台创建具有影响力的业务解决方案。同时能完美构建流畅、美观且易于使用的应用程序,无论是Office风…...

IO口速度影响了什么?
我们在初学单片机的时候都知道单片机GPIO的作用是巨大的,在配置GPIO的时候,结构体初始化里有一个选项是配置输入输出速度的,对于这个速度输出是必须要配置的,输入没有明令说明需不需要配置。 这个速度对于学习过32单片机的都应该知…...

Verilog基础:时序调度中的竞争(一)
相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 作为一个硬件描述语言,Verilog HDL常常需要使用语句描述并行执行的电路,但其实在仿真器的底层,这些并行执行的语句是有先后顺序…...
nginx 配置静态缓存全教程 (以及静态缓存文件没有生成)
一、第一步定义一个缓存目录设置目录结构 在 http 模块下定义(keys_zone 缓存区名:后面是缓存区大小 inactive 不活跃的文件多久清理 max_size 缓存区所占磁盘的上限 use_temp_path 默认关闭(有需要自己百度)) proxy_cache_path /path/your…...

自己动手打包构建编译cri-dockerd
1.背景 本机是 armv7l架构cpu,发现官方文档中竟然没有,因此需要自己编译下; [rootcontainer0 ~]# uname -a Linux container0 5.4.206-v7l.1.el7 #1 SMP Mon Jul 25 14:13:29 UTC 2022 armv7l armv7l armv7l GNU/Linux2.打包/构建/编译 gi…...

Self-Supervised Exploration via Disagreement论文笔记
通过分歧进行自我监督探索 0、问题 使用可微的ri直接去更新动作策略的参数的,那是不是就不需要去计算价值函数或者critic网络了? 1、Motivation 高效的探索是RL中长期存在的问题。以前的大多数方式要么陷入具有随机动力学的环境,要么效率…...

【网络奇幻之旅】那年我与区块链技术的邂逅
🌺个人主页:Dawn黎明开始 🎀系列专栏:网络奇幻之旅 ⭐每日一句:追光的人,终会光芒万丈 📢欢迎大家:关注🔍点赞👍评论📝收藏⭐️ 文章目录 &#…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...