自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(45)
  • 收藏
  • 关注

原创 吃透计算机网络(三)

安全通信特性:机密性:仅发送方和接收方能够理解传输报文的内容,这要求报文在一定程度上进行加密。报文完整性:确保通信内容在传播中未被改变(恶意篡改或者意外改动)端点鉴别:发送方和接收方都能证实通信过程所涉及的另一方,确保通信的另一方具有所声称的身份。运行安全性:保护服务器和网路的正常运行,防止对网络的攻击个人理解,安全通信的核心就是防止破坏,发送方和接收方无法阻止第三方得到报文段,底层网路是互通的,只能在传输的数据包上下文章。第三方可能在任何时候进行破坏,机密性是防止报文被其他人截获,从而知道双方的

2022-01-06 20:35:49 3855

原创 吃透synchronized关键字

Java中的锁分为显示锁和隐式锁。

2021-11-22 21:28:45 2367 1

原创 吃透Java内存模型

首先强调,Java内存模型和Java运行时数据区的别搞混了。Java内存模型不是介绍内存是怎么分配的,它是一系列的规定来保证程序能更好的执行的。Java运行时数据区才是将内存分成了哪些部分,各部分分别放的是社么。...

2021-11-15 21:56:59 1732 4

原创 手撕单例模型

面试的时候经常会碰到的一些手撕题目,平时不写面试面试根本没思路。常见的主要有手撕单利、手撕生产者消费者、多个线程轮流打印等等。单例模型单例模型涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。单例模型特点:1、单例类只能有一个实例。2、单例类必须自己创建自己的唯一实例。3、单例类必须给所有其他对象提供这一实例单例模式的关键点:构造方法不对外开放,为private确保单例类只有一个对象,尤其是

2022-04-19 11:07:36 471

原创 Redis缓存穿透、击穿、雪崩、更新

正常状态下Redis做缓存时,请求会先落在Redis上,假设Redis中不存在或者缓存失效,则去数据库中进行查找,找到就更新缓存返回请求,找不到就返回空。缓存穿透上述时正常执行时,但是如果请求的数据根本不存在,即数据库中没有,Redis中肯定也不会缓存,Redis缓存对于这种请求相当于透明的(肯定不会起作用),最终请求会落在数据库上,查询的结果肯定为空,这就叫缓存穿透。当大量的这种请求落在数据库上,就可能会导致数据库的宕机,数据永远不存咋,请求永远落在数据库上。解决方法:1.请求数据不存在,也将

2022-04-13 10:23:45 325

原创 MySQL之Innodb

InnoDB体系架构:InnoDB存储引擎有多个内存块,这些内存块组成了一个大的内存池,负责1.维护所有的进程、线程访问的多个内部数据结构2.缓存磁盘上的数据,方便快速的读取,同时在对磁盘文件的数据修改之前在此处缓存3.重做日志缓存后台线程后台线程的主要作用是负责刷新缓存池中的数据,保证缓存池中的内存缓存是最近的数据,同时将脏页刷回磁盘。1.Master ThreadMaster Thread顾名思义是非常核心的线程,主要负责将缓存池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新

2022-03-05 21:58:14 3905

原创 MySQL的整体框架

MySQL由以下几部分组成:连接池组件管理服务和工具组件SQL接口组件查询分析器组件优化器组件缓冲组件插入式存储引擎物理文件MySQL大致分为Server和存储引擎层:Server层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖MySQL的大多数核心服务 功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在 这一层实现,比如存储过程、触发器、视图等。而存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持InnoDB、MyISAM、 Memo

2022-03-04 16:29:37 5956

原创 Redis总结

数据结构Redis中有简单动态字符串SDS、双端链表、字典、跳跃表、整数集合和压缩列表6种数据结构。简单动态字符串SDSRedis是使用C语言的,但是C语言中的字符串只会作为字符串字面量出现在一些无需对字符串进行修改的地方。而可能出现修改时,Redis使用SDS来实现。每个sds.h/sdshdr结构表示一个SDS值,SDS保存字符串同样以‘\0’结尾,但是这个结尾不计入长度。SDS和C字符串的区别...

2022-03-01 16:16:27 101

原创 排序算法总结

以下所有的排序全部是正序。选择排序首先找到数组中最小的一个数,然后将该值和第一个元素交换。如果最小的数就是第一个元素本身,自己和自己交换。再剩下的元素中找到第二小的数,和第二个元素交换,如此反复,直到整个数组排序。选择排序就是不断地选择最值。时间复杂度: O(N^2)空间复杂度 :O(1)选择排序运行时间和输入数组无关。不论输入的数组是否有序,选择排序所耗费的时间是固定的。因为每次选择最小值并不能为下一轮选择最值提供什么有用的信息。‘选择排序的数据移动最少。选择排序只需要O(N)次的交换数据

2022-02-24 22:04:22 119

原创 吃透计算机网络(四)

网络层能够被分为两个相互作用的部分:数据平面和控制平面数据平面:即网络中每台路由器的功能,该数据平面决定到达路由器输入链路之一的数据报如何转发到路由器的输出链路之一。控制平台:即网络范围的逻辑,该控制平面能控制数据报沿着源主机到目的主机到端到端路径中路由器之间的路由方式。数据平面的主要作用是从其输入链路向其输出链路转发数据报,控制平面的主要作用是协调这些本地的路由转发动作,使得数据报沿着源和目的之间的路由路劲最终进行端到端传送。网络层的主要功能有两个:转发和路由选择转发:当一个分组到达路由器的一条

2022-02-23 20:31:20 1396

原创 吃透计算机网络(五)

链路层链路层提供的服务成帧:每个网络层数据报在经链路传输之前,链路层协议都会将其用链路层帧封装起来。链路接入:媒体访问控制协议MAC规定了帧在链路上传输的规则。MAC可以控制点对点的链路传播和链路广播可靠交付:当链路层提供可靠交付时,它保证无差错的移动网络层数据报。(以太网并不提供)差错检测和纠正:运输层和网络层也提供有限形式的差错检测,即因特网检验和。链路层的差错检测通常更加复杂,它用硬件时间,可以支持复杂的检测和更快的速度。而运输层和网络层都是软件实现,检测比较简单且速度慢。差错纠正类似与差错

2022-02-20 22:14:50 1290

原创 吃透计算机网络(二)

运输层协议为运输在不同主机上的进程提供了逻辑通信功能。进程通过运输层的逻辑通信彼此发送报文,无须考虑承载报文的基础细节。运输层协议实在端系统中而不是在路由器中实现的。运输层实现了不同主机上进程之间的逻辑通信,网络层提供了主机之间的逻辑通信。运输层依靠网络层(即IP),IP的服务模型是尽力而为。IP尽可能保证通信在主机之间的交付,但不做保证。即不保证报文段的交付、完整性和顺序。运输层想要保证可靠逻辑通信,必须在网络层之上多做些工作。TCP使用流量控制、序号、定时器和确认等保证正确按序的交付报文,而UDP不保

2022-01-04 19:46:09 1237

原创 吃透计算机网络(一)

强烈推荐《计算机网络-自顶向下方法》这本书,由浅入深的讲解计算机网络的基础知识。本系列为对此书的学习总结。计算机网络模型在两个不同端系统上的进程,通过跨越计算机网络的交换报文而相互通信。网络应用程序由成对的进程组成,这些进程通过网络相互发送报文。在一对进程之间的通信会话场景中,发起通信的进程被标识为客户端,而会话开始时等待连接的进程是服务器。应用层网络的核心设备并不在应用层上起作用,而仅在较低层起作用。特别是在网络及下面层次起作用。应用层级接口体系客户-服务器体系结构有一个总是打开的主机服务器

2022-01-01 21:22:13 1437

原创 Java集合体系

任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。Java的集合体系由最上层的接口、中间的一些抽象类、以及最后各种具体的实现类组成。Java集合的基本接口是Collection接口和Map接口。Java中经常使用的语法糖"for each"循环可以与任何实现了Iterable接口的对象一起工作。Iterable借口包含了Iterator接口,这就是常用的迭代器,其中包含hasNext()、next()、remove()、forEachRemaining(Consumer)4

2021-12-15 17:56:07 2509 1

原创 Java中的Iterator接口实现

Iterator是Java中常用的接口,在Iterable接口中有一个iterator()方法,它返回一个Iterator对象。集合框架中的迭代器就是来源与此。Iterator()的功能简单,只能单向移动:1.调用iterator()方法返回一个Iterator对象。2.第一次调用Iterator的next()方法,返回序列的第一个元素。此后每调用一个next(),会返回序列的下一个元素。调用next()方法前最好先调用hasNext()方法,判断序列后面是否还有元素。3.remove()删除上次n

2021-12-13 17:48:38 1305

原创 吃透Java异常体系

Java的异常都是派生于Throwable类的一个实例,所有的异常都是由Throwable继承而来的。Throwable有分为了Error类和Exception类。Error(错误)Error 类层次结构描述了 Java 运行时系统的内部错误和资源耗尽错误。Error表示比较严重的问题,一般是JVM运行时出现了错误,如没有内存可分配抛出OOM错误、栈资源耗尽抛出StackOverflowError错误、Java虚拟机运行错误Virtual MachineError、类定义错误NoClassDefFoun

2021-12-08 22:05:19 539

原创 Java中的equals()和hashCode()

Java中有这么句话,如果重写了equals(),那么必须重写hashcode()。那么为啥要这么干呢?他俩到底是啥关系?怎样重写都行吗?今天来撸一撸经常用到的equals和hashcode()Object 类Object类是Java中最顶层的类,所有的类都继承自它。Object类中方法有:1.clone方法 默认实现浅拷贝2.getClass 方法 获得运行时类3.toString 方法 将对象转化为字符串4.finalize 方法 用于释放类所持有的资源 GC时才会调用5.equals 方

2021-12-06 17:09:02 577

原创 反向理解synchronized锁升级

在总结前文吃透synchronized关键字中,锁升级介绍是由低到高,一步一步的出发。其实也可以反其道而行之,想想怎么锁降级,这样能更好的理解锁升级的思路。原先synchronized关键字就是现在的重量级锁,不论遇到何种情况都是重量级锁,需要内核态和用户态之间的相互切换。在JDK1.6之后引入了锁升级,分为无锁-偏向锁-轻量级锁-重量级锁。从开发人员角度想,为啥要这么做呢?无锁状态和重量级锁肯定好理解,一个最轻,一个最重。记住无论何时何地,只要出现两个线程一直争夺同一个锁,必然是用重量级锁。不管原先是

2021-11-24 21:57:16 325

原创 volatile关键字是怎样实现的

理解volatile关键字可以分为两块,一块是它到底是怎么实现功能的,另一部分就是Java内存模型中volatile的内存语义。前者是变量加上volatile之后,处理器和编译器会怎样的处理,后者是在整个Java程序中,添加了volatile之后,编译器会保证volatile这一块不会被重排序。点击查看Java内存模型Java语言对volatile的定义:Java 编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。volatile又被称为轻量级的s

2021-11-19 17:29:34 577 1

原创 Java后端编译优化

虚拟机最开始是通过解释器进行解释执行的,解释器是最基础的,但是没有优化,效率和速度都有待提高。但是只依靠解释器不进行优化也是可以的。即时编译器和提前编译器都是采取的优化措施,是可选择的。即时编译器:当虚拟机发现某个方法或代码块的运行特别频繁,就会把这些代码认 定为“热点代码”(Hot Spot Code),为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代 码编译成本地机器码,并以各种手段尽可能地进行代码优化,运行时完成这个任务的后端编译器被称 为即时编译器提前编译器:解释器与编译器主流的虚拟

2021-11-11 17:54:07 674

原创 Java前段编译优化

前段编译器:把*.java文件转变成*.class文件的过程(代表:JDK的Javac)即时编译器(JIT编译器):运行期把字节码转变成本地机器码的过程(代表:HotSpot虚拟机的C1、C2编译器)提前编译器:直接把程序编译成与目标机器指令集相关的二进制代码的过程(代表:JDK的Jaotc、Excelsior JET)Java中即时编译器在运行期的优 化过程,支撑了程序执行效率的不断提升;而前端编译器在编译期的优化过程,则是支撑着程序员的 编码效率和语言使用者的幸福感的提高。Javac编译器Ja

2021-11-09 21:00:35 126

原创 JVM虚拟机方法调用和选择

虚拟机是JVM最核心的组成部分之一。物理机和虚拟机的区别二者都有代码执行的能力物理机的执行引擎是建立在处理器、硬件、指令集和操作系统层面上的。虚拟机的执行引擎是自己实现的,可以自行指定指令集与执行引擎结构体(包括不被硬件支持的指令集格式)JVM执行引擎概念模型, 就是一个理论模型:执行引擎输入的是字节码,处理过程是字节码解析的等效过程,输出的是执行结果。所有JVM执行引擎都是这个模式,但是不同的JVM可以选择不同的执行过程,也就处理过程可以不同,可选择解释执行、编译执行、解释+编译二者兼备。**

2021-11-08 21:28:26 407

原创 Java类加载机制

类加载机制:类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最 终形成可以被虚拟机直接使用的Java类型。类的生命周期:一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载 (Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化 (Initialization)、使用(Using)和卸载(Unloading)七个阶段,其中验证、准备、解析三个部分统称 为连接(Linking)。其中解

2021-11-05 22:10:44 679

原创 Class类文件结构

计算机只能执行机器码,而机器码是一系列0和1的组合。直接编写机器码肯定不行,为了简化开发就有了汇编语言,由汇编语言翻译成机器码。汇编开发也复杂,就有了C语言,由C语言翻译成汇编语言。后来就由C写出了Java。在各种IDE平台上写的程序都是.java文件,经过编译器编译为.class文件,然后JVM拿到这些.class文件经过解释器生成可执行的机器码。各种不同平台的虚拟机和所有平台都统一使用的程序存储格式—字节码,是构成平台无关性的基石。.class文件就是存储字节码的,不同平台产生的Class格式是统一的。

2021-11-03 22:27:58 124

原创 JVM的内存分配策略

内存的分配与内存的回收一样,都是为了减少GC时间而服务的。总体来说内存的分配是在堆上进行(但是也可能经过JTI编译后被拆分标量类型在栈上分配),优先在Eden区里分配。如果启动本地线程分配缓冲,按线程优先在TLAB上分配。1.对象优先在Eden区分配绝大多数对象的生存时间很短,所以将对象先分配在Eden区,等到Eden区满了之后进行Young GC,GC时Eden区存活的对象和From区的存活对象进入To区。如果To区放不下,就要放到老年代里。怎样判断老年代能不能放下呢?就是下文的空间分配担保。优先在

2021-11-02 17:17:30 546

原创 JVM的各种垃圾收集器

新生代Serial收集器 (复制算法)新生代收集器,Serial英文连续串行,这个收集器是单线程的收集器。它的“单线程”不仅仅是只会使用一个CPU或者一条线程完成垃圾收集工作,更重要的是它在进行垃圾收集时,其他工作线程必须暂停,直至收集结束。优点就是简单高效,对于只有单个CPU的环境来说,没有线程交互的开销,专心做垃圾收集效率最好。缺点时收集时其他线程需要暂停,如果暂停时间不长还可以接受,太长的话影响程序的效率,而且如果有多个CPU的话只使用一个就浪费资源,速度慢。ParNew收集器(复制算法)新生

2021-10-30 22:25:38 132

原创 JVM的安全点

HotSpot是目前使用最广泛的JVM。它在实现各种垃圾收集算法时,在具体实现上做了一点小优化。在可达性分析法中,可以作为GCRoots节点的有四种(虚拟机栈中的引用对象、本地方法栈的引用对象、方法区的静态属性引用变量、方法区的常量引用对象),但是这些内容很大(方法区有时候就有数百M),要想检查完所有符合要求的对象,必定很费时间。另外可达性分析应当是对某瞬间的程序快照进行的,不然一边进行可达性分析,一边程序运行,最后出的结果肯定是牛头不对马尾。这个时间点导致GC进行时必须停顿所有Java执行的线程。目前

2021-10-29 22:23:23 926 1

原创 JVM中的垃圾回收器算法

各种各样的垃圾回收器,总体的回收算法有三种:标记-清除:首先标记出所有需要回收的对象,在标记完成之后统一回收所有被标记的对象。这个算法是所有回收算法的基础,下面的算法都是在这个基础上的改进。标记-清除有两个缺点:1.标记和清除分两个阶段,但是这两阶段的效率都不是很高。2、容易产生大量的内存‘碎片’。标记-清除的位置是不确定的,而新建对象需要的内存应该是在一块的。假设需要新建一个对象内存为10,而现在却有100段不连续的容量为1的空间。虽然可用空间为100,但是却连10的对象都无法新建,这种情况下不得不再次

2021-10-28 22:25:34 57

原创 JVM的垃圾回收

看了周志明的《深入理解Java虚拟机》,重新理解了JVM的垃圾回收机制。建议没看过原书的先去读一下原书,一在网上看各种博文大多数都是从那本书中出来的,而且很多都只是截取了一部分,并不能很好的表达JVM的意思。我原先就是背八股,背的云里雾里的,这次看过原文豁然开朗。强烈安利~~~首先要理解JVM的内存划分:方法区、程序计数器、虚拟机栈、本地方法栈、堆。垃圾回收主要是指的堆的回收,但是也包括方法区。只不过方法区内垃圾回收的效率和结果不尽如人意,堆中垃圾回收一次可以收回70%—95%,而方法区远远达不到这个。

2021-10-27 19:34:46 76

原创 Java中线程安全的类

上次面试的时候,面试官说Java集合中有四个线程安全的类,你知道那几个吗?随口说了Vector、Hashtable、ConcurrentHashMap。但是内心的蒙的,Java中线程安全的类海了去了,为啥只有4个呢?查资料,大多数说的都是在jdk1.1中出了4个线程安装的类,在1.2之后出的都是非线程安全的累。4个线程安全的类分别是:Vector、Hashtable、stack、enumeration。但这种说法个人认为是不对的,Java中的线程安全的类有非常多。而且上述4个类像stack被Deque替

2021-10-25 22:14:01 1105

原创 初识RocketMQ(1)

RocketMQ 消息中间件,原先是阿里内部使用,后来捐赠给Apache基金,成为顶级的开源项目之一。经历过多次的双十一洗礼和考验,性能可靠,最高单台7万TPS。用Java开发,相比较其他的消息中间件(RqbbitMQ 用Erlong语言、Kfka用Scala语言)更容易找到技术人员进行定制开发,也能更好的理解RocketMQ系统运行,毕竟源码看起来顺手一点。理解RocketMQ可以类比为寄信:需要寄信人投递到邮箱,然后邮局送到另一个邮箱,收信的人在另一端取信,还有以一个全国的邮政系统,用来管理各地的邮

2021-10-08 17:46:19 111

原创 跨域(四)CROS跨域过程

第一步 浏览器:首先,浏览器访问网址的时候会判断跟当前的网页是否是同源(协议-域名-端口),如果判断是不是同源,就会携带Origin头。非同源,会判断是否简单请求,简单请求就会直接发送,非简单请求会先进行一次预检,预检成功才发送真实的请求。判断同源及是否简单请点非简单请求预检:在HTTP里就是OPTIONS请求方式,不会包含主体,主要将一些凭证授权的辅助信息放在请求头里交给服务器。除了携带Cookie,还会携带Access-Control-Request-Method和Access-Control-Re

2021-10-05 20:37:44 400

原创 跨越(三)CORS中的Cookie

之前遇到过一个跨域的问题,在服务端配置Access-Control-Allow-Origin和Access-Control-Allow-Credentials,并且前端设置withCredentials 为true。同样的程序在本地计算机运行正常,但是将程序部署到服务器上异常。排查发现是因为浏览器默认不发送Cookie,导致虽然服务器set-cookie,并且前段保存这个cookie,但是在随后的请求中并没有将此cookie携带,服务端没收到cookie,一直认为是新登录,不停的转到登录界面。但是为社么本

2021-10-04 20:03:04 355

原创 接口引用

啃某项目代码的时候,发现接口也被引用到了类内部。具体如下:public interface CommonError { public int getErrCode(); public String getErrMsg(); public CommonError setErrMsg(String errMsg);}public class BusinessException extends Exception implements CommonError{ priv

2021-10-03 17:44:31 578 1

原创 巨坑的Redis远程连接

程序远程连接Redis时报错,显示:Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to XXX.XXX.XXXX.XXX:6379 at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:56) ~[lettuce-core-5.0.5.RELEASE.jar:na] at io.lettuce.cor

2021-09-29 11:59:03 504

原创 浏览器不发送Cookie

前几天写了个小项目,本地跑的好好的,部署到服务器上也正常。最近在服务器上跑,出幺蛾子了。程序突然报错,本应该从httpServletRequest.getSession()中写入和读出的,但是却读不出,结果为null。...

2021-09-16 11:34:15 1145

原创 跨域(二)CORS

CORS跨域是目前使用最多的跨域解决方案,是W3C的一种技术规范,2014年起成为行业的标准,当前所有的浏览器都支持CORS。属于HTTP的一部分。CORS(Cross-origin resource sharing):跨域资源共享。要实现CORS需要前后端同时的支持,而浏览器自动给支持CORS,所以设置主要是服务器端。浏览器将CORS请求分为两种:简单请求和非简单请求。简单请求(同时满足两大条件):(1)请求方法是以下三种之一:HEADGETPOST(2)Http的头信息不超出以下几种字段

2021-09-14 16:10:16 1048

原创 跨域(一)

跨域只是针对浏览器和服务器之间,服务器和服务器之间是不存在跨域需求。为啥只有浏览器和服务器之间需要呢?CORS(Cross-origin resource sharing)跨域资源共享。实现CORS跨域,需要浏览器和服务器同时支持。而浏览器默认都是支持CORS跨域的,所以设置变成了服务器端的事。Origin是社么呢?介绍一些为啥要设置同源策略呢?这是为了防止隔离不同用户,一个浏览器所获取的资源(数据)可以来自不同服务器,假设用户刚刚登录网站A,然后又去登录网站B,如果不设限制,网站B可以拿网站A的用户

2021-09-13 21:16:51 103

原创 IDEA切换JDK版本

在使用import sun.misc.BASE64Encoder时程序报错,查询发现在Java8之后改包被 import org.apache.commons.codec.binary.Base64替换,而自己使用的是Java9。两种解决方案,切换回Java8或者使用新的包。考虑到Java8仍是目前的主流,为了以后的简便,选择使用JDK8。IDEA可以导入多个版本的JDK,可以为不同的工程设置不同的JDK。点击右上角 file->project structure->SDKS->绿色加号

2020-11-12 17:48:28 1613

原创 用Python进行人脸识别(六)

用python进行人脸识别(六)前文讲述了Opencv的基本用法和face_recognition进行人脸识别。这篇文章介绍一下Pyqt5,并用pyqt5进行简单的界面设计。PyQt5是由Riverbank Computing开发的一套绑定Qt5的应用程序框架,支持Pythono2.x和Python3.x版本。Qt 是一个跨平台应用程序和 UI 开发框架,使用 Qt 只需一次性开发应用程序,无...

2019-06-11 20:05:15 1186 2

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除