You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot获取WebService令牌时Qualifier类序列化报错求助

问题分析与解决方案

这个错误的核心原因很明确:你让Spring把Swagger生成的TokenRequest和TokenResponse这两个**数据传输对象(DTO)**当成了容器管理的Bean,导致这些对象被Spring附加了内部元数据(比如@Qualifier注解相关的类信息),而Gson在序列化TokenRequest时,尝试序列化这些Spring内部的类,而这些类并没有对应的Gson类型适配器,最终抛出了序列化异常。

具体问题点

在你的FE_ControlController中,你通过@Autowired注入了TokenRequest和TokenResponse:

@Autowired
private TokenRequest tokenRequest;
@Autowired
private TokenResponse tokenResponse;

Swagger生成的DTO类是用来封装单次请求/响应数据的,它们应该是每次请求都新建的临时对象,而不是被Spring作为单例Bean管理的组件。当Spring容器创建这些Bean时,会给它们添加一系列Spring内部的代理或元数据属性,这些属性在Gson序列化时会被误处理。

修复方案

去掉这两个DTO的@Autowired注入,在需要使用的时候手动创建实例即可。修改后的FE_ControlController代码如下:

package com.ids.app.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Controller;
import com.ids.app.entities.FE_Control;
import com.ids.app.service.FE_ControlService;
import io.swagger.client.ApiClient;
import io.swagger.client.ApiException;
import io.swagger.client.api.AuthorizationApi;
import io.swagger.client.model.TokenRequest;
import io.swagger.client.model.TokenResponse;

@Controller
@ComponentScan
public class FE_ControlController {
    @Autowired
    private FE_ControlService fe;
    @Autowired
    private ApiClient api;
    @Autowired
    private AuthorizationApi authorizationApi;

    private String accessToken;

    public void selWebServiceAndUsernameAndPassword(String code) {
        String webService=fe.selWebService(code);
        String username=fe.selUsername(code);
        String password=fe.selPassword(code);
        api.setBasePath(webService+"OAuth");
        authorizationApi.setApiClient(api);
        
        // 手动创建TokenRequest实例,避免Spring容器附加元数据
        TokenRequest tokenRequest = new TokenRequest();
        tokenRequest.setClientId(null);
        tokenRequest.setClientSecret(null);
        tokenRequest.setGrantType(TokenRequest.GrantTypeEnum.PASSWORD);
        tokenRequest.setUsername(username);
        tokenRequest.setPassword(password);
        
        try {
            System.out.println(tokenRequest.getUsername());
            System.out.println(tokenRequest.getPassword());
            // 直接接收接口返回的TokenResponse,不需要提前注入
            TokenResponse tokenResponse=authorizationApi.token(tokenRequest);
            accessToken=tokenResponse.getAccessToken();
            System.out.println(accessToken);
        } catch (ApiException e) {
            // 建议添加异常日志,便于后续排查问题
            e.printStackTrace();
        }
    }
}

额外建议

  1. 异常处理优化:当前代码中catch块是空的,建议添加日志打印(比如使用SLF4J),这样能及时发现接口调用失败的具体原因。
  2. DTO复用逻辑:如果需要在多个地方复用TokenRequest的初始化逻辑,可以封装一个工具类或工厂方法来创建实例,而不是依赖Spring注入。

内容的提问来源于stack exchange,提问作者Scripta14

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:34:27