描述问题:通过调用snakeyaml的api生产了yaml的配置文件,然后将生成的yaml配置文件放到spring boot 的bootstrap.yml 配置文件中,启动项目,程序报错。
问题结论:Spring Boot 集成snakeyaml 但却没用snakeyaml 对set集合中复杂对象的解析,自己封装了一套解析方案,导致Spring Boot 加载yaml时对set集合中复杂对象解析失败。
疑问:是Spring Boot 压根没有想对这种类型支持,还是Spring Boot的Bug?有大佬给解答下吗?
虽然通过Spring Boot和snakeyaml 对比将问题解决,但感觉很麻烦,还修改了源码。
1. 通过调用snakeyaml的api,生产yaml的配置文件,如下:
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import java.util.Set;
public class ApiDefinitionExt extends ApiDefinition implements Comparable<ApiDefinitionExt> {
private String apiNameExt;
private Set<ApiPredicateItem> predicateItemsExt;
public ApiDefinitionExt() {
public ApiDefinitionExt(String apiNameExt) {
super(apiNameExt);
this.apiNameExt = apiNameExt;
public String getApiNameExt() {
return super.getApiName();
public void setApiNameExt(String apiNameExt) {
super.setApiName(apiNameExt);
this.apiNameExt = apiNameExt;
public Set<ApiPredicateItem> getPredicateItemsExt() {
return super.getPredicateItems();
public void setPredicateItemsExt(Set<ApiPredicateItem> predicateItemsExt) {
super.setPredicateItems(predicateItemsExt);
this.predicateItemsExt = predicateItemsExt;
@Override
public int compareTo(ApiDefinitionExt o) {
return apiNameExt.compareTo(o.apiNameExt);
import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
public class ApiPathPredicateItemExt implements ApiPredicateItem, Comparable<ApiPathPredicateItemExt> {
private String pattern;
private int matchStrategy = SentinelGatewayConstants.URL_MATCH_STRATEGY_EXACT;
public String getPattern() {
return pattern;
public void setPattern(String pattern) {
this.pattern = pattern;
public int getMatchStrategy() {
return matchStrategy;
public void setMatchStrategy(int matchStrategy) {
this.matchStrategy = matchStrategy;
@Override
public int compareTo(ApiPathPredicateItemExt o) {
return pattern.compareTo(o.pattern);
import java.util.Set;
import java.util.TreeSet;
import org.yaml.snakeyaml.Yaml;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.gateway.config.sentinel.ApiDefinitionExt;
import com.gateway.config.sentinel.ApiPathPredicateItemExt;
import junit.framework.TestCase;
public class SnakeyamlBeanToYaml extends TestCase {
public void testBeanToYaml() {
Set<ApiPredicateItem> predicateItems = new TreeSet<ApiPredicateItem>();
ApiPathPredicateItemExt ext1 = new ApiPathPredicateItemExt();
ext1.setPattern("/ahas");
predicateItems.add(ext1);
ApiPathPredicateItemExt ext2 = new ApiPathPredicateItemExt();
ext2.setPattern("/product/**");
ext2.setMatchStrategy(1);
predicateItems.add(ext2);
ApiDefinitionExt apiDefinition = new ApiDefinitionExt();
apiDefinition.setApiNameExt("some_customized_api");
apiDefinition.setPredicateItemsExt(predicateItems);
Set<ApiPredicateItem> predicateItems2 = new TreeSet<ApiPredicateItem>();
ApiPathPredicateItemExt ext3 = new ApiPathPredicateItemExt();
ext3.setPattern("/**");
ext3.setMatchStrategy(1);
predicateItems2.add(ext3);
ApiDefinitionExt apiDefinition1 = new ApiDefinitionExt();
apiDefinition1.setApiNameExt("another_customized_api");
apiDefinition1.setPredicateItemsExt(predicateItems2);
Set<ApiDefinitionExt> definitions = new TreeSet<ApiDefinitionExt>();
definitions.add(apiDefinition);
definitions.add(apiDefinition1);
ApiDefinitionConfigProperties apiDefinitionConfig = new ApiDefinitionConfigProperties();
apiDefinitionConfig.setApiDefinitionExt(definitions);
Yaml yaml = new Yaml();
String output = yaml.dumpAsMap(apiDefinitionConfig);
System.out.println(output);
通过测试类SnakeyamlBeanToYaml生成的yaml配置文件,如下:
apiDefinitionExt: !!set
? apiNameExt: another_customized_api
predicateItemsExt: !!set
? !!com.gateway.config.sentinel.ApiPathPredicateItemExt
matchStrategy: 1
pattern: /**
: null
: null
? apiNameExt: some_customized_api
predicateItemsExt: !!set
? !!com.gateway.config.sentinel.ApiPathPredicateItemExt
matchStrategy: 0
pattern: /ahas
: null
? !!com.gateway.config.sentinel.ApiPathPredicateItemExt
matchStrategy: 1
pattern: /product/**
: null
: null
2. 将配置文件复制到的bootstrap.yml 配置文件中,然后自定义配置类加载Yaml
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.gateway.config.sentinel.ApiDefinitionExt;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Component
@ConfigurationProperties("api")
public class ApiDefinitionConfigProperties {
private Set<ApiDefinitionExt> apiDefinitionExt;
public Set<ApiDefinitionExt> getApiDefinitionExt() {
return apiDefinitionExt;
public void setApiDefinitionExt(Set<ApiDefinitionExt> apiDefinitionExt) {
this.apiDefinitionExt = apiDefinitionExt;
apiDefinitionExt: !!set
? apiNameExt: another_customized_api
predicateItemsExt: !!set
? !!com.gateway.config.sentinel.ApiPathPredicateItemExt
matchStrategy: 1
pattern: /**
: null
: null
? apiNameExt: some_customized_api
predicateItemsExt: !!set
? !!com.gateway.config.sentinel.ApiPathPredicateItemExt
matchStrategy: 0
pattern: /ahas
: null
? !!com.gateway.config.sentinel.ApiPathPredicateItemExt
matchStrategy: 1
pattern: /product/**
: null
: null
然后启动SpringBoot项目报错:
Caused by: org.yaml.snakeyaml.constructor.ConstructorException: could not determine a constructor for the tag tag:yaml.org,2002:com.gateway.config.sentinel.ApiPathPredicateItemExt
in 'reader', line 104, column 15:
? !!com.gateway.config.sentin ...
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructUndefined.construct(SafeConstructor.java:576)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.SafeConstructor.processDuplicateKeys(SafeConstructor.java:91)
at org.yaml.snakeyaml.constructor.SafeConstructor.flattenMapping(SafeConstructor.java:76)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructSet2ndStep(SafeConstructor.java:195)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructSet(BaseConstructor.java:457)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlSet.construct(SafeConstructor.java:505)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:482)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:190)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:463)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:556)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.SafeConstructor.processDuplicateKeys(SafeConstructor.java:91)
at org.yaml.snakeyaml.constructor.SafeConstructor.flattenMapping(SafeConstructor.java:76)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructSet2ndStep(SafeConstructor.java:195)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructSet(BaseConstructor.java:457)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlSet.construct(SafeConstructor.java:505)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:482)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:190)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:463)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:556)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:482)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:190)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:463)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:556)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:482)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:190)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:463)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:556)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:482)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:190)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:463)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:556)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:174)
at org.yaml.snakeyaml.constructor.BaseConstructor.getData(BaseConstructor.java:139)
at org.yaml.snakeyaml.Yaml$1.next(Yaml.java:494)
at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:200)
at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:164)
at org.springframework.boot.env.OriginTrackedYamlLoader.l
4.查看源码分析问题:
上面说了Spring Boot 自己封装了自己Yaml解析方式, 这里涉及到一个类OriginTrackedYamlLoader 。以及snakeyaml 本身对Yaml解析方式,下面对比下发现,SpringBoot 创建Yaml对象时的第一个参数BaseConstructor 参入的是自己定义的OriginTrackingConstructor,而snakeyaml 用的是 Constructor对象,他们都是SafeConstructor的子类但内部实现方式却不同,Constructor对Set集合复杂对象有解析,但用OriginTrackingConstructor却不支持,因为它没有对应set复杂对象的解析对象 ConstructYamlObject,所以会报错。
* Class to load {@code .yml} files into a map of {@code String} to
* {@link OriginTrackedValue}.
* @author Madhura Bhave
* @author Phillip Webb
class OriginTrackedYamlLoader extends YamlProcessor {
@Override
protected Yaml createYaml() {
LoaderOptions loaderOptions = new LoaderOptions();
loaderOptions.setAllowDuplicateKeys(false);
loaderOptions.setMaxAliasesForCollections(Integer.MAX_VALUE);
loaderOptions.setAllowRecursiveKeys(true);
return createYaml(loaderOptions);
private Yaml createYaml(LoaderOptions loaderOptions) {
BaseConstructor constructor = new OriginTrackingConstructor(loaderOptions);
Representer representer = new Representer();
DumperOptions dumperOptions = new DumperOptions();
LimitedResolver resolver = new LimitedResolver();
// Yaml对象的创建
return new Yaml(constructor, representer, dumperOptions, loaderOptions, resolver);
* {@link Constructor} that tracks property origins.
private class OriginTrackingConstructor extends SafeConstructor{
OriginTrackingConstructor(LoaderOptions loadingConfig) {
super(loadingConfig);
@Override
protected Object constructObject(Node node) {
if (node instanceof ScalarNode) {
if (!(node instanceof KeyScalarNode)) {
return constructTrackedObject(node, super.constructObject(node));
else if (node instanceof MappingNode) {
replaceMappingNodeKeys((MappingNode) node);
return super.constructObject(node);
private void replaceMappingNodeKeys(MappingNode node) {
node.setValue(node.getValue().stream().map(KeyScalarNode::get).collect(Collectors.toList()));
private Object constructTrackedObject(Node node, Object value) {
Origin origin = getOrigin(node);
return OriginTrackedValue.of(getValue(value), origin);
private Object getValue(Object value) {
return (value != null) ? value : "";
private Origin getOrigin(Node node) {
Mark mark = node.getStartMark();
Location location = new Location(mark.getLine(), mark.getColumn());
return new TextResourceOrigin(OriginTrackedYamlLoader.this.resource, location);
对比snakeyaml 源码Yaml对象的创建,代码如下:
public class Yaml {
* Create Yaml instance.
public Yaml() {
this(new Constructor(), new Representer(), new DumperOptions(), new LoaderOptions(),
new Resolver());
这里我们修改Spring Boot OriginTrackedYamlLoader 的源码,让它可以返回可以解析set对象的ConstructYamlObject对象,这类是把OriginTrackingConstructor 的继承类换成了Constructor,如下:
* Class to load {@code .yml} files into a map of {@code String} to
* {@link OriginTrackedValue}.
* @author Madhura Bhave
* @author Phillip Webb
class OriginTrackedYamlLoader extends YamlProcessor {
* {@link Constructor} that tracks property origins.
* 这里我们把SafeConstructor修改为Constructor,让它在调用super.constructObject(node)时针
* 对Set复杂集合可以返回ConstructYamlObject对象
private class OriginTrackingConstructor extends Constructor{
OriginTrackingConstructor(LoaderOptions loadingConfig) {
super(loadingConfig);
@Override
protected Object constructObject(Node node) {
if (node instanceof ScalarNode) {
if (!(node instanceof KeyScalarNode)) {
return constructTrackedObject(node, super.constructObject(node));
else if (node instanceof MappingNode) {
replaceMappingNodeKeys((MappingNode) node);
return super.constructObject(node);
修改完代码启动程序,上面的报错不在显示,但又引入了新的问题,参数类型不匹配,出现这个问题是,OriginTrackingConstructor对数据进行了二次封装,通过方法 constructObject方法将Node对象转化为了OriginTrackedValue对象了,这时snakeyaml 中Constructor通过反射映射值时类型不匹配,导致matchStrategy对应的int类型变成了OriginTrackedValue对象,所以有问题,这里我们修改下Constructor的源码。
Caused by: org.yaml.snakeyaml.constructor.ConstructorException: Cannot create property=matchStrategy for JavaBean=com.gateway.config.sentinel.ApiPathPredicateItemExt@f79e
in 'reader', line 104, column 15:
? !!com.gateway.config.sentin ...
argument type mismatch
in 'reader', line 105, column 30:
matchStrategy: 1
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2ndStep(Constructor.java:297)
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.construct(Constructor.java:172)
at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:336)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.SafeConstructor.processDuplicateKeys(SafeConstructor.java:91)
at org.yaml.snakeyaml.constructor.SafeConstructor.flattenMapping(SafeConstructor.java:76)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructSet2ndStep(SafeConstructor.java:195)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructSet(BaseConstructor.java:457)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlSet.construct(SafeConstructor.java:505)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:482)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:190)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:463)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:556)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.SafeConstructor.processDuplicateKeys(SafeConstructor.java:91)
at org.yaml.snakeyaml.constructor.SafeConstructor.flattenMapping(SafeConstructor.java:76)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructSet2ndStep(SafeConstructor.java:195)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructSet(BaseConstructor.java:457)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlSet.construct(SafeConstructor.java:505)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:482)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:190)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:463)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:556)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:482)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:190)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:463)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:556)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:482)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:190)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:463)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:556)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:482)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:190)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:463)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:556)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:234)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:105)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:174)
at org.yaml.snakeyaml.constructor.BaseConstructor.getData(BaseConstructor.java:139)
at org.yaml.snakeyaml.Yaml$1.next(Yaml.java:494)
at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:200)
at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:164)
at org.springframework.boot.env.OriginTrackedYamlLoader.load(OriginTrackedYamlLoader.java:82)
at org.springframework.boot.env.YamlPropertySourceLoader.load(YamlPropertySourceLoader.java:50)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.loadDocuments(ConfigFileApplicationListener.java:607)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.load(ConfigFileApplicationListener.java:523)
... 37 common frames omitted
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.yaml.snakeyaml.introspector.MethodProperty.set(MethodProperty.java:77)
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2ndStep(Constructor.java:290)
... 102 common frames omitted
修改Constructor的源码在方法constructJavaBean2ndStep里中加入如下判断代码:
if(null != value && value instanceof OriginTrackedValue){
OriginTrackedValue originTrackedValue = (OriginTrackedValue)value;
value = originTrackedValue.getValue();
对应完整代码如下:
package org.yaml.snakeyaml.constructor;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.springframework.boot.origin.OriginTrackedValue;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;
* Construct a custom Java instance.
public class Constructor extends SafeConstructor {
protected Object constructJavaBean2ndStep(MappingNode node, Object object) {
flattenMapping(node);
Class<? extends Object> beanType = node.getType();
List<NodeTuple> nodeValue = node.getValue();
for (NodeTuple tuple : nodeValue) {
ScalarNode keyNode;
if (tuple.getKeyNode() instanceof ScalarNode) {
// key must be scalar
keyNode = (ScalarNode) tuple.getKeyNode();
} else {
throw new YAMLException(
"Keys must be scalars but found: " + tuple.getKeyNode());
Node valueNode = tuple.getValueNode();
// keys can only be Strings
keyNode.setType(String.class);
String key = (String) constructObject(keyNode);
try {
TypeDescription memberDescription = typeDefinitions.get(beanType);
Property property = memberDescription == null ? getProperty(beanType, key)
: memberDescription.getProperty(key);
if (!property.isWritable()) {
throw new YAMLException("No writable property '" + key + "' on class: "
+ beanType.getName());
valueNode.setType(property.getType());
final boolean typeDetected = (memberDescription != null)
? memberDescription.setupPropertyType(key, valueNode)
: false;
if (!typeDetected && valueNode.getNodeId() != NodeId.scalar) {
// only if there is no explicit TypeDescription
Class<?>[] arguments = property.getActualTypeArguments();
if (arguments != null && arguments.length > 0) {
// type safe (generic) collection may contain the
// proper class
if (valueNode.getNodeId() == NodeId.sequence) {
Class<?> t = arguments[0];
SequenceNode snode = (SequenceNode) valueNode;
snode.setListType(t);
} else if (Set.class.isAssignableFrom(valueNode.getType())) {
Class<?> t = arguments[0];
MappingNode mnode = (MappingNode) valueNode;
mnode.setOnlyKeyType(t);
mnode.setUseClassConstructor(true);
} else if (Map.class.isAssignableFrom(valueNode.getType())) {
Class<?> ketType = arguments[0];
Class<?> valueType = arguments[1];
MappingNode mnode = (MappingNode) valueNode;
mnode.setTypes(ketType, valueType);
mnode.setUseClassConstructor(true);
Object value = (memberDescription != null)
? newInstance(memberDescription, key, valueNode)
: constructObject(valueNode);
// 在这里我们加入如下判断针对object为OriginTrackedValue对象时
if(null != value && value instanceof OriginTrackedValue){
OriginTrackedValue originTrackedValue = (OriginTrackedValue)value;
value = originTrackedValue.getValue();
// Correct when the property expects float but double was
// constructed
if (property.getType() == Float.TYPE || property.getType() == Float.class) {
if (value instanceof Double) {
value = ((Double) value).floatValue();
// Correct when the property a String but the value is binary
if (property.getType() == String.class && Tag.BINARY.equals(valueNode.getTag())
&& value instanceof byte[]) {
value = new String((byte[]) value);
if (memberDescription == null
|| !memberDescription.setProperty(object, key, value)) {
property.set(object, value);
} catch (DuplicateKeyException e) {
throw e;
} catch (Exception e) {
throw new ConstructorException(
"Cannot create property=" + key + " for JavaBean=" + object,
node.getStartMark(), e.getMessage(), valueNode.getStartMark(), e);
return object;
在启动项目,正常的启动成功。
描述问题:通过调用snakeyaml的api生产了yaml的配置文件,然后将生成的yaml配置文件放到spring boot 的bootstrap.yml 配置文件中,启动项目,程序报错。问题结论:Spring Boot 集成snakeyaml 但却没用snakeyaml 对set集合中复杂对象的解析,自己封装了一套解析方案,导致Spring Boot 加载yaml时对set集合中复杂对象解析失败。疑问:是Spring Boot 压根没有想对这种类型支持,还是Spring Boot的Bug?有大佬给
Caused by: org.yaml.snakeyaml.constructor.ConstructorException: Can't construct a java object for !QAZ2wsx; exception=Invalid tag: !QAZ2wsx
用单引号将特殊字符的值包起来,如下:
password : '!QAZ2wsx'
重新启动即可正常运行。
5.daemon-linux-zip.xml --主要用于打包的配置
备注:1,2,3这三个文件放在工程的src的bin目录下,在linux下执行的时候可能会提示找不到文件,例如start.sh:只需要vim start.sh,然后:set ff=unix,最后:wq即可
5文件放在src-main-assembly目录下即可
Book Description
Apart from knowing how to write frontend and backend code, a full-stack engineer has to tackle all the problems that are encountered in the application development life cycle, starting from a simple idea to UI design, the technical design, and all the way to implementing, testing, production, deployment, and monitoring. This book covers the full set of technologies that you need to know to become a full-stack web developer with Spring Boot for the backend and React for the frontend.
This comprehensive guide demonstrates how to build a modern full-stack application in practice. This book will teach you how to build RESTful API endpoints and work with the data access Layer of Spring, using Hibernate as the ORM. As we move ahead, you will be introduced to the other components of Spring, such as Spring Security, which will teach you how to secure the backend. Then, we will move on to the frontend, where you will be introduced to React, a modern JavaScript library for building fast and reliable user interfaces, and its app development environment and components.
You will also create a Docker container for your application. Finally, the book will lay out the best practices that underpin professional full-stack web development.
错误yaml.constructor.ConstructorError: could not determine a constructor for the tag
错误提示:
Traceback (most recent call last):
File "tools/train_net.py", line 133, in <module>
main()
File "tools/train_net.py", line 98, in main
if args.cfg_fi
错误信息:
java.lang.NoSuchMethodError: org.apache.flink.streaming.connectors.elasticsearch7.ElasticsearchSink: method <init>()V not found
产生原因:
method ()V not found这种原因就是没找到正确的无参构造方法:
引用的类里面没有无参构造方法
引用的类出现冲突,有两个或以上的方法被捕获,但是系统无法判断用哪个
我的问题:
出于某种原因,我需要继承
Caused by: org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 1
at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:254) ~[snakeyam...
pom.xml中解决Provides transitive vulnerable dependency maven:org.yaml:snakeyaml:1.33警告
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. 配置Redis连接信息:在application.properties文件中添加以下配置信息:
spring.redis.host=redis服务器IP
spring.redis.port=redis服务器端口号
spring.redis.password=redis密码
3. 创建RedisTemplate:在Java代码中创建RedisTemplate对象,并注入到需要使用Redis的类中。
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
redisTemplate.afterPropertiesSet();
return redisTemplate;
4. 使用RedisTemplate操作Redis:通过RedisTemplate对象的方法,可以进行各种Redis操作,如set、get、delete等。
以上是Spring Boot集成Redis的基本步骤,具体实现还需根据具体需求进行配置和调整。