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(); } } }
额外建议
- 异常处理优化:当前代码中
catch块是空的,建议添加日志打印(比如使用SLF4J),这样能及时发现接口调用失败的具体原因。 - DTO复用逻辑:如果需要在多个地方复用
TokenRequest的初始化逻辑,可以封装一个工具类或工厂方法来创建实例,而不是依赖Spring注入。
内容的提问来源于stack exchange,提问作者Scripta14
相关产品推荐
相关产品推荐

