自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 docker安装redis

这个是关键配置,让redis不是无配置启动,而是加载容器内的conf文件,最终加载的是宿主机上的文件。到redis官网下载一下压缩包, http://www.redis.cn/download.html。:把宿主机配置好的redis.conf放到容器内的这个位置中。:把redis持久化的数据在宿主机内显示,做数据备份。:把容器内的6379端口映射到宿主机6666端口。一个是用来放配置文件的,一个是用来放数据文件的。至此就全部安装完毕了,小伙伴们快去试试吧~查看一下镜像已经拉下来了。

2023-08-27 20:23:18 480

原创 一篇文章搞懂MVCC

在 MySQL 中,事务支持是在引擎层实现的。MySQL 是一个支持多引擎的系统,但并不是所有的引擎都支持事务。比如 MySQL 原生的 MyISAM 引擎就不支持事务,这也是 MyISAM 被 InnoDB 取代的重要原因之一。事务有四个特性,ACID,即原子性、一致性、隔离性和持久性。开启事务用。

2023-08-20 18:42:16 131

原创 介绍Sping Boot的5个扩展点

定义了这8个初始化器,那一定是有地方在调它们的,不然怎么会打印出来呢,那具体在什么地方调的,我们在自己的初始化器的地方打断点,看到已经进来了,然后看下方的堆栈信息,这个就是调用的地方。最后我来把扩展点图补充完整,如下所示,很清晰明了,在什么时候调用了什么,我们自己开发的时候结合应用场景,在什么时候要干什么事,就知道要创建什么类型的扩展点了。和初始化器一样,现在我们自定义两个监听器,一个是Starting,一个是Started,括号里面的是泛型,这个是一定要写的,

2023-08-05 12:49:01 205

原创 Nacos Java Api和Namespace介绍

这个是nacos的架构图,https://nacos.io/en-us/docs/architecture.html在1.x的 Nacos 版本中服务端只支持 http 协议,后来为了提升性能在2.x版本引入了谷歌的 grpc,grpc 是一款长连接协议,极大的减少了 http 请求频繁的连接创建和销毁过程,能大幅度提升性能,节约资源。据官方测试,Nacos服务端 grpc 版本,相比 http 版本的性能提升了9倍以上。

2023-04-02 09:26:03 1375 1

原创 从二进制和源码安装Nacos

本文介绍了两种启动nacos的方法,二进制安装是我们项目中实际使用的方式,源码安装是我们学习源码时候的启动方式,大家快动手操作下吧。。。

2023-03-18 22:56:19 413

原创 初识Jenkins

发现标题也成功的改掉了,多了一个1[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4Q9vKRwQ-1661786001648)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5abc903bb011480595063fbe8fe4e243~tplv-k3u1fbpfcp-watermark.image?)]演示圆满成功。............

2022-08-29 23:19:24 323

原创 从Architecture带你认识JVM

JVM就是javavirtualmachine,java虚拟机JVM就是将java源文件编译成字节码文件,然后加载到虚拟机,JVM在执行字节码时,最终把字节码解释成具体平台上的机器指令执行。这个就是一次编写,到处运行。JVM是一种java虚拟机规范,很多厂商进行了实现,可以通过java-version命令查看OracleIBMJ9VMAliTaobaoVMZualZing当然最常见的就是HotSpot了https。...

2022-07-25 21:03:22 342

原创 一条更新SQL语句是如何执行的?

前言在上篇文章《一条查询SQL语句是如何执行的?》 介绍了一些常用组件,一般是经过连接器、分析器、优化器、执行器等功能模块,最后到达存储引擎。本文是介绍一条更新语句如何执行,还会介绍一写其他组件,现在让我们开始吧。Buffer Pool我们知道在执行 sql 对某一行进行操作时,每次对磁盘操作其实是很慢的。为了解决这个问题,我们设置了一个缓冲池。这个缓冲池简单来说就是一块内存区域,这是InnoDB设置的,不是MySQL的服务端设置的。它存在的原因之一是为了避免每次都去访问磁盘,把最常访问的数据放在缓存

2022-05-29 17:29:38 235

原创 实现生产者消费者模式的三种方式

什么是生产者消费者模式简单来说,生产者消费者模式就是缓冲区。那么这么做有两个好处,一个是解耦,第二个是平衡生产能力和消费能力的差,因为生产者和消费者的速度是不一样的,有了这个缓冲区就可以平衡这样一个落差,达到动态平衡。那么这个缓冲区其实就是一个队列,它的规则就是当队列是满的时候,生产者会被阻塞。当队列为空的时候,消费者会被阻塞, 在java中实现生产者消费者模式有多种方式,主要是线程间的通信,这里介绍三种:wait/notify、await/signal和阻塞队列。wait/notifywait

2022-05-23 12:43:58 512

原创 一条查询SQL语句是如何执行的?

总体架构先看下总体架构,有一个全览的概念。连接MySQL服务监听的端口默认是3306,客户端连接的方式也有很多。可以是同步的也可以是异步的,可以是长连接也可以是短连接,可以是TCP连接也可以是Unix Socket,MySQL有专门处理连接的模块,连接的时候需要验证权限。客户端每产生一个连接或者一个会话,在服务端就会创建一个线程来处理。反过来,如果要杀死会话的话,就是kill掉线程。 我们用show processlist看下有哪些连接,kill 的时候就是 kill 下面的 id。如果客户端

2022-05-06 22:07:41 703

原创 腾讯云CentOS 7 Docker安装MySQL 5.7

首先准备一台云服务器安装docker可以参考菜鸟教程curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun启动 Dockersudo systemctl start docker测试一下sudo docker run hello-world没问题了[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VFWxZnQw-1651494244699)(https://p9-juejin

2022-05-02 20:25:09 1774 1

原创 SpingBoot启动原理精讲第二讲

前言上一篇文章 《深度解析SpringBoot以及手写一个 starter》火了之后,由于篇幅的原因讲的不够深,我决定再加更一篇,两篇看下来相信对SpringBoot肯定能够理解了。自动装配就是像事务、配置文件加载和解析、aop、缓存、数据源、springmvc等等,我们以前在项目中要加载这些需要配置xml或者写个@Configuration和很多个@Bean,这些都是需要手写的,现在不需要,只需要引入spring-boot-autoconfigure这个jar包即可,这个就是自动装配的魅力。以前要手

2022-01-23 17:46:50 1071 1

原创 多线程顺序执行的几种写法

前言这是一道常见面试题,我也碰到过,下面介绍的这几种写法也是对并发编程常用工具掌握程度的一个考察,是一道很好的面试题。一共有以下几种写法,下面来分别介绍。join写法(两种写法)线程池写法wait、notify写法Condition写法CountDownLatch写法CyclicBarrier写法Thread.sleep写法CompletableFuture写法join写法join()方法的作用,把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。也就是说,

2022-01-16 23:38:19 2526

原创 异步编程Future掌控未来

Callable有了Runnable,为什么还要Callable?我们先来看下Callable的接口:public interface Callable<V> { /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a re

2021-11-28 21:43:59 600

原创 强引用和弱引用的Threadlocal

从SimpleDateFormat开始首先看一个例子,创建20个线程,线程里就干一件事,就是转换时间public class ThreadLoaclExample { //非线程安全的 private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static Date parse(String strDate) throws ParseExcep

2021-11-21 19:10:53 847

原创 多重校验神器责任链模式

背景最近在做需求,写一个方法,先在前面做验证,if不满足A条件则return,if不满足B条件则return…一共写了5个验证,等验证通过以后才执行下面的逻辑,这个也没问题。过了一阵产品提了需求,跟这个方法类似,我又把这个方法copy了一份,只不过验证条件稍微有点不一样,要变成6个验证了。这时候我就发现有三个问题,第一重复代码,相同的A条件B条件C条件写了两份,没有复用。第二,“头重脚轻”,比如100行的方法,前面60行都是验证,后面40行才是真正有用的业务代码,你看一个方法功能的时候前面验证肯定是不关

2021-09-24 21:20:51 653

原创 老生常谈线程基础的几个问题

实现线程只有一种方式我们知道启动线程至少可以通过以下四种方式:实现 Runnable 接口继承 Thread 类线程池创建线程带返回值的 Callable 创建线程但是看它们的底层就一种方式,就是通过new Thread()实现,其他的只不过在它的上面做了层封装。实现Runnable接口要比继承Thread类的更好:结构上分工更明确,线程本身属性和任务逻辑解耦。某些情况下性能更好,直接把任务交给线程池执行,无需再次new Thread()。可拓展性更好:实现接口可以多个,而继承只能

2021-09-14 20:02:17 288

原创 万丈高楼平地起的建造者模式

定义建造者模式(Builder Pattern)是将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示,属于创建型模式。使用建造者模式对于用户而言只需指定需要建造的类型就可以获得对象,建造过程及细节不需要了解。建造者模式适用于创建对象需要很多步骤,但是步骤的顺序不一定固定。如果一个对象有非常复杂的内部结构(很多属性),可以将复杂对象的创建和使用进行分离。组装电脑一般建造者模式是搭配着链式编程一起写的,所以这里不介绍传统的写法,直接介绍链式写法。这里以组装电脑为例,新建一个Co

2021-09-11 21:22:33 116

原创 手写JdbcTemplate的模板方法模式

模板方法模式模板方法模式(Template Method Pattern)又叫模板模式,是指定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤,属于行为型设计模式。模板方法模式实际上是封装了一个固定流程,该流程由几个步骤组成,具体步骤可以由子类进行不同的实现,从而让固定的流程产生不同的结果。模板方法的本质就是抽象封装流程,然后进行类的继承实现。通用UML类图举例说明我们平时在家自己做饭, (1)买菜,(2)洗菜, (3)做菜,(4)吃

2021-09-06 22:44:16 525

原创 ReentrantLock介绍及AQS源码精讲

LockLock是J.U.C中最核心的工具,它的作用和前面所讲解的synchronized一样,也是用来解决多线程环境下的线程安全性问题。在J.U.C这个包中,很多的地方都有用到Lock这个机制。J.U.C全称是java.util.concurrent,是并发编程中比较常用的工具包,这个包中包含很多用来在并发场景中使用的组件,比如线程池、阻塞队列、计时器、同步器、并发集合等等。并发包的作者是大名鼎鼎的Doug Lea。在Lock接口出现之前,Java中的应用程序对于多线程的并发安全处理只能基于sy

2021-09-04 21:16:11 141

原创 ConcurrentHashMap源码精讲

哈希表哈希表也叫散列表,这种数据结构提供了键(Key)和值(Value)的映射关系。只要给出一个key,就可以高效查找到它所匹配的value,时间复杂度接近于O(1)。如下所示:1.7和1.8的区别主要是两方面的,一方面是1.7里加锁用的是segment分段锁,锁的粒度较大。1.8里面用的是synchronized+CAS来实现的,锁的粒度也从分段锁缩小为节点锁。第二个是数据结构的层面,1.7里面是数组+链表,1.8里面是数组+链表+红黑树,时间复杂度O(n) -> O(logn)。 如下所

2021-08-26 22:21:48 156

原创 elasticsearch7.x集群搭建及倒排索引脑裂问题精讲

简介大家好,我是jackxu,es大家都听过,现在也是越来越火了,用到的公司越来越多。中文官网:https://www.elastic.co/cn/ 。es的特点:可拓展性:大型分布式集群(数百台服务器)技术,处理PB级数据,es自动可以将海量数据分散到多台服务器上去存储和检索,进行并行查询,提高搜索效率。相对的,Lucene是单机应用。技术整合:将全文检索、数据分析、分布式相关技术整合在一起:lucene(全文检索),商用的数据分析软件(BI软件),分布式数据库(mycat)部署简单:开箱即用

2021-04-18 11:35:39 871

原创 RocketMQ扫盲贴及Java API使用精讲

大家好,在上篇文章《高可用架构及二主二从异步集群部署》中介绍了的 RocketMQ 的历史及安装,为本文开始做实验打下了基础,接下来就正式开始讲解RocketMQ的概念以及Java API的操作使用。RocketMQ的架构这是在RocketMQ官网的架构图,http://rocketmq.apache.org/docs/rmq-arc/一般见到的架构图都是这样的,其中这些重要的角色需要解释下。BrokerRocketMQ 的服务,或者说一个进程,叫做 Broker,Broker 的作用是存储

2021-03-20 21:25:50 370

原创 帮我们找房租房买房的代理模式

前言大家好,看到这个标题大家应该想到了是中介,中介可以帮我们租房找房买房办手续等等,让我们在整个租房买房过程中轻松很多。生活中还有售票黄牛、婚介、经纪人、快递、事务代理、非侵入式日志监听等,都是代理模式的实际体现。代理模式(Proxy Pattern)是指为其他对象提供一种代理,以控制对这个对象的访问,属于结构型模式。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用。通用UML类图:使用代理模式主要有两个目的:一是保护目标对象,二是增强目标

2021-03-12 22:02:47 221

原创 手抓饼加生菜加鸡蛋的装饰器模式

装饰器模式装饰器模式(Decorator Patter),也称为包装模式(Wrapper Pattern)是指在不改变原有对象的基础之上,将功能附加在对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式。装饰器模式的核心是功能扩展。使用装饰器可以透明且动态地扩展类的功能。下面是通用的UML类图:生活中的应用场景看完上面的概念以及类图可能比较抽象,接下来我会举一个生活中的场景,来通俗易懂的讲解装饰器模式。我们在早上上班途中,往往会在公司门口买一个手抓饼,然后带到工位上慢慢

2021-02-24 22:10:44 281

原创 RocketMQ高可用架构及二主二从异步集群部署

RocketMQ发展历史RocketMQ是一个由阿里巴巴开源的消息中间件, 2012年开源,2017年成为apache顶级项目。RocketMQ在阿里内部应用是非常广泛的,阿里内部的几千个应用都运行在RocketMQ之上,双十一期间需要处理亿万级别的消息,TPS可以达到几十万。目前支持Java、C/C++,Python、Go四种语言访问。RocketMQ现在有两个版本,一个是社区开源版,一个是商业的云服务版(AliwareMQ)。最新版本:4.8.0(本文演示版本)。它的核心设计借鉴了Kafka,所以

2021-02-15 22:43:11 616 2

原创 xxl-job详细使用指南

新建任务说明本篇文章承接上文《xxl-job快速入门指南》,上一次和大家简单介绍了下 xxl-job 的由来以及使用方法,本篇文章将会详细介绍一些高级使用方法及特性。上文中我们在新建一个任务的时候发现有很多的选项,现在我们来详细聊一聊他们的作用。路由策略路由策略是指一个任务可以由多个执行器完成,那具体由哪一个完成呢,这就要看我们指定的路由策略了,这个参数当执行器做集群部署的时候才有意义。Quartz中只能随机负载那么这里的第一个,最后一个是按什么顺序来的呢,就是点击查看-注册节点中的1,2

2021-02-02 13:10:04 22715 2

原创 xxl-job快速入门指南

前言大家好,我是 jack xu,今天和大家分享一下 xxl-job,xxl 是许雪里大神名字的首字母缩写,他是大众点评的程序员,也是利用业余时间创作的一个开源的任务调度系统。除了 xxl-job 之外,作者还开源了许多其他组件,现在一共有11个开源项目,组成了 xxl 家族。到目前为止在 xxl-job 官网上登记使用的公司有几百家,其实很多都没有登记,所以真正在使用的远不止这几百家,最新发布版本是:2.2.0。Quartz的不足在介绍 xxl-job 之前先介绍一下 Quartz,Quartz 有

2021-01-30 19:13:15 7321 1

原创 java核心基础之自定义注解

认识注解注解( Annotation )相当于一种标记,在程序中加入注解就等于为程序打上某种标记,没有加,则等于没有任何标记,以后,javac编译器、开发工具和其他程序可以通过反射来了解你的类及各种元素上有无何种标记,看你的程序有什么标记,就去干相应的事,标记可以加在包、类,属性、方法,方法的参数以及局部变量上。作用分类:1、编写文档:通过代码里标识的注解生成文档【生成文档doc文档】2、代码分析:通过代码里标识的注解对代码进行分析【使用反射】3、编译检查:通过代码里标识的注解让编译器能够实现基本

2021-01-13 11:49:07 134

原创 java核心基础之泛型

为什么要使用泛型大家好,我是 jack xu,今天给大家讲的是 java 核心基础的第二篇,泛型,这个东西熟悉又陌生,熟悉是相信大家每天都在用,List< Long>这个就是泛型,陌生是泛型还有一些其他偏门冷门的知识,今天给大家查漏补缺一下。不喜勿喷,高手也可以略过,先看下面一段代码:这段代码把 Integer 和 String 类型的数据都塞进去,然后打印出来,list 默认是可以存放任意类型的数据,代码是没毛病的,运行一下报错了,Integer 不能转成 String 类型的,为了

2020-11-14 22:41:09 159

原创 java核心基础之反射

前言大家好,我是 jack xu,今天跟大家介绍核心基础里面的反射,反射这个东西你说它重要也重要,不重要也不重要。重要是当你看一些框架的源码时候,里面会用到反射的代码,你不会是看不懂的。不重要是因为我们平时的工作中绝大多数都是在写业务代码,真正操作类的场景很少。这个跟英语一样,不会不影响你的生活,但是当你往上层高层走的时候,不会会制约你的发展。应用我把我在工作中用的场景给大家举下例子,加强一下大家学习的信心。一个是我在写 openapi 时候,做一个切面的拦截,获取请求参数,代码如下另一个是我在写

2020-10-31 20:01:19 167 1

原创 教你三分钟用docker compose搭建一个自己的个人博客网站

hi,大家好,我是 jack xu,今天和大家聊一个轻松、好玩、易懂的话题,就是教大家搭建一个自己的个人博客网站,可以在同事朋友面前炫耀一把。事情的缘由是我们公司有个同事,有一天他给了我一个网站,我打开一看,上面是一个 jenkins 的页面,我问他这个你是怎么搞的,他说他有一块树莓派,然后在上面搞着玩,装了个 jenkins,我说你这样子搞就浪费了,装个 jenkins 也没什么用,不如装个个人博客网站,这样你的树莓派也不浪费,别人也能通过你的域名来访问,你也可以发一些文章上去,这样岂不是妙哉。小伙伴听

2020-06-20 18:51:37 5253

原创 介绍几种常见的分布式锁写法

什么是分布式锁?大家好,我是jack xu,今天跟大家聊一聊分布式锁。首先说下什么是分布式锁,当我们在进行下订单减库存,抢票,选课,抢红包这些业务场景时,如果在此处没有锁的控制,会导致很严重的问题。学过多线程的小伙们知道,为了防止多个线程同时执行同一段代码,我们可以用 synchronized 关键字或 JUC 里面的 ReentrantLock 类来控制,但是目前几乎任何一个系统都是部署多台机器的,单机部署的应用很少,synchronized 和 ReentrantLock 发挥不出任何作用,此时就需要

2020-06-14 12:59:59 489

原创 你真的会用@Transactional吗?

小伙伴大家好,我是 jack xu,今天跟大家讲一讲 @Transactional,这个注解相信大家应该都用过,它能保证方法内多个数据库操作要么同时成功、要么同时失败。使用 @Transactional 注解时需要注意许多的细节,虽然它看起来简单,但不知道底层原理的话,用起来往往达不到我们想要的效果。事务分为编程式事务和声明式事务两种。编程式事务指在代码中手动的管理事务的提交、回滚等操作,代码侵入性比较强。声明式事务是基于 AOP 面向切面的,它将具体业务与事务处理部分解耦,代码侵入性很低,声明式事务也有

2020-06-02 20:40:17 2760 3

原创 深度解析 Spring Boot 以及手写一个 starter

什么是 Spring BootSpring Boot 基本上是 Spring 框架的扩展,它消除了设置 Spring 应用程序所需的复杂例行配置。我们在使用 Spring 框架的时候,我们接触得比较多的应该是 Spring MVC、 IOC 、 DI 、AOP 等等,而这些框架在使用的过程中会需要配置大量的 XML,或者需要做很多繁琐的配置。Spring Boot 可以帮助我们快速搭建一个基于 Spirng 框架以及 Spring 生态体系的应用解决方案。我们对着官网来翻译一下:创建独立的 Spr

2020-05-23 21:36:21 565

原创 从b+ tree底层分析索引以及优化

什么是索引数据库索引,是数据库管理系统(DBMS)中一个排序的数据结构,以协助快速查询、更新数据库表中数据。大家看下上面的图就很清晰明了了,索引就是查字典嘛,比如说我要去字典里面找个帅字,你肯定不会从头找到尾,一页一页翻吧,你肯定是先去目录,通过拼音或者偏旁找到帅字在第几页,然后在去对应的页查看。索引类型以及创建索引不管网上是怎么分类的,我这里把索引分为四类,我们打开navicat,选中一张表右击设计表,然后点索引,打开索引类型的下拉,一共有FULLTEXT、NORMAL、SPATIAL、UNIQ

2020-05-17 14:55:43 1158

原创 咱们从头到尾再说一次GC垃圾回收

小伙伴好,我是 jack xu。我们知道 JVM 调优主要调的是垃圾收集器的选择和参数的设置,所以我们对垃圾回收的知识必须要掌握了解,不然怎么调优呢,那么什么是垃圾呢,我们类比生活中的垃圾,就是不要的东西,需要清除的东西,那么第一步就是要找到垃圾,在Java中我们有两种方式。怎么定义垃圾引用计数法给对象中添加一个引用计数器,每当有一个地方引用他时,计数器值就+1。当引用失效时,计数器值就-1...

2020-05-05 09:30:55 476

原创 深入探究volatile和JMM内存模型

小伙们大家好,本篇是并发编程的第三篇,上一节跟大家讲了synchronized,这一节我们来聊聊他的好兄弟volatile,volatile的功能稍微差一点,他只有可见性和有序性,那么他的底层是如何保障可见性和有序性,以及什么是Java内存模型,本篇文章将给出通俗易懂的解释。。可见性什么是可见性先来看一段代码/** * @author jack xu */public class V...

2020-05-03 16:25:35 240

原创 一个经典面试题:如何保证缓存与数据库的双写一致性?

缓存是互联网高并发系统里常用的组件,由于多增加了一层,如果没有正确的使用效果可能适得其反,诸如“缓存是删除还是更新?”,“先操作数据库还是先操作缓存?”都是些老生常谈的话题,今天我们就来聊一聊缓存与数据库的双写一致性的解决方案。Cache Aside Pattern在一开始先科普下最经典的缓存+数据库读写的模式,就是 Cache Aside Pattern。读的时候,先读缓存,缓存没有的话...

2020-04-26 21:30:58 491

原创 简单的单例模式其实不简单

小伙们好,我是jack xu,今天跟大家讲一个老生常谈的话题,单例模式是最常用到的设计模式之一,熟悉设计模式的朋友对单例模式都不会陌生。网上的文章也很多,但是参差不齐,良莠不齐,要么说的不到点子上,要么写的不完整,我试图写一篇史上最全单例模式,让你看一篇文章就够了。。单例模式定义及应用场景单例模式是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。单例模式是创建型模式。许多时候...

2020-04-25 14:30:22 232

空空如也

空空如也

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

TA关注的人

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