Java面试题 -其他框架

本文涉及的产品
云原生网关 MSE Higress,422元/月
MSE Nacos/ZooKeeper 企业版试用,1600元额度,限量50份
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
简介: Java面试题 -其他框架
1. 描述⼀下Hibernate的三个状态?

a. transient(瞬时状态):new出来⼀个对象,还没被保存到数据库中

b. persistent(持久化状态):对象已经保存到数据库中并且在hibernate session也存在该对象

c. detached(离线状态):对象在数据库中存在,hibernate session不存在

2. struts⼯作流程

1、客户端浏览器发出HTTP请求。

2、根据web.xml配置,该请求被FilterDispatcher接收。

3、根据struts.xml配置,找到需要调⽤的Action类和⽅法, 并通过IoC⽅式,将值注⼊给Aciton。

4、Action调⽤业务逻辑组件处理业务逻辑,这⼀步包含表单验证。

5、Action执⾏完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到相应⻚⾯。

6、返回HTTP响应到客户端浏览器。

3. Hibernate对⼀⼆级缓存的使⽤, Lazy-Load的理解

a. ⼀级缓存:hibernate的⼀级缓存是由session提供的,因此它只存在session的⽣命周期中。也就是说session关闭的时候该session所管理的⼀级缓存也随之被清除。hibernate的⼀级缓存是session所内置的,默认开启,不能被卸载,也不能进⾏任何配置。在缓存中的对象,具有持久性,session对象负责管理.⼀级缓存的优点是使⽤同⼀个session对象多次查询

同⼀个数据对象,仅对数据库查询⼀次。⼀级缓存采⽤的是Key-Value的MAP⽅式来实现的。在缓存实体对象时,对象的主关键字ID是MAP的Key,实体对象就是对象的值。所以说⼀级缓存是以实体对象为单位进⾏存储的。访问的时候使⽤的是主键关键字ID。⼀级缓存使⽤的是⾃动维护的功能。但可以通过session提供的⼿动⽅法对⼀级缓存的管理进⾏⼿动⼲预。evict()⽅法⽤于将某个对象从session的⼀级缓存中清除。clear()⽅法⽤于将session缓存中的⽅法全部清除。

b. ⼆级缓存:⼆级缓存的实现原理与⼀级缓存是⼀样的。也是通过Key-Value的Map来实现对对象的缓存。⼆级缓存是作⽤在SessionFactory范围内的。因此它可被所有的Session对象所共享。需要注意的是放⼊缓存中的数据不能有第三⽅的应⽤对数据进⾏修改。⼆级缓存默认关闭,需要程序员⼿动开启,默认为ehcache实现.

c. 懒加载:当⽤到数据的时候才向数据库查询,这就是hibernate的懒加载特性。延迟加载策略能避免加载应⽤程序不需要访问的关联对象,以提⾼应⽤程序的性能。

4. mybatis如何实现批量提交?

a. 通过标签:

insert into sys_user_role
  ( `user_id`, `role_id`) 
values
<foreach collection="roleIdList" item="item" index="index" separator=","> 
  (  #{userId}, #{item} )
</foreach>

b. 通过ExecutorType.BATCH:

5. session机制?
  1. session是服务器的⽣成,并传⾄客户端浏览器,后续请求,都会通过URL重写传⾄服务器进⾏session⽐较.
  2. session是基于cookie
  3. session可以保存⽤户信息,但cookie如果浏览器被禁⽤,则⽆法保存⽤户信息
  4. 如果浏览器禁⽤会话cookie,则每次请求都⽆法将第⼀次请求获得的sessionId传⾄后台服务器.所以每次请求刷新⻚⾯服务器都会⽣成新的sessionid给到浏览器
  5. 因HTTP协议为⽆状态的协议(⼀旦数据交互完毕,客户端和服务端的连接就会关闭,再次交换数据时需要建⽴新的连接),需要通过session或者cookie保存和跟踪⽤户信息
  6. sessionID放在浏览器客户端cookie,其它信息放在服务器内存中,也可以做持久化管理memcached、redis中;
6. Struts2表单重复提交问题(token拦截器)
  1. 访问⻚⾯前保存token(服务器后台⽣成的⼀串序列时间串放到session中),并传⾄前台jsp⻚⾯中的隐藏域
  2. 提交时验证token,将前台的隐藏的token传⾄后台进⾏验证是否⼀致,提交随机⽣成新的token,可以防⽌重复提交;
7.Shiro

定义:

apache shiro是java的⼀个安全框架,简单易⽤,基本功能有:认证、授权、加密、会话管理、与Web集成、缓存等。Shiro不会去维护⽤户、维护权限;这些需要我们⾃⼰去设计/提供;然后通过相应的接⼝注⼊给Shiro即可(五张表)。

功能点:

Authentication:身份认证/登录,验证⽤户是不是拥有相应的身份;

Authorization:授权,即权限验证,验证某个已认证的⽤户是否拥有某个权限;即判断⽤户是否能做事情,常⻅的如:验证某个⽤户是否拥有某个⻆⾊。或者细粒度的验证某个⽤户对某个资源是否具有某个权限;

Session Manager:会话管理,即⽤户登录后就是⼀次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;

Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,⽽不是明⽂存储;

Web Support:Web⽀持,可以⾮常容易的集成到Web环境;

Caching:缓存,⽐如⽤户登录后,其⽤户信息、拥有的⻆⾊/权限不必每次去查,这样可以提⾼效率;

Concurrency:shiro⽀持多线程应⽤的并发验证,即如在⼀个线程中开启另⼀个线程,能把权限⾃动传播过去;

Testing:提供测试⽀持;

Run As:允许⼀个⽤户假装为另⼀个⽤户(如果他们允许)的身份进⾏访问;

Remember Me:记住我,这个是⾮常常⻅的功能,即⼀次登录后,下次再来的话不⽤登录了。

⼯作流程:

  1. 应⽤代码通过Subject(主体,代表当前”⽤户")来进⾏认证和授权,⽽Subject⼜委托给SecurityManager(安全管理器,shiro核⼼);
  2. 我们需要给Shiro的SecurityManager注⼊Realm(域,Shiro从Realm获取安全数据(如⽤户、⻆⾊、权限)),从⽽让SecurityManager能得到合法的⽤户及其权限进⾏判断。
8. Tomcat Filter过滤器责任链模式,过滤器拦截器区别?

责任链模式

  • 将⼀个事件处理流程分派到⼀组执⾏对象上去,这⼀组执⾏对象形成⼀个链式结构,事件处理请求在这⼀组执⾏对象上进⾏传递。

过滤器和拦截器

  1. 过滤器filter:是在java web中,你传⼊的request,response提前过滤掉⼀些信息,或者提前设置⼀些参数,然后再传⼊servlet或者struts的 action进⾏业务逻辑,⽐如过滤掉⾮法url(不是login.do的地址请求,如果⽤户没有登陆都过滤掉),或者在传⼊servlet或者 struts的action前统⼀设置字符集,或者去除掉⼀些⾮法字符;
  2. 拦截器interceptor:是在⾯向切⾯编程的就是在你的service或者⼀个⽅法,前调⽤⼀个⽅法,或者在⽅法后调⽤⼀个⽅法⽐如动态代理就是拦截器的简单实现,在你调⽤⽅法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调⽤⽅法后打印出字符串,甚⾄在你抛出异常的时候做业务逻辑的操作。拦截是AOP的⼀种实现策略;

区别:

a. 拦截器是基于java的反射机制的,⽽过滤器是基于函数回调。

b. 拦截器不依赖于servlet容器,过滤器依赖与servlet容器。

c. 拦截器只能对action请求起作⽤,⽽过滤器则可以对⼏乎所有的请求起作⽤。

d. 拦截器可以访问action上下⽂、值栈⾥的对象,⽽过滤器不能访问。

e. 在action的⽣命周期中,拦截器可以多次被调⽤,⽽过滤器只能在容器初始化时被调⽤⼀次。

9. Git与Svn的区别

1、Git是分布式的,⽽Svn不是;

2、GIT把内容按元数据⽅式存储,⽽SVN是按⽂件

3、分⽀不同:git分⽀切换很⽅便;svn分⽀就是版本库的另外⼀个⽬录;

4、GIT没有⼀个全局的版本号,⽽svn有,SVN的版本号实际是任何⼀个相应时间的源代码快照。

5、GIT的内容完整性要优于SVN(GIT的内容存储使⽤的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和⽹络问题时降低对版本库的破坏。)

10. Git命令底层原理:

1.git init:使⽤git init初始化⼀个新的⽬录时,会⽣成⼀个.git的⽬录,该⽬录即为本地仓库。⼀个新初始化的本地仓库是这样的:

  • description⽤于GitWeb程序
  • config配置特定于该仓库的设置(还记得git config的三个配置级别么)
  • hooks放置客户端或服务端的hook脚本
  • HEAD传说中的HEAD指针,指明当前处于哪个分⽀
  • objectsGit对象存储⽬录
  • refsGit引⽤存储⽬录
  • branches放置分⽀引⽤的⽬录

其中description、config和hooks这些不在讨论中,后⽂会直接忽略。

git add:Git commit之前先要通过git add添加⽂件:

可以看到,多了⼀个index⽂件。并且在objects⽬录下多了⼀个9f的⽬录,其中多了⼀个

4d96d5b00d98959ea9960f069585ce42b1349a⽂件。其实9f4d96d5b00d98959ea9960f069585ce42b1349a就是⼀个Git对象,称为blob对象。

git commit:

11. JSP的执⾏过程:
  1. 客户端发出请求。
  2. Web容器将JSP转译成Servlet源代码。
  3. Web容器将产⽣的源代码进⾏编译。
  4. Web容器加载编译后的代码并执⾏。
  5. 把执⾏结果响应⾄客户端。
12. ZK⾼可⽤
  • ZooKeeper 运⾏期间,集群中⾄少有过半的机器保存了最新数据。集群超过半数的机器能够正常⼯作,集群就能够对外提供服务。
13. zookeeper有什么功能,选举算法如何进⾏?

选举算法 (Fast Leader(领导者选举)选举算法):

  1. server启动时默认选举⾃⼰,并向整个集群⼴播
  2. 收到消息时,通过3层判断:选举轮数,zxid,server id⼤⼩判断是否同意对⽅,如果同意,则修改⾃⼰的选票,并向集群⼴播
  3. QuorumCnxManager负责IO处理,每2个server建⽴⼀个连接,只允许id⼤的server连id⼩的server,每个server启动单独的读写线程处理,使⽤阻塞IO
  4. 默认超过半数机器同意时,则选举成功,修改⾃身状态为LEADING或FOLLOWING
  5. Obserer机器不参与选举

原理:

  • 选举结果的影响权重关系是:⾸先看数据id,数据id⼤者胜出;其次再判断leader id,leader id⼤者胜出。

举例:

假设有五台服务器组成的zookeeper集群,它们的id从1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这⼀点上,都是⼀样的.假设这些服务器依序启动,来看看会发⽣什么?

  1. 服务器1启动,此时只有它⼀台服务器启动了,它发出去的报没有任何响应,所以它的选举状态⼀直是LOOKING状态;
  2. 服务器2启动,它与最开始启动的服务器1进⾏通信,互相交换⾃⼰的选举结果,由于两者都没有历史数据,所以id值较⼤的服务器2胜出,但是由于没有达到超过半数以上的服务器都同意选举它(这个例⼦中的半数以上是3),所以服务器1,2还是继续保持LOOKING状态.
  3. 服务器3启动,根据前⾯的理论分析,服务器3成为服务器1,2,3中的⽼⼤,⽽与上⾯不同的是,此时有三台服务器选举了它,所以它成为了这次选举的leader.
  4. 服务器4启动,根据前⾯的分析,理论上服务器4应该是服务器1,2,3,4中最⼤的,但是由于前⾯已经有半数以上的服务器选举了服务器3,所以它只能接收当⼩弟的命了.
  5. 服务器5启动,同4⼀样,当⼩弟.

4、zookeeper管理员指南:

  • 集群中过半存活即可⽤,故集群选择奇数台机器;
14. RPC、RMI、MQ、SOAP

RPC:远程过程调⽤协议,采⽤C/S模式,分布式跨语⾔平台,更多⽤于同步调⽤,⽐如Web Service(SOAP);

RMI:远程⽅法调⽤,依赖于java远程消息交换协议,要求服务端与客户端都为java编写;每个⽅法都具有⽅法签名,只有签名匹配才可以调⽤,返回值是基本类型和对象;

MQ:队列,更多⽤于异步传输;

SOAP:最主要的⼯作是使⽤标准的XML描述了RPC的请求信息(URI/类/⽅法/参数/返回值)。理论上,SOAP就是⼀段xml,你可以通过http,smtp等发送它(复制到软盘上,叫快递公司送去也⾏?),同样SOAP也是跨语⾔的。

15. Netty⾼性能
  1. NIO异步⾮阻塞通信
  2. “零拷⻉”
  3. 内存池ByteBuf
  4. Netty提供了多种内存管理策略,通过在启动辅助类中配置相关参数,可以实现差异化的定制。
  5. ⾼效的Reactor线程模型:Reactor单线程(多线程、主从)模型,指的是所有的IO操作都在同⼀个NIO线程上⾯完成
  6. 为了尽可能提升性能,Netty采⽤了串⾏⽆锁化设计,在IO线程内部进⾏串⾏操作,避免多线程竞争导致的性能下降。表⾯上看,串⾏化设计似乎CPU利⽤率不⾼,并发程度不够。但是,通过调整NIO线程池的线程参数,可以同时启动多个串⾏化的线程并⾏运⾏,这种局部⽆锁化的串⾏线程设计相⽐⼀个队列-多个⼯作线程模型性能更优。
  7. ⾼效的序列化框架。
  8. 灵活的TCP参数配置能⼒:合理设置TCP参数在某些场景下对于性能的提升可以起到显著的效果,例如SO_RCVBUF和SO_SNDBUF。如果设置不当,对性能的影响是⾮常⼤的。

⾼效的并发编程:Netty的⾼效并发编程主要体现在如下⼏点:

  • volatile的⼤量、正确使⽤;
  • CAS和原⼦类的⼴泛使⽤;
  • 线程安全容器的使⽤;
  • 通过读写锁提升并发性能。
16. 如何保证服务的幂等性?

概念:接⼝的幂等性实际上就是接⼝可重复调⽤,在调⽤⽅多次调⽤的情况下,接⼝最终得到的结果是⼀致的。有些接⼝可以天然的实现幂等性,⽐如查询接⼝,对于查询来说,你查询⼀次和两次,对于系统来说,没有任何影响,查出的结果也是⼀样。

GET幂等:值得注意,幂等性指的是作⽤于结果⽽⾮资源本身。怎么理解呢?例如,这个HTTP GET⽅法可能会每次得到不同的返回内容,但并不影响资源。

POST⾮幂等:因为它会对资源本身产⽣影响,每次调⽤都会有新的资源产⽣,因此不满⾜幂等性。

如何保证幂等性

  1. 全局唯⼀id:如果使⽤全局唯⼀ID,就是根据业务的操作和内容⽣成⼀个全局ID,在执⾏操作前先根据这个全局唯⼀ID是否存在,来判断这个操作是否已经执⾏。如果不存在则把全局ID,存储到存储系统中,⽐如数据库、redis等。如果存在则表示该⽅法已经执⾏。从⼯程的⻆度来说,使⽤全局ID做幂等可以作为⼀个业务的基础的微服务存在,在很多的微服务中都会⽤到这样的服务,在每个微服务中都完成这样的功能,会存在⼯作量重复。另外打造⼀个⾼可靠的幂等服务还需要考虑很多问题,⽐如⼀台机器虽然把全局ID先写⼊了存储,但是在写⼊之后挂了,这就需要引⼊全局ID的超时机制。使⽤全局唯⼀ID是⼀个通⽤⽅案,可以⽀持插⼊、更新、删除业务操作。但是这个⽅案看起来很美但是实现起来⽐较麻烦,下⾯的⽅案适⽤于特定的场景,但是实现起来⽐较简单。
  2. 去重表:这种⽅法适⽤于在业务中有唯⼀标的插⼊场景中,⽐如在以上的⽀付场景中,如果⼀个订单只会⽀付⼀次,所以订单ID可以作为唯⼀标识。这时,我们就可以建⼀张去重表,并且把唯⼀标识作为唯⼀索引,在我们实现时,把创建⽀付单据和写⼊去重表,放在⼀个事务中,如果重复创建,数据库会抛出唯⼀约束异常,操作就会回滚。
  3. 插⼊或更新:这种⽅法插⼊并且有唯⼀索引的情况,⽐如我们要关联商品品类,其中商品的ID和品类的ID可以构成唯⼀索引,并且在数据表中也增加了唯⼀索引。这时就可以使⽤InsertOrUpdate操作。在mysql数据库中如下:
  4. 多版本控制:这种⽅法适合在更新的场景中,⽐如我们要更新商品的名字,这时我们就可以在更新的接⼝中增加⼀个版本号,来做幂等:在实现时可以如下:
  5. 、状态机控制:这种⽅法适合在有状态机流转的情况下,⽐如就会订单的创建和付款,订单的付款肯定是在之前,这时我们可以通过在设计状态字段时,使⽤int类型,并且通过值类型的⼤⼩来做幂等,⽐如订单的创建为0,付款成功为100。付款失败为99在做状态机更新时,我们就这可以这样控制:
17. zookeeper⼯作原理?

定义:zookeeper是⼀种为分布式应⽤所设计的⾼可⽤、⾼性能且⼀致的开源协调服务,它提供了⼀项基本服务:分布式锁服务。后来摸索出了其他使⽤⽅法:配置维护、组服务、分布式消息队列、分布式通知/协调等。

特点:

  1. 能够⽤在⼤型分布式系统中;
  2. 具有⼀致性、可⽤性、容错性,不会因为⼀个节点的错误⽽崩溃;

⽤途:(⽤户⼤型分布式系统,作协调服务⻆⾊)

  1. 分布式锁应⽤:通过对集群进⾏master选举,来解决分布式系统中的单点故障(⼀主n从,主挂全挂)。
  2. 协调服务;
  3. 注册中⼼;

术语:

  • 数据结构Znode:zookeeper数据采⽤树形层次结构,和标准⽂件系统⾮常相似,树中每个节点被称为Znode;
  • 通知机制Watcher:zookeeper可以为所有的读操作(exists()、getChilden()及getData())设置watch,watch事件是⼀次性出发器,当watch的对象状态发⽣改变时,将会触发次对象上watch所对应的事件。watch事件将被异步的发送给客户端,并且zookeeper为watch机制提供了有序的⼀致性保证。

基本流程:(分布式锁应⽤场景)

  1. 传统的⼀主n从分布式系统,容易发⽣单点故障,传统解决⽅式是增加⼀个备⽤节点,定期给主节点发送Ping包,主节点回复ack,但是如果⽹络原因ack丢失,那么会出现两个主节点,造成数据混乱。
  2. zookeeper的引⼊可以管理两个主节点,其中挂了⼀个,会将另外⼀个作为新的主节点,挂的节点回来时担任备⽤节点;

18. cap理论

概念:⼀个分布式系统最多只能同时满⾜⼀致性(Consistency)、可⽤性(Availability)和分区容错性(Partition tolerance)这三项中的两项。

  • ⼀致性:更新操作成功并返回客户端完成后,所有节点在同⼀时间的数据完全⼀致,所以,⼀致性,说的就是数据⼀致性。
  • 可⽤性:服务⼀直可⽤,⽽且是正常响应时间。
  • 分区容错性:分布式系统在遇到某节点或⽹络分区故障的时候,仍然能够对外提供满⾜⼀致性和可⽤性的服务。
目录
相关文章
|
25天前
|
人工智能 Java 开发者
阿里出手!Java 开发者狂喜!开源 AI Agent 框架 JManus 来了,初次见面就心动~
JManus是阿里开源的Java版OpenManus,基于Spring AI Alibaba框架,助力Java开发者便捷应用AI技术。支持多Agent框架、网页配置、MCP协议及PLAN-ACT模式,可集成多模型,适配阿里云百炼平台与本地ollama。提供Docker与源码部署方式,具备无限上下文处理能力,适用于复杂AI场景。当前仍在完善模型配置等功能,欢迎参与开源共建。
706 58
阿里出手!Java 开发者狂喜!开源 AI Agent 框架 JManus 来了,初次见面就心动~
|
4月前
|
缓存 Java 关系型数据库
2025 年最新华为 Java 面试题及答案,全方位打造面试宝典
Java面试高频考点与实践指南(150字摘要) 本文系统梳理了Java面试核心考点,包括Java基础(数据类型、面向对象特性、常用类使用)、并发编程(线程机制、锁原理、并发容器)、JVM(内存模型、GC算法、类加载机制)、Spring框架(IoC/AOP、Bean生命周期、事务管理)、数据库(MySQL引擎、事务隔离、索引优化)及分布式(CAP理论、ID生成、Redis缓存)。同时提供华为级实战代码,涵盖Spring Cloud Alibaba微服务、Sentinel限流、Seata分布式事务,以及完整的D
208 1
|
3月前
|
缓存 Java API
Java 面试实操指南与最新技术结合的实战攻略
本指南涵盖Java 17+新特性、Spring Boot 3微服务、响应式编程、容器化部署与数据缓存实操,结合代码案例解析高频面试技术点,助你掌握最新Java技术栈,提升实战能力,轻松应对Java中高级岗位面试。
341 0
|
2月前
|
存储 缓存 安全
Java集合框架(二):Set接口与哈希表原理
本文深入解析Java中Set集合的工作原理及其实现机制,涵盖HashSet、LinkedHashSet和TreeSet三大实现类。从Set接口的特性出发,对比List理解去重机制,并详解哈希表原理、hashCode与equals方法的作用。进一步剖析HashSet的底层HashMap实现、LinkedHashSet的双向链表维护顺序特性,以及TreeSet基于红黑树的排序功能。文章还包含性能对比、自定义对象去重、集合运算实战和线程安全方案,帮助读者全面掌握Set的应用与选择策略。
167 23
|
1月前
|
SQL Java 数据库连接
区分iBatis与MyBatis:两个Java数据库框架的比较
总结起来:虽然从技术角度看,iBATIS已经停止更新但仍然可用;然而考虑到长期项目健康度及未来可能需求变化情况下MYBATISS无疑会是一个更佳选择因其具备良好生命周期管理机制同时也因为社区力量背书确保问题修复新特征添加速度快捷有效.
91 12
|
2月前
|
存储 缓存 安全
Java集合框架(三):Map体系与ConcurrentHashMap
本文深入解析Java中Map接口体系及其实现类,包括HashMap、ConcurrentHashMap等的工作原理与线程安全机制。内容涵盖哈希冲突解决、扩容策略、并发优化,以及不同Map实现的适用场景,助你掌握高并发编程核心技巧。
|
2月前
|
安全 Java 开发者
Java集合框架:详解Deque接口的栈操作方法全集
理解和掌握这些方法对于实现像浏览器后退功能这样的栈操作来说至关重要,它们能够帮助开发者编写既高效又稳定的应用程序。此外,在多线程环境中想保证线程安全,可以考虑使用ConcurrentLinkedDeque,它是Deque的线程安全版本,尽管它并未直接实现栈操作的方法,但是Deque的接口方法可以相对应地使用。
133 12
|
2月前
|
存储 安全 Java
Java集合框架(一):List接口及其实现类剖析
本文深入解析Java中List集合的实现原理,涵盖ArrayList的动态数组机制、LinkedList的链表结构、Vector与Stack的线程安全性及其不推荐使用的原因,对比了不同实现的性能与适用场景,帮助开发者根据实际需求选择合适的List实现。
|
3月前
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
408 0
|
2月前
|
Cloud Native Java API
Java Spring框架技术栈选和最新版本及发展史详解(截至2025年8月)-优雅草卓伊凡
Java Spring框架技术栈选和最新版本及发展史详解(截至2025年8月)-优雅草卓伊凡
336 0

热门文章

最新文章

下一篇
日志分析软件