遗传算法框架-基于java jenetics库实现
本篇并非介绍如何从0开始开发遗传算法框架,反而推荐各位使用已有的GA库jenetics来做遗传算法。
GA算法的逻辑还是贴下:

好了,下面介绍的是基于jenetics开发的更贴近业务侧的框架,以及使用方法。
pom依赖,毕竟java的嘛,就不要用matlab、R、python这些了
<!-- https://mvnrepository.com/artifact/io.jenetics/jenetics -->
<dependency>
<groupId>io.jenetics</groupId>
<artifactId>jenetics</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>io.jenetics</groupId>
<artifactId>jenetics.ext</artifactId>
<version>5.1.0</version>
</dependency>
先看看我们提供的这个框架,能怎样简化业务侧代码吧:
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5); //需要指定一个线程池,因为GA算法需要很多运算
Demo1SolutionConverter demo1SolutionConverter = new Demo1SolutionConverter(); //这个class中定义了GA算法所需的底层基因序列的定义、以及业务解决方案class与基因的互相转换逻辑
Demo1FitnessBuilder fitnessBuilder = new Demo1FitnessBuilder(); //这个class定义了适应度函数的指向(遗传算法非常依赖适应度函数,非常非常依赖,重中之重)
EngineInvokeOptions options = new EngineInvokeOptions(); //引擎调用默认参数,如需改写默认参数单独修改即可
options.setFitnessBuilder(fitnessBuilder);
options.setEnableMaxLimits(true); //设置为停止条件为最大种群次数限制
options.setMaxLimits(20); //设置为最大次数限制为20次,既:20次种群迭代
for(int idx=0;idx<20;idx++) { //连续执行20次看效果
MinMaxScaler minMaxScaler = new MinMaxScaler(100, false);
GAEngine gaEngine = new GAEngine(50, executorService);
Demo1SolutionConverter.Demo1Solution solution = (Demo1SolutionConverter.Demo1Solution) gaEngine.generate(demo1SolutionConverter, minMaxScaler, options);
System.out.println(solution.toString());
}
executorService.shutdown();
}
我们先看看核心class:Demo1SolutionConverter,这个是每个业务都不同的地方,需要单独业务单独编码
public class Demo1SolutionConverter extends DefaultSolutionConverter { //DefaultSolutionConverter是框架里的默认实现,已经实现了很多默认方法
@Override
public AbstractSolution convert2Solution(EvolvingSolutionInfo solutionInfo) {
Demo1Solution solution=new Demo1Solution();
solution.setFitnessValues(solutionInfo.getFitnessValues());
Genotype<IntegerGene> geneMap=solutionInfo.getMap(); //这个是获取基因架
Chromosome<IntegerGene> chromosome=geneMap.getChromosome(); //获取默认的也就是第一个基因条
for(int idx=0;idx<chromosome.length();idx++) //开始业务解码
{
IntegerGene integerGene=chromosome.getGene(idx);
if(integerGene.intValue()==1)
{
solution.getSelectedIds().add(idx); //这里实现的解码逻辑:共10个数字,有2种可能0和1,0代表不选中,1代表选中,选中了就会加入selectedIds这个List里
}
}
return solution;
}
@Override
public Genotype<IntegerGene> loadGenotype() { //这个是唯一一个DefaultSolutionConverter种的抽象方法,必须实现,用来定义基因序列的组成
Genotype<IntegerGene> genotype=Genotype.of(
IntegerChromosome.of(0, 1, IntRange.of(10)) //10个基因,每个基因只有2种可能,0或者1
);
return genotype;
}
public double test(AbstractSolution solution) //这个是适应度函数定义,要注意入参和出参,这2个是固定的
{ //test是method名,待会会在后面介绍,会在其他class中指定过来
Demo1Solution s=(Demo1Solution)solution;
long 偶数个数=s.getSelectedIds().stream().filter(f->f%2==0).count();
long 奇数个数=s.getSelectedIds().stream().filter(f->f%2!=0).count();
double score=(-偶数个数)+(+奇数个数); //score是适应度函数的分值,越小越优,由于我们希望不要奇数、只要偶数,所以偶数部分为负号、奇数部分为正号
return score;
}
@Data
public class Demo1Solution extends DefaultSolution { //这个是业务解码后存放的class,很好理解
private List<Integer> selectedIds=new ArrayList<>();
@Override
public String toString() {
StringBuilder stringBuilder=new StringBuilder();
for(int id:selectedIds)
{
stringBuilder.append(id);
stringBuilder.append(", ");
}
return stringBuilder.toString();
}
}
}
然后再看看Demo1FitnessBuilder类,既:适应度函数指向类:
public class Demo1FitnessBuilder implements FitnessBuilder {
@Override
public Tuple2<Map<String, Object>, List<Tuple3<String, String, Double>>> build() {
Map<String, Object> objConfigs= buildObjectAndConfigs();
List<Tuple3<String, String, Double>> fitnessConfigs=buildFitnessConfigs();
return Tuples.of(objConfigs, fitnessConfigs);
}
private Map<String, Object> buildObjectAndConfigs() {
Map<String, Object> configs=new HashMap<>();
Demo1SolutionConverter obj=new Demo1SolutionConverter(); //这里定义的是n个适应度函数所在的对象(此处只定义了1个,也可以多个)
configs.put("obj", obj);
return configs;
}
private List<Tuple3<String, String, Double>> buildFitnessConfigs() {
List<Tuple3<String, String, Double>> fitnessConfigs = new ArrayList<>();
fitnessConfigs.add(Tuples.of("obj", "test", 1D)); //obj和上面的对应,test指明了适应度函数是在obj这个对象中方法名为test的函数
//此处也可以多个
//1D代表默认权重,也可以定期较低的权重,比如:0.5D这种
return fitnessConfigs;
}
}
看看程序的输出:
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 3, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
如同大家所见,GA算法的问题在于不太稳定,只能代表一种优化趋势,导致这样的原因有很多,最重要的原因还是在于智能算法一般使用的场景都是由于传统算法无能为力的场景,或者无法穷举的场景。
下面看看加大种群迭代次数是否能解决:
options.setMaxLimits(100);
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
算是表面解决了,但其实还有很多因素能导致不稳定,比如,我们从当前的10个数字,enlarge到50个数字,会怎样:
@Override
public Genotype<IntegerGene> loadGenotype() {
Genotype<IntegerGene> genotype=Genotype.of(
IntegerChromosome.of(0, 1, IntRange.of(50))
); return genotype;
}
0, 2, 4, 5, 6, 8, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 35, 36, 38, 40, 41, 42, 44, 46,
0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
2, 4, 5, 6, 8, 10, 12, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 6, 8, 10, 12, 14, 16, 18, 22, 24, 26, 28, 30, 32, 34, 35, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 8, 14, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41, 42, 44, 46, 48,
0, 2, 4, 5, 6, 8, 10, 12, 14, 15, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 47, 48, 49,
0, 2, 4, 6, 8, 10, 12, 13, 14, 16, 18, 20, 22, 24, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46,
0, 2, 4, 6, 8, 10, 12, 13, 16, 18, 19, 22, 24, 26, 28, 30, 31, 32, 36, 38, 40, 42, 43, 44, 45, 46, 48,
0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 21, 22, 24, 25, 26, 28, 30, 32, 34, 38, 40, 42, 44, 45, 46, 48,
0, 1, 2, 4, 5, 6, 8, 10, 11, 12, 14, 16, 18, 20, 21, 22, 23, 24, 26, 28, 30, 32, 36, 38, 40, 42, 44, 46, 48,
2, 4, 6, 8, 10, 12, 14, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 44, 46, 48,
0, 2, 6, 8, 10, 12, 14, 18, 20, 22, 24, 26, 28, 32, 34, 36, 38, 40, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 38, 40, 42, 43, 44, 46, 48, 49,
0, 2, 4, 6, 8, 9, 10, 12, 14, 18, 22, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 45, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 22, 24, 26, 32, 34, 36, 38, 40, 42, 44, 45, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 24, 26, 28, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 13, 14, 16, 18, 20, 22, 24, 26, 28, 31, 32, 34, 38, 40, 42, 45, 46, 48,
0, 2, 4, 6, 8, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 27, 29, 30, 32, 34, 36, 38, 40, 46, 48,
0, 4, 6, 8, 10, 12, 14, 16, 20, 22, 24, 25, 26, 28, 30, 32, 34, 36, 38, 40, 44, 46, 48,
0, 2, 4, 8, 10, 12, 14, 16, 18, 20, 21, 22, 24, 26, 28, 32, 34, 36, 38, 40, 42, 44, 46, 48,
哇塞,简直了,这结果。。。
再来:
options.setMaxLimits(2000);
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
体会到了不确定的痛苦了吗?
再来:
// options.setEnableMaxLimits(true);
// options.setMaxLimits(2000);
options.setEnableSteadyFitness(true); //设置为稳定适应度函数值默认
options.setSteadyFitnessValue(1000); //当连续1000次的种群迭代的最优适应度函数值都稳定的时候,稳定就是分值没有超越当前的最好分值,然后才停止算法
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
遗传算法是非常耗费算力的,能其他算法就尽量其他算法来做,真的。虽然GA也有很多优点,比如:
- 当无法穷举时,这个算法就是好的
- 当数据量较少时,这个算法也挺稳定(要调好参数)
- 当计算什么是好,什么是坏时的逻辑是非线性的时候,GA算法也是个很好的选项
完整代码下载,带demo+自研框架+底层是jenetics
遗传算法框架-基于java jenetics库实现的更多相关文章
- 自定义RPC框架--基于JAVA实现
视频教程地址 DT课堂(原名颜群) 整体思路RPC(Remote Procedure Call),即远程过程调用.使用RPC,可以像使用本地的程序一样使用远程计算机上的程序.RPC使得开发分布式程序更 ...
- 完全开源Android网络框架 — 基于JAVA原生的HTTP框架
HttpNet网络请求框架基于HttpUrlConnection,采用Client + Request + Call的请求模型,支持https默认证书,数字安全证书.支持http代理!后续将会实现队列 ...
- 【原创】三分钟教你学会MVC框架——基于java web开发(2)
没想到我的上一篇博客有这么多人看,还有几位看完之后给我留言加油,不胜感激,备受鼓励,啥都别说了,继续系列文章之第二篇.(如果没看过我第一篇博客的朋友,可以到我的主页上先浏览完再看这篇文章,以免上下文对 ...
- 【原创】三分钟教你学会MVC框架——基于java web开发(1)
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用于组织代码用一种业务逻辑和数据显示分离的方法. ...
- 基于java.util.logging实现轻量级日志记录库(增加根据当前类class初始化,修复线程池模型(javaEE)下的堆栈轨迹顺序与当前调用方法不一致问题)
前言: 本章介绍自己写的基于java.util.logging的轻量级日志记录库(baseLog). 该版本的日志记录库犹如其名,baseLog,是个实现日志记录基本功能的小库,适合小型项目使用,方便 ...
- 基于java spring框架开发部标1078视频监控平台精华文章索引
部标1078视频监控平台,是一个庞杂的工程,涵盖了多层协议,部标jt808,jt809,jt1078,苏标Adas协议等,多个平台功能标准,部标796标准,部标1077标准和苏标主动安全标准,视频方面 ...
- 9个基于Java的搜索引擎框架
在这个信息相当繁杂的互联网时代,我们已经学会了如何利用搜索引擎这个强大的利器来找寻目标信息,比如你会在Google上搜索情人节如何讨女朋友欢心,你也会在百度上寻找正规的整容医疗机构(尽管有很大一部分广 ...
- 基于Java Netty框架构建高性能的部标808协议的GPS服务器
使用Java语言开发一个高质量和高性能的jt808 协议的GPS通信服务器,并不是一件简单容易的事情,开发出来一段程序和能够承受数十万台车载接入是两码事,除去开发部标808协议的固有复杂性和几个月长周 ...
- 基于Java Mina框架的部标808服务器设计和开发
在开发部标GPS平台中,部标808GPS服务器是系统的核心关键,决定了部标平台的稳定性和行那个.Linux服务器是首选,为了跨平台,开发语言选择Java自不待言. 我们为客户开发的部标服务器基于Min ...
随机推荐
- 深入理解JVM(一)Java内存区域
运行时数据区 程序计数器 当前线程执行的字节码的行号指示器 每条线程都有独立的程序计数器,各线程之间计数器互不影响,独立存储. 如果执行的是java方法,计数器记录正在执行的虚拟机字节码指令的位置: ...
- 分布式ID生成服务,真的有必要搞一个
目录 阐述背景 Leaf snowflake 模式介绍 Leaf segment 模式介绍 Leaf 改造支持RPC 阐述背景 不吹嘘,不夸张,项目中用到ID生成的场景确实挺多.比如业务要做幂等的时候 ...
- BUUCTF-web ZJCTF,不过如此
很明显要利用伪协议读next.php base64解码后查看源码 <?php $id = $_GET['id']; $_SESSION['id'] = $id; function complex ...
- 并发系列(二)——FutureTask类源码简析
背景 本文基于JDK 11,主要介绍FutureTask类中的run().get()和cancel() 方法,没有过多解析相应interface中的注释,但阅读源码时建议先阅读注释,明白方法的主要的功 ...
- 关于docker--详解安装,常规操作,导入导出等(2017-3-29)
测试环境 :CentOS 7.1 64位 目的:展示docker的常规使用(安装,常规操作,导入导出等) 其他:关于原理等请参考文章后面的延伸阅读,本文不做深入探讨,且方法不唯一 0x01 关于安装d ...
- Django学习路8_学生表和班级表级联并相互查询信息
在创建好的 app3 目录下的 models.py 中 创建对 数据表(学生和班级)的描述 分析: 学生和班级是一对多的关系 班级表的设计 class Grade(models.Model): # 设 ...
- Python time asctime()方法
描述 Python time asctime() 函数接受时间元组并返回一个可读的形式为"Tue Dec 11 18:07:14 2008"(2008年12月11日 周二18时07 ...
- PDOStatement::closeCursor
PDOStatement::closeCursor — 关闭游标,使语句能再次被执行.(PHP 5 >= 5.1.0, PECL pdo >= 0.9.0) 说明 语法 bool PDOS ...
- 加载Properties文件工具类:LoadConfig
import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; impor ...
- Spring Security和Swagger2集成报错
出现问题的项目算是一个新项目,但基本的脚手架代码是从另一个项目里迁过来的,原项目并没有报错,只有新项目才报异常.看报错内容,判断发生冲突的主要是spring-boot-starter-security ...