- 博客(1081)
- 收藏
- 关注
原创 Redis:IO多路复用深度解析
多路复用快的原因在于,操作系统提供了这样的系统调用,使得原来的 while 循环里多次系统调用,变成了一次系统调用 + 内核层遍历这些文件描述符。所谓 I/O 多路复用机制,就是说通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或写就绪),能够通知程序进行相应的读写操作。这种机制的使用需要 select 、 poll 、 epoll 来配合。多个连接共用一个阻塞对象,应用程序只需要在一个阻塞对象上等待,无需阻塞等待所有连接。
2023-07-06 12:09:39
4277
2
原创 【HTTP基础】GET 和 POST 的区别,以及幂等性详解
本文对比分析了HTTP请求方法GET与POST的核心区别,从安全性、幂等性、可缓存性等维度展开说明。GET请求用于获取资源,具有安全、幂等和可缓存的特性;而POST请求用于提交数据,不安全且非幂等。文章进一步解释了幂等性的概念,指出PUT和DELETE方法也具有幂等性。通过表格对比和形象比喻,清晰呈现了各方法的特点与适用场景,为Web开发中选择合适的请求方法提供了实用指导。
2025-11-24 14:04:43
586
原创 Spring Data Redis 中 opsForXXX 和 BoundXXXOps 的区别与应用
Spring Data Redis提供了opsForXXX和BoundXXXOps两种操作接口: opsForXXX(如opsForValue())是通用接口,每次操作需传入Redis键,适用于动态操作不同键和数据类型; BoundXXXOps(如boundValueOps())绑定特定键,操作时无需重复传键,适合频繁操作固定键的场景。 区别在于前者灵活性高,后者简化代码。选择依据是:动态多键操作用opsForXXX,固定键频繁操作用BoundXXXOps。两者共同满足不同Redis操作需求。
2025-11-24 13:50:00
525
原创 Java装饰器模式实战:优雅增强Spring线程池的ThreadFactory
摘要:装饰器模式是一种动态扩展对象功能的结构型设计模式。以咖啡加料为生活实例,通过在原始对象(SimpleCoffee)外包装装饰层(MilkDecorator/SugarDecorator)实现功能叠加,而不改变原有结构。该模式包含Component接口、ConcreteComponent实现类、Decorator抽象类和具体装饰器,通过持有并转发原始对象请求,在前后添加新行为。Java示例展示了如何为咖啡添加牛奶和糖的功能,ThreadFactory案例则演示了线程异常处理的装饰应用。当需要扩展对象功能
2025-11-17 15:48:03
579
原创 如何正确设置线程池大小?从 CPU 密集到 IO 密集的全方位解析
本文深入探讨了线程池优化的核心问题——如何合理设置线程数量。通过超市收银员的生动类比,文章区分了CPU密集型和IO密集型任务的特点:前者需要少量线程(CPU核心数+1)以避免上下文切换开销,后者可配置更多线程(CPU核心数×2-3)以填补IO等待时的CPU空闲。文中提供了任务类型的判断方法(代码分析、系统监控)和计算公式,并针对混合型任务建议采用异步拆分策略。最终给出了基于不同任务类型的线程数配置方案,强调CPU密集型要"少而精",IO密集型要"多并发"的优化原则。
2025-11-17 13:58:43
986
原创 深入理解系统调用:用户态与内核态的边界与协作
本文深入解析了用户态与内核态的概念及其在Java程序中的应用。操作系统通过这两种运行模式(用户态权限受限,内核态可直接操作硬件)保障系统安全稳定。当Java程序执行文件读写、网络通信等操作时,会通过系统调用触发用户态到内核态的切换,由内核完成实际硬件操作后再返回结果。频繁切换会带来性能开销,可通过零拷贝、NIO等技术优化。文章用政府办事的比喻形象说明了权限隔离的必要性,强调开发中应尽量减少状态切换以提高效率。
2025-11-09 11:05:40
621
原创 TCP 为什么要三次握手、四次挥手?2MSL 又是什么?
TCP连接管理的逻辑链 TCP协议通过三次握手建立可靠连接,防止旧的SYN请求导致错误连接,并确认双方收发能力。四次挥手则因全双工特性需独立关闭双向通道,确保数据完整传输。最后客户端等待2MSL(2倍报文最大生存时间),保证最后的ACK被接收并清除网络残留报文。三次握手防错连,四次挥手保数据完整,2MSL等待确保干净断开,共同构建TCP可靠通信机制。
2025-11-09 10:47:49
757
原创 Docker 加载镜像时报 no space left on device 的彻底解决方案
摘要: 在部署FastDDS镜像时遇到磁盘空间不足问题,原因是Docker默认数据目录/var/lib/docker占满根分区(99%)。通过将Docker数据迁移至空闲的/data分区解决: 停止Docker服务 使用rsync迁移数据至/data/docker 修改daemon.json配置新数据目录 验证并删除旧数据备份 最终成功重新导入镜像,释放根分区空间。关键经验:生产环境中应将Docker数据目录设置在独立大容量分区。
2025-11-07 21:44:53
488
原创 Spring Boot 实现 DOCX 转 PDF(基于 docx4j 的轻量级开源方案)
本文介绍了一种基于docx4j的开源方案,在Spring Boot中实现Word转PDF功能。该方案通过对比Apache POI、LibreOffice和Aspose等工具,选择了纯Java实现的docx4j,具有开源免费、部署简单、支持中文格式等优势。详细说明了Maven依赖配置,并提供了核心工具类DocxToPdfUtil的实现代码,重点解决了中文字体映射问题,确保转换质量。该方案无需安装Office软件,适合需要高质量文档转换的Java项目。
2025-10-23 10:23:28
1473
2
原创 Spring Boot + Jacob 实现 WPS 文件自动转换(DOCX → WPS)
本文介绍了基于Jacob库实现WPS文档转换的Spring Boot项目配置。项目结构包含lib目录存放jacob.jar和jacob.dll,通过JacobConfig类加载DLL文件。核心功能由WpsJacobUtil工具类实现,利用WPS COM接口将Word文档转换为WPS格式,并提供了Service层和Controller层实现。pom.xml中配置了system范围的Jacob依赖,需手动将jar包放入lib目录。项目启动时自动加载Jacob库,通过KWPS.Application调用WPS转换
2025-10-23 10:19:10
396
原创 Java中的资源管理:try-with-resources vs try-catch-finally
Java提供了两种资源管理方式:传统的try-catch-finally和Java 7引入的try-with-resources。传统方式需要手动在finally块中关闭资源,代码冗长且容易出错。而try-with-resources自动管理实现了AutoCloseable接口的资源,语法更简洁,能自动处理异常和资源关闭,有效防止资源泄漏。虽然传统方式在特殊场景下仍有使用价值,但现代Java开发中推荐优先使用try-with-resources,它能显著提升代码的安全性和可维护性。这种语法尤其适用于文件I/
2025-10-21 10:32:32
965
原创 阿里巴巴 Java 开发手册解读:DO、DTO、BO、AO、VO、Query 的区别与用法
摘要:本文解析阿里巴巴Java开发手册中的六大对象定义(DO、DTO、BO、AO、VO、Query),通过用户登录案例说明其应用场景。DO对应数据库表,AO处理前端请求,BO封装业务逻辑,DTO用于跨系统传输,VO负责前端展示,Query管理查询条件。文章强调分层架构的核心是职责分离,避免直接暴露数据库对象,禁用Map传参,确保各层数据对象各司其职,实现高内聚低耦合的设计规范。(150字)
2025-10-21 10:28:03
1052
原创 HAVING 与 WHERE 的区别详解(含执行顺序)
SQL执行顺序与WHERE/HAVING区别解析 SQL查询的实际执行顺序为:FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY。关键区别在于: WHERE在分组前执行,用于过滤原始数据行,不能使用聚合函数 HAVING在分组后执行,用于过滤分组结果,可以使用聚合函数判断 典型错误是在WHERE中使用COUNT()等聚合函数 最佳实践是先通过WHERE过滤无效数据,再用HAVING筛选分组结果 性能优化建议:优先使用WHERE过滤,对分组字段建立索引 核心原则:WHERE过
2025-10-20 10:01:32
494
原创 数据库主键选择:自增主键、UUID、雪花算法实战对比
自增主键单机数据库首选,性能最好。适合核心业务表内部主键。不要直接对外暴露(可预测)。UUID天然唯一,适合跨系统同步、对外标识。不建议直接做主键,存储开销大,性能差。推荐用BINARY(16)存储 + UUID v7(时间序)。雪花算法分布式环境的最佳选择,性能接近自增主键。要注意时钟回拨,可采用阻塞/序列补偿/回拨标记方案。适合作为数据库内部主键,对外可搭配 UUID。单机 + 高性能→ 自增 ID分布式 + 高性能→ 雪花 ID对外唯一标识→ UUID。
2025-10-20 09:58:22
1162
原创 大文件分片上传:简单案例(前端切割与后端合并)
前端实现分片上传的核心是通过JavaScript的File.slice()方法将大文件切割成小块,逐个上传。该方法支持断点续传,通过进度条实时显示上传状态。代码主要包括文件分片、已上传分片检查、分片上传及进度更新等功能,每个分片上传时携带文件名、总分片数和当前分片编号等元数据,确保后端能正确合并文件。失败时自动重试当前分片,最终完成全部上传后显示成功提示。
2025-10-19 11:54:33
482
原创 高性能单文件上传的秘密武器-sendfile零拷贝
本文介绍了零拷贝技术在文件上传中的应用。零拷贝通过减少不必要的数据拷贝,显著提高了文件传输效率。传统文件上传需要四次数据拷贝,而零拷贝技术利用Linux的sendfile系统调用,仅需两次上下文切换即可完成。Java NIO提供了FileChannel.transferTo()方法支持零拷贝,可直接将文件数据从磁盘传输到网络套接字。文章还展示了Spring Boot结合零拷贝实现文件上传的代码示例,包括后端接口和前端页面,为开发高性能文件上传功能提供了实践指导。
2025-10-19 11:36:45
473
原创 Tomcat 类加载器隔离机制的实际应用
摘要:本文通过代码示例演示了Tomcat的类加载器隔离机制如何解决Web应用中第三方库版本冲突问题。当App1使用LibraryX-1.0.jar和App2使用LibraryX-2.0.jar时,Tomcat为每个应用创建独立的WebAppClassLoader,采用child-first策略优先加载各自WEB-INF/lib下的JAR文件。测试结果显示两个应用能正确调用对应版本的类方法(App1输出1.0,App2输出2.0),验证了该机制能有效隔离不同应用的类加载环境,保障多版本库的并行运行。该机制提升
2025-10-18 16:37:39
910
原创 如何解决 Jacob 与 Tomcat 类加载问题:深入分析 Tomcat 类加载机制与 JVM 双亲委派机制
本文分析了在Java Web项目中集成Jacob库时常见的ClassNotFoundException和UnsatisfiedLinkError问题。通过解析Tomcat的类加载机制和JVM双亲委派模型,指出问题根源在于Tomcat的child-first策略导致WebAppClassLoader无法正确加载共享库。解决方案包括:1)将jacob.jar和jacob.dll放入Tomcat/lib目录由CommonClassLoader统一加载;2)在context.xml中配置delegate="
2025-10-18 16:32:15
824
原创 Redis 限流解决方案:结合 Lua 脚本、AOP 和自定义注解的实现
本文介绍了一个基于Redis、Lua脚本和AOP的限流组件设计方案。该组件通过自定义注解@RedisLimitAnnotation实现灵活配置,支持设置限流时间窗口、请求次数等参数。核心实现包括:使用Lua脚本保证Redis操作的原子性,通过AOP切面拦截带注解的方法执行限流逻辑。组件具备高可用性,能在高并发场景下稳定运行,且与业务代码解耦。配套提供了Redis配置类、限流切面实现和Lua脚本,并通过示例Controller展示了具体应用方式。该方案实现了可配置、可插拔的流量控制功能,有效保护系统稳定性。
2025-10-16 09:37:01
642
原创 Spring Boot 中使用自定义注解和 AOP 实现微服务日志记录(包含 URL、状态码和耗时信息)
本文提出了一种基于自定义注解和Spring AOP的轻量级方法日志记录方案。通过定义@MethodExporter注解标记需要监控的方法,利用AOP切面自动收集方法调用信息,包括输入参数、返回结果和执行耗时。该方案可避免手动添加日志代码的冗余,只需在方法上添加注解即可实现统一监控,便于运维和问题排查。文中详细展示了注解定义、切面实现和实际应用效果,未加注解的方法不会触发日志记录,验证了方案的灵活性和有效性。
2025-10-16 09:33:28
1050
1
原创 Spring AOP 中@annotation的两种写法详解
本文介绍了Spring AOP中@annotation的两种写法及区别。第一种写法@annotation(注解类路径)仅拦截带指定注解的方法,不获取注解内容;第二种写法@annotation(变量名)结合方法参数可获取注解实例,读取注解参数值。两种方式适用于不同场景:前者适合简单拦截,后者适合需要处理注解内容的场景。通过完整示例演示了两种写法的实际应用和输出结果,帮助开发者根据需求选择最合适的实现方式。
2025-10-15 10:15:15
404
原创 代理模式 vs AOP:支付服务中的日志增强实践(含执行顺序详解)
本文介绍了Java中支付服务的实现方式,首先定义PayService接口和PayServiceImpl实现类,随后通过代理模式(PayProxy)为支付操作添加日志增强功能。第二部分对比了AOP中execution和@annotation两种切点表达式的区别:execution基于方法签名进行精准匹配,适合批量拦截;@annotation则通过方法注解灵活控制,适合特定方法增强。最后展示了AOP通知的执行顺序示例,包括@Before前置通知和@After后置通知。(99字)
2025-10-15 09:35:27
810
原创 Linux 硬链接 vs 软链接:原理、区别与实战场景全解析
Linux系统中的硬链接和软链接是两种不同的文件链接方式。硬链接通过多个文件名共享同一个inode,删除一个链接不会影响文件内容,但不能跨文件系统或链接目录。软链接则是独立的文件,包含目标文件的路径信息,可以跨文件系统和链接目录,但若目标被删除则链接失效。硬链接适用于防止数据丢失和共享数据,而软链接适合跨文件系统、目录链接和路径简化。选择时需根据具体需求:硬链接更可靠,软链接更灵活。
2025-10-14 09:35:45
1110
原创 CentOS 磁盘空间不足的排查与解决(以虚拟机为例)
CentOS磁盘空间不足的完整解决方案:首先通过df -h和du -sh排查根分区爆满问题,发现/var/lib/docker和/opt是主要占用目录。临时清理方法包括:删除无用的Docker资源(docker system prune)、清理yum缓存、旧内核和日志文件。长期解决方案是新增磁盘:在虚拟机控制台添加硬盘后,使用fdisk分区(创建扩展分区sda4和逻辑分区sda5),格式化(mkfs.xfs)并挂载到/data目录,最后迁移大目录如Docker数据到新磁盘。整个过程涵盖从问题排查到永久扩容的
2025-10-14 09:30:58
852
原创 深入理解 Java 泛型的通配符:? extends T 和 ? super T
本文介绍了Java泛型中的通配符机制,重点分析了? extends T(上界通配符)和? super T(下界通配符)的使用场景与特性。上界通配符允许安全读取数据但不能写入,而下界通配符支持写入操作但只能读取Object类型数据。文章通过代码示例演示了两种通配符的实际应用,并解释了PECS原则(Producer Extends, Consumer Super)来指导正确选择通配符类型。最后展示了通配符在数据拷贝场景中的具体应用,帮助开发者编写更灵活可靠的泛型代码。
2025-10-13 10:11:13
729
原创 深入理解 Java 序列化:实现 Serializable 接口与 serialVersionUID 的重要性
Java序列化机制解析:Serializable接口与serialVersionUID的作用 摘要:Java序列化通过Serializable接口实现对象与字节流的相互转换,主要用于对象持久化和网络传输。实现时只需让目标类实现Serializable标记接口,并通过ObjectOutputStream/ObjectInputStream进行读写操作。核心机制serialVersionUID用于版本控制,确保序列化兼容性。若类结构改变但未更新该值,反序列化会抛出InvalidClassException。
2025-10-13 09:55:03
1178
原创 依赖注入实战:构造、字段与方法注入的案例与缺陷分析
本文介绍了Java中依赖注入(DI)的三种形式:构造注入、字段注入和方法注入。通过汽车依赖引擎的案例,展示了每种方式的代码实现和优缺点对比:构造注入强制依赖但构造器可能臃肿;字段注入简洁但依赖不可见;方法注入灵活但易遗漏setter调用。最后给出实践建议:必需依赖用构造注入,可选依赖用setter注入,尽量避免字段注入(除Spring自动装配场景)。150字
2025-10-12 10:59:06
298
原创 反转控制与依赖注入详解:以订单处理系统为例
摘要:本文通过电商订单处理案例演示控制反转(IoC)和依赖注入(DI)的应用。传统方法中,OrderService直接创建PaymentService和NotificationService实例,导致强耦合、难以扩展和测试困难。改进方案采用依赖注入:定义服务接口,通过构造函数注入依赖。这样做实现了松耦合(可轻松替换实现类)、灵活扩展(不改动OrderService即可新增功能)和可测试性(支持Mock测试)。最后展示了如何通过DI切换不同通知服务(如Email/SMS),验证了IoC的灵活性。
2025-10-11 10:13:53
1012
原创 告别冗长的 if...else:通过策略、工厂和模板模式优化代码结构
本文介绍了如何通过策略模式和工厂模式优化传统if-else逻辑的问题。首先分析了if-else写法存在的维护性差、扩展性差、违反开闭原则等问题,然后提出使用策略模式将不同逻辑封装为独立策略类,运行时动态选择执行策略。接着引入工厂模式,通过DrinkFactory类统一管理对象创建过程,实现创建与使用的解耦。最后提出策略工厂模式,结合Map缓存策略实例,完全消除if-else判断,实现更优雅的策略选择。两种模式的结合既保持了策略模式的灵活性,又通过工厂简化了策略对象的创建与管理,提高了代码的可维护性和扩展性。
2025-10-11 10:06:04
1177
原创 Spring Bean 生命周期详解:初始化与销毁方式对比与实践
Spring Bean生命周期管理:初始化与销毁详解 本文系统介绍了Spring框架中Bean生命周期的管理方式,重点分析了初始化和销毁两个关键阶段。初始化提供了三种实现方式:推荐使用标准注解@PostConstruct,也可选择实现InitializingBean接口或配置init-method;销毁阶段同样提供三种方式:@PreDestroy注解、DisposableBean接口和destroy-method配置。文章详细比较了各种方式的优缺点,展示了完整的执行顺序,并给出了实际开发中的典型应用场景。建
2025-10-10 10:44:29
795
原创 Java 单元测试全攻略:JUnit 生命周期、覆盖率提升、自动化框架与 Mock 技术
本文总结了阿里巴巴Java开发手册中的单元测试要点,强调单元测试的核心价值在于提前发现问题、保证重构安全、提升代码质量和降低维护成本。关键结论包括:1)单元测试必须有明确断言而非仅看绿色条;2)演示了JUnit测试案例和覆盖率报告;3)详细解释了JUnit生命周期注解(@BeforeAll、@BeforeEach、@AfterEach、@AfterAll)的使用场景与案例。文章通过具体代码示例展示了如何利用这些注解优化测试结构,最终强调好的单元测试应关注断言合理性而非单纯通过率。
2025-10-10 10:07:35
1148
原创 MapStruct 教程:从零开始的对象映射实战
MapStruct是一个Java对象映射工具,能在编译期自动生成映射代码,提升DTO与Entity之间的转换效率。相比传统反射工具,它性能更高且代码更简洁。通过定义Mapper接口并添加注解,即可实现字段映射、表达式赋值和集合转换等功能。示例展示了UserDTO与UserEntity的互转,以及处理字段名不一致的情况。MapStruct能大幅减少样板代码,提高开发效率和可维护性,特别适合前后端交互中的对象转换场景。
2025-10-09 10:02:06
959
原创 浅拷贝与深拷贝详解:概念、代码示例与后端应用场景
本文探讨了深拷贝与浅拷贝的区别及应用场景。浅拷贝仅复制对象引用,新旧对象共享内存,修改一个会影响另一个;深拷贝创建完全独立的新对象,两者互不影响。分析表明,浅拷贝适用于简单数据传输(如DTO与Entity转换),因其高效且开销小;而深拷贝更适用于需要对象完全独立的场景(如多线程安全)。文章通过Java代码示例验证了两种拷贝方式的实现效果,并指出在包含可变引用对象时浅拷贝可能导致数据共享问题,此时应选择深拷贝。
2025-10-09 09:45:03
1113
原创 IDEA-Debug必备基本功
本文详细介绍了IDEA中Debug功能的常用操作和技巧。主要内容包括:1)基本调试操作如步过、步入、强制步入、步出等;2)高级功能如计算表达式、强行返回、重置方法栈帧等;3)四种断点类型(单行断点、方法断点、字段断点和异常断点)的特点及适用场景。通过示例代码和流程图,特别说明了Reset Frame功能的使用效果和注意事项。文章还提供了断点类型的速查表,帮助开发者快速选择适合的调试方式。
2025-10-05 20:45:07
1115
原创 传值还是传引用?Java 中的基本数据类型与对象传递机制解析
Java方法参数传递机制解析:基本数据类型采用值传递,方法内修改不影响原值;对象类型传递引用副本,方法内修改会影响原对象;String类型由于不可变性,行为类似基本数据类型。通过示例代码展示了int、Person和String三种类型的参数传递差异,说明在Java中所有参数传递本质上都是值传递,但对象类型传递的是引用的副本,而基本数据类型传递的是值的副本。
2025-09-30 10:13:44
779
原创 掌握Java BigDecimal:精确计算的技巧与常见问题
文章摘要 Java中的BigDecimal类用于高精度计算,避免浮点数精度丢失问题。本文通过对比构造方法、等值比较、除法运算和科学计数法处理四个方面,详细解析BigDecimal的正确使用方式: 构造方法:推荐使用BigDecimal(String)或BigDecimal.valueOf(double),避免直接使用double构造方法导致的精度问题 等值比较:应使用compareTo()而非equals(),前者忽略精度差异 除法运算:必须指定精度和舍入模式(如HALF_UP) 科学计数法:使用toPla
2025-09-30 09:28:25
1245
原创 Cursor开发助手:Tab键、Chat模式与Ctrl+K全解析
Cursor通过Tab键提供智能代码补全功能,支持单行/多行代码生成、代码重写和优化。Chat模式则允许用户通过自然语言与代码库交互,实现代码编辑、错误修复和项目搭建。Tab键可接受或拒绝建议,支持部分接受,并可通过配置调整功能范围。Chat模式能理解代码库并进行修改、重构和项目初始化,适用于多种开发场景。
2025-09-29 10:34:57
1122
原创 深入理解 BCrypt:安全的密码加密与存储方式
本文介绍了BCrypt密码加密算法的优势及在Java中的应用。相比普通哈希,BCrypt具有自动加盐、可调节成本因子和抗GPU破解等特性,能有效增强密码安全性。文章详细解释了BCrypt的工作原理,包括随机盐生成和Blowfish加密过程,并提供了Spring Boot中使用BCryptPasswordEncoder的代码示例。最佳实践建议设置合理的成本因子,避免存储明文密码和重复加密。BCrypt已成为主流框架的默认密码加密方案,开发者应避免使用快速哈希算法,以降低数据泄露风险。
2025-09-29 09:28:56
1284
原创 Spring Cloud Gateway 实战:全局过滤器日志统计与 Prometheus + Grafana 接口耗时监控
本文介绍了基于Spring Cloud Gateway的接口性能监控方案。通过在全局过滤器中记录请求日志和耗时,并集成Prometheus和Grafana实现可视化监控。关键步骤包括:1)使用GlobalFilter实现日志统计;2)通过Micrometer MeterRegistry上报指标;3)配置Prometheus采集数据;4)在Grafana中创建监控大盘。该方案能有效监控接口性能,帮助开发者快速定位问题,为系统优化提供数据支持。
2025-09-28 09:43:01
1524
原创 Sentinel完整学习笔记:雪崩效应、解决方案与流量控制
本文介绍了Sentinel的基本概念及其在微服务架构中的应用。首先解释了雪崩效应及其四种解决方案:超时处理、隔离处理、熔断处理和流量控制。随后详细介绍了Sentinel的历史、核心功能和控制台部署方法,包括Docker安装方式。接着演示了如何将Spring Cloud服务与Sentinel控制台整合,并展示了流量控制的基本操作流程,包括设置QPS阈值来限制接口访问频率。Sentinel作为阿里巴巴开源的流量控制组件,能够有效预防微服务系统中的雪崩问题,保障系统稳定性。
2025-09-28 09:13:51
1336
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅