开心一刻

2021,朋友某一次核酸检测,跟我聊天
朋友:今天我们小区做核算,队长死了
我:卧槽,过劳死吗
朋友:?????
我:啊?
朋友:队 长死了,队伍很长!
我:哈哈哈,我以为做核算的队长死了呢

背景介绍

项目基于 springboot2.5.2 实现的,用 springfox-swagger2 生成与前端对接的 API 文档;pom.xml 中依赖如下

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
</parent> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>

启动服务后,就可以访问 Swagger UI

http://localhost:8080/swagger-ui/index.html

前端同事就可以访问这个来对接接口了,后端省去了写接口文档的工作,一切都是那么美好!可突然有一天,安全部门发来报告,说服务存在很多安全漏洞

CVE-2023-20860、CVE-2022-45143、CVE-2023-46589、...

让我们根据报告中的建议进行修复,然后就开始了我的踩坑之旅!

springboot 与 springfox 兼容问题

粗略看了一眼,将 spring-boot 升级,可以解决很多漏洞,既然要升,那就升到可升的最高版本;因为是基于 JDK8,所以 spring-boot 最高能升级到 2.7.8。那就升嘛,不要怂就是干!

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>

启动服务,第一个坑来了:NullPointerException

2025-05-30 21:13:42.264|ERROR|main|818|o.s.boot.SpringApplication              :Application run failed
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182)
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54)
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:357)
at java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:156)
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:124)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:946)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:594)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289)
at com.qsl.Application.main(Application.java:16)
Caused by: java.lang.NullPointerException: null
at springfox.documentation.spring.web.WebMvcPatternsRequestConditionWrapper.getPatterns(WebMvcPatternsRequestConditionWrapper.java:56)
at springfox.documentation.RequestHandler.sortedPaths(RequestHandler.java:113)
at springfox.documentation.spi.service.contexts.Orderings.lambda$byPatternsCondition$3(Orderings.java:89)
at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
at java.util.TimSort.sort(TimSort.java:220)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1454)
at java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:387)
at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:81)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.withDefaults(AbstractDocumentationPluginsBootstrapper.java:107)
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.buildContext(AbstractDocumentationPluginsBootstrapper.java:91)
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.bootstrapDocumentationPlugins(AbstractDocumentationPluginsBootstrapper.java:82)
at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:100)
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:179)
... 14 common frames omitted

遇到问题不要怕

查询问题并解决问题嘛;从哪查,我想大家已经达成了统一的共识:大数据模型deepseek 就是热门之一,我们直接将堆栈信息扔给他,让他提供解决方案。他一针见血分析出了原因

这个错误通常是由于 Springfox Swaggerspringfox-swagger2)与 Spring Boot 版本不兼容Spring MVC 路径匹配策略冲突 导致的。以下是几种解决方案

  1. 降级 Spring Boot 版本

    Spring Boot 2.6+ 开始与 springfox 不兼容,但 Springfox Swagger 2.x 已经停止维护了,所以说通过升级 Springfox Swagger 来适配 Spring Boot 2.6+ 是不行了。

    我们的目的是升级 Spring Boot,那么降级 Spring Boot 这个方案肯定是行不通的。

  2. 升级到 SpringDoc OpenAPI

    SpringDoc 是 Swagger 的替代方案,支持 OpenAPI 3.0,兼容 Spring Boot 2.6+ 和 3.x

    考虑到注解变动大,需要调整的地方太多,这个方案不到万不得已不采用

  3. 修改路径匹配策略

    如果不想降级 Spring Boot,可以调整路径匹配策略

    spring:
    mvc:
    pathmatch:
    matching-strategy: ant_path_matcher

    这个调整简单,感觉可行,试试发现雀氏可以,采用这种方案

  4. Swagger 配置是否正确

    确保 @EnableSwagger2Docket 配置正确


    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
    @Bean
    public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
    .select()
    .apis(RequestHandlerSelectors.basePackage("com.your.package")) // 替换成你的 Controller 包名
    .paths(PathSelectors.any())
    .build();
    }
    }

    这个确定是配置正确的,不是这个问题

deepseek 还给了其他方案,大家可以结合自己的实际情况,看看方案是否适用。如果你们以为坑就这么填平了,那只能说你们还是太年轻啦

我再加个依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

启动服务,同样的问题又来了

org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182)
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54)
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:357)
at java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:156)
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:124)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:946)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:594)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289)
at com.qsl.Application.main(Application.java:16)
Caused by: java.lang.NullPointerException: null
at springfox.documentation.spring.web.WebMvcPatternsRequestConditionWrapper.getPatterns(WebMvcPatternsRequestConditionWrapper.java:56)
at springfox.documentation.RequestHandler.sortedPaths(RequestHandler.java:113)
at springfox.documentation.spi.service.contexts.Orderings.lambda$byPatternsCondition$3(Orderings.java:89)
at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
at java.util.TimSort.sort(TimSort.java:220)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1454)
at java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:387)
at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:81)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.withDefaults(AbstractDocumentationPluginsBootstrapper.java:107)
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.buildContext(AbstractDocumentationPluginsBootstrapper.java:91)
at springfox.documentation.spring.web.plugins.AbstractDocumentationPluginsBootstrapper.bootstrapDocumentationPlugins(AbstractDocumentationPluginsBootstrapper.java:82)
at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:100)
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:179)
... 14 common frames omitted

同个问题出现一次也就算了,换个方式出现第二次,有点欺负人了!

此时我们再去问 deepseek,给出的解决方案,尝试了都不对,好在在网上找到了解决方案,增加如下配置

@Configuration
@EnableSwagger2
public class SwaggerConfig { /**
* springboot 2.7.x不支持swagger2,注册bean进行兼容
* 该方法在Spring Boot 2.7.x中手动注册WebMvcEndpointHandlerMapping,用于解决Swagger无法直接访问Actuator端点的问题。下面详细说明其作用:
* 1. 收集所有可暴露的端点
* 使用以下组件获取不同类型的端点:
* webEndpointsSupplier.getEndpoints():获取所有基于Web的端点(如/actuator/health)。
* servletEndpointsSupplier.getEndpoints():获取Servlet类型的端点(如/actuator/servlet)。
* controllerEndpointsSupplier.getEndpoints():获取Controller类型的端点。
* 将这些端点统一添加到allEndpoints列表中,以便后续处理。
* 2. 设置端点的基础路径
* 从WebEndpointProperties中获取配置的端点基础路径(basePath),默认值通常是/actuator。
* 创建一个EndpointMapping对象,并传入基础路径,用于定义端点的URL映射规则。
* 3. 判断是否需要注册端点链接映射
* 判断条件如下:
* 如果启用了端点发现(webEndpointProperties.getDiscovery().isEnabled())。
* 并且设置了有效的基础路径(StringUtils.hasText(basePath)),或者管理端口与应用端口不同(ManagementPortType.DIFFERENT)。
* 如果满足条件,则创建端点链接映射,用于生成包含所有可用端点的首页链接(例如/actuator)。
* 4. 构建并返回WebMvcEndpointHandlerMapping
* 创建WebMvcEndpointHandlerMapping实例时传入以下参数:
* endpointMapping:定义端点的基础路径。
* webEndpoints:需要注册的Web类型端点集合。
* endpointMediaTypes:定义端点支持的媒体类型(如JSON、YAML等)。
* corsConfiguration:跨域资源共享(CORS)配置。
* new EndpointLinksResolver(allEndpoints, basePath):用于生成端点链接的解析器。
* shouldRegisterLinksMapping:是否注册端点链接映射。
* null:通常用于指定自定义的请求谓词,此处为默认值。
* 返回的WebMvcEndpointHandlerMapping使Swagger能够正常访问和展示Actuator端点的信息。
* 5. 兼容性适配
* Spring Boot 2.7.x之后,Swagger 2不再直接支持访问Actuator端点,此方法通过手动注册WebMvcEndpointHandlerMapping来恢复兼容性,确保Swagger UI可以正确显示和调用这些监控和管理接口。
* 总结
* 此方法的核心目的是手动注册端点处理器映射,以确保Swagger能够正确访问Spring Boot Actuator提供的各种监控和管理端点。通过整合多种端点类型、设置基础路径、启用链接映射等方式,使得开发者能够在Swagger UI中方便地测试和使用这些端点。
*/
@Bean
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
ServletEndpointsSupplier servletEndpointsSupplier,
ControllerEndpointsSupplier controllerEndpointsSupplier,
EndpointMediaTypes endpointMediaTypes,
CorsEndpointProperties corsProperties,
WebEndpointProperties webEndpointProperties,
Environment environment) {
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
allEndpoints.addAll(webEndpoints);
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
String basePath = webEndpointProperties.getBasePath();
EndpointMapping endpointMapping = new EndpointMapping(basePath);
boolean shouldRegisterLinksMapping =
webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath)
|| ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath),
shouldRegisterLinksMapping, null);
}
}

启动服务,不再报错,Swagger UI 也能正常访问

也许你们会觉得这个坑解决的也快呀,没什么大不了的,可实际是项目中有众多的依赖,你如何知道是因为 spring-boot-starter-actuator 导致的?我实际排查这个问题的过程,可不是如上所说的那般容易,但有一点我们要清楚

我们遇到的坑,肯定有前辈遇到过

所以我们要做的是想清楚关键词,到大数据模型搜索,或者到搜索引擎搜索

总结

  1. 归根结底,还是 Springfox 没有去适配 Spring Boot 的升级,所以可能的话,还是推荐大家用 SpringDoc OpenAPI

  2. 不到万不得已,不要去升级组件

    坑我已经替你们踩过

    都说了能不动就别动,非要去调整,出生产事故了吧

    都说了能不动就别动,非要去调整,出生产事故了吧 → 补充

    都是血的教训,希望大家引以为戒

  3. 遇到问题,当下推荐的做法是用 大数据模型,关键词给的好,得到的回答八九不离十就是正确的解决方案

参考

SpringBoot 2.7.x 整合 swagger2 冲突问题

Swagger与SpringBoot冲突

安全漏洞修复导致SpringBoot2.7与Springfox不兼容,问题排查与处理的更多相关文章

  1. 织梦dedecms漏洞修复大全(5.7起)

    很多人说dedecms不好,因为用的人多了,找漏洞的人也多了,那么如果我们能修复的话,这些都不是问题. 好,我们来一个一个修复.修复方法都是下载目录下该文件,然后替换或添加部分代码,保存后上传覆盖(记 ...

  2. java中xxe漏洞修复方法

    java中禁止外部实体引用的设置方法不止一种,这样就导致有些开发者修复的时候采用的错误的方法 之所以写这篇文章是有原因的!最早是有朋友在群里发了如下一个pdf, 而当时已经是2019年1月末了,应该不 ...

  3. 360软件的木马查杀、漏洞修复等组件不能使用,提示runtime error

    一.故障现象:1.360软件的木马查杀.漏洞修复等组件不能使用,提示runtime error2.暴风影音等很多软件不能正常使用3.设备管理器不能打开,提示“MMC 不能打开文件”4.部分https安 ...

  4. 转载两篇dedecms的漏洞修复教程

    Dedecms安全步骤,安装之后的操作 1 将文件夹dede改名为其他,比如 /256256.com/ 2 搜索ad.dedecms.com,文件D:\WebSite\256256.com\www\g ...

  5. Nginx range filter模块数字错误漏洞修复 (Nginx平滑升级) 【转】

    对线上生产环境服务器进行漏洞扫描, 发现有两台前置机器存在Nginx range filter模块数字错误漏洞, 当使用nginx标准模块时,攻击者可以通过发送包含恶意构造range域的header ...

  6. Nginx range filter模块数字错误漏洞修复 (Nginx平滑升级)

    对线上生产环境服务器进行漏洞扫描, 发现有两台前置机器存在Nginx range filter模块数字错误漏洞, 当使用nginx标准模块时,攻击者可以通过发送包含恶意构造range域的header ...

  7. Struts2 高危漏洞修复方案 (S2-016/S2-017)

    近期Struts2被曝重要漏洞,此漏洞影响struts2.0-struts2.3所有版本,可直接导致服务器被远程控制从而引起数据泄漏,影响巨大,受影响站点以电商.银行.门户.政府居多. 官方描述:S2 ...

  8. 网站漏洞修复案例之Discuz!3.4最新版本

    Discuz!论坛目前最新版本为3.4版本,已经好久没有更新了,我们SINE安全在对其网站安全检测的同时发现一处漏洞,该漏洞可导致论坛的后台文件可以任意的删除,导致网站瘫痪,后台无法登陆.关于该网站漏 ...

  9. 苹果cms网站漏洞修复解决办法

    苹果cms系统,是目前很多电影网站都在使用的一套网站系统,开源,免费,扩展性较好,支持一键采集,伪静态化,高并发的同时承载,获得的很多站长的喜欢,于近日被网站安全检测发现,maccms存在网站漏洞,s ...

  10. wordpress网站程序漏洞修复办法

    近日wordpress被爆出高危的网站漏洞,该漏洞可以伪造代码进行远程代码执行,获取管理员的session以及获取cookies值,漏洞的产生是在于wordpress默认开启的文章评论功能,该功能在对 ...

随机推荐

  1. php stripslashes 函数的意思

    脑子不行了,很多东西看过就忘,比如这个stripslashes,知道是去除反斜杠,但为啥用它死活想不起来,搜索一下,把这几篇文章抄下来: 1.反斜杠是怎么回事 两个东西 ini_set(magic_q ...

  2. python 二级 语言基本元素笔记-字符串

    l='12345' 1.递增顺序: 正向递增从0开始 负向从[-1]开始,l[1]=2,l[-1]=5 2.切片操作:左开右闭,l[2:5]=3,4 3.导入库,引入 库名.函数名 input函数 输 ...

  3. antd vue 嵌套表格之实现每次展开一行

    在项目中遇到一个需求,就是使用嵌套子表格时,每次只展示一行,且展开一行另一行收起,直接上代码吧,顺便记录一下 这里需要注意,我们要在外层table组件添加如图三个属性,缺一不可,咳咳,不用杠我那个&l ...

  4. go-ini 中文文档

    简介 地表 最强大.最方便 和 最流行 的 Go 语言 INI 文件操作库 灵活的数据源 不光光可以从文件读取配置,还支持 []byte 类型的纯数据读取和基于 io.ReadCloser 的流式读取 ...

  5. nginx启动失败 Starting nginx nginx [fail]

    nginx -t :测试配置文件是否有语法错误 看看报什么错误,我的是忘记给权限了 nginx: [alert] could not open error log file: open() " ...

  6. maven知识理解和生命周期

    学习的技能/知识 运动 提升 不足 强化了maven的知识理解和生命周期 3公里日常跑,其中1公里破之前的记录达到3分40 没有赖床,嗯:写完的博客自己阅读又温习了一遍 下午没课,但都用来休息了.. ...

  7. 【C#】Winform监听USB串口设备拔插实现自动断开

    [C#]Winform监听USB串口设备拔插 零.问题 最近在开发串口相关的软件,需要检测串口拔掉后主动关闭串口,因此需要检测到USB的拔插事件. 一.解决 在主窗口From类下覆盖WndProc方法 ...

  8. IntelliJ IDEA 社区版没有 Spring Initializr

    RT 解决办法 打开文件 - 设置 - 插件 输入 Spring 找到插件 Spring Assistant 并安装 下载可能会需要一点点时间. 重启 IDEA 后,新建项目就可以看见 Spring ...

  9. iOS Facebook和Google登录

    前言 最近在对接完Google和Facebook登录之后准备对这部分内容做一个小小的总结,方便以后有需要的时候查看. 具体的Google账号申请和Facebook账号的申请在这里就不做介绍了,这部分内 ...

  10. JAVA基础之多线程三期--线程安全问题

    一.线程安全问题就是指:多个线程并发访问同一个资源而发生安全性的问题, 线程安全问题都是由全局变量及静态变量引起的. 若每个线程中对全局变量.静态变量只有读操作,而无写 操作,一般来说,这个全局变量是 ...