shenyu2.5.0 报错 Expected a com.google.gson.JsonObject but was com.google.gson.JsonPrimitive; at path

一、环境

shenyu:2.5.0
业务服务接入方式: http
shen-admin的数据数据同步方式:websocket

二、异常描述

当shenyu-admin启动或者业务服务注册到admin时,报错

2022-10-12 00:06:10 [main] ERROR org.apache.shenyu.admin.service.manager.impl.DocManagerImpl - getDocInfo error={}
com.google.gson.JsonSyntaxException: Expected a com.google.gson.JsonObject but was com.google.gson.JsonPrimitive; at path $
	at com.google.gson.internal.bind.TypeAdapters$34$1.read(TypeAdapters.java:920)
	at com.google.gson.Gson.fromJson(Gson.java:991)
	at com.google.gson.Gson.fromJson(Gson.java:956)
	at com.google.gson.Gson.fromJson(Gson.java:905)
	at com.google.gson.Gson.fromJson(Gson.java:876)
	at org.apache.shenyu.common.utils.GsonUtils.fromJson(GsonUtils.java:135)
	at org.apache.shenyu.admin.service.manager.impl.DocManagerImpl.getDocInfo(DocManagerImpl.java:101)
	at org.apache.shenyu.admin.service.manager.impl.DocManagerImpl.addDocInfo(DocManagerImpl.java:85)
	at org.apache.shenyu.admin.service.manager.impl.ServiceDocManagerImpl.pullApiDocument(ServiceDocManagerImpl.java:72)
	at java.lang.Iterable.forEach(Iterable.java:75)
	at org.apache.shenyu.admin.service.manager.impl.ServiceDocManagerImpl.pullApiDocument(ServiceDocManagerImpl.java:53)
	at org.apache.shenyu.admin.service.manager.impl.LoadServiceDocEntryImpl.loadApiDocument(LoadServiceDocEntryImpl.java:100)
	at org.apache.shenyu.admin.listener.ApplicationStartListener.onApplicationEvent(ApplicationStartListener.java:49)
	at org.apache.shenyu.admin.listener.ApplicationStartListener.onApplicationEvent(ApplicationStartListener.java:33)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378)
	at org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:46)
	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178)
	at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54)
	at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356)
	at java.lang.Iterable.forEach(Iterable.java:75)
	at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155)
	at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123)
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:745)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:420)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1317)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
	at org.apache.shenyu.admin.ShenyuAdminBootstrap.main(ShenyuAdminBootstrap.java:36)

三、问题定位

当服务注册或者admin启动时,会向业务服务请求获取swagger的元数据


@Service
public class ServiceDocManagerImpl implements ServiceDocManager {
	
    private static final String SWAGGER_V2_PATH = "/v2/api-docs";
	
	// 向业务服务拉取swagger的元数据
    public void pullApiDocument(final UpstreamInstance instance) {
        String clusterName = instance.getClusterName();
        if (!canPull(instance)) {
            LOG.info("api document has been pulled and cannot be pulled againl,instance={}", JsonUtils.toJson(instance));
            return;
        }
        String url = getSwaggerRequestUrl(instance);
        try {
            String body = HTTP_UTILS.get(url, Collections.EMPTY_MAP);
            docManager.addDocInfo(
                clusterName,
                body,
                callback -> LOG.info("load api document successful,clusterName={}, iPandPort={}",
                    clusterName, instance.getIp() + ":" + instance.getPort())
            );
            CLUSTER_LASTSTARTUPTIME_MAP.put(clusterName, instance.getStartupTime());
        } catch (Exception e) {
            LOG.error("add api document fail. url={} error={}", url, e);
        }
    }

	// 拼接Swagger的元数据请求地址
    private String getSwaggerRequestUrl(final UpstreamInstance instance) {
        return "http://" + instance.getIp() + ":" + instance.getPort() + SWAGGER_V2_PATH;

    }

}

当业务服务的注册http的配置为

server:
  port: 8080
  servlet:
    context-path: /spvr

shenyu:
  register:
    registerType: nacos #zookeeper #etcd #nacos #consul
    serverLists: ${spring.cloud.nacos.config.server-addr} #localhost:2181 #http://localhost:2379 #localhost:8848
    props:
      username: nacos
      password: nacos
      nacosNameSpace: ${spring.cloud.nacos.discovery.namespace}
  client:
    http:
      props:
        contextPath: /demo
        isFull: true
        appName: ${spring.application.name}

因为服务默认带着context-path故请求到demo服务时,报出404异常信息,
使用gson无法解析,故报错

四、解决

  1. 去除server.servlet.context-path
包含以下java源文件: com.google.gson.DefaultDateTypeAdapter.class com.google.gson.ExclusionStrategy.class com.google.gson.FieldAttributes.class com.google.gson.FieldNamingPolicy.class com.google.gson.FieldNamingStrategy.class com.google.gson.Gson.class com.google.gson.GsonBuilder.class com.google.gson.InstanceCreator.class com.google.gson.JsonArray.class com.google.gson.JsonDeserializationContext.class com.google.gson.JsonDeserializer.class com.google.gson.JsonElement.class com.google.gson.JsonIOException.class com.google.gson.JsonNull.class com.google.gson.JsonObject.class com.google.gson.JsonParseException.class com.google.gson.JsonParser.class com.google.gson.JsonPrimitive.class com.google.gson.JsonSerializationContext.class com.google.gson.JsonSerializer.class com.google.gson.JsonStreamParser.class com.google.gson.JsonSyntaxException.class com.google.gson.LongSerializationPolicy.class com.google.gson.TreeTypeAdapter.class com.google.gson.TypeAdapter.class com.google.gson.TypeAdapterFactory.class com.google.gson.annotations.Expose.class com.google.gson.annotations.SerializedName.class com.google.gson.annotations.Since.class com.google.gson.annotations.Until.class com.google.gson.internal.ConstructorConstructor.class com.google.gson.internal.Excluder.class com.google.gson.internal.JsonReaderInternalAccess.class com.google.gson.internal.LazilyParsedNumber.class com.google.gson.internal.LinkedTreeMap.class com.google.gson.internal.ObjectConstructor.class com.google.gson.internal.Primitives.class com.google.gson.internal.Streams.class com.google.gson.internal.UnsafeAllocator.class com.google.gson.internal.bind.ArrayTypeAdapter.class com.google.gson.internal.bind.CollectionTypeAdapterFactory.class com.google.gson.internal.bind.DateTypeAdapter.class com.google.gson.internal.bind.JsonTreeReader.class com.google.gson.internal.bind.JsonTreeWriter.class com.google.gson.internal.bind.MapTypeAdapterFactory.class com.google.gson.internal.bind.ObjectTypeAdapter.class com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.class com.google.gson.internal.bind.SqlDateTypeAdapter.class com.google.gson.internal.bind.TimeTypeAdapter.class com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.class com.google.gson.internal.bind.TypeAdapters.class com.google.gson.reflect.TypeToken.class com.google.gson.stream.JsonReader.class com.google.gson.stream.JsonScope.class com.google.gson.stream.JsonToken.class com.google.gson.stream.JsonWriter.class com.google.gson.stream.MalformedJsonException.class
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值