自定义OneTimeToken实现类触发IllegalStateException异常排查
解决
No primary or single unique constructor found for interface OneTimeToken异常 1. 修正Repository的泛型参数
确保你的JPA Repository是针对具体实体类PersistentOneTimeToken而非OneTimeToken接口定义的,示例:
// 错误写法 // public interface OneTimeTokenRepository extends JpaRepository<OneTimeToken, String> { ... } // 正确写法 public interface OneTimeTokenRepository extends JpaRepository<PersistentOneTimeToken, String> { Optional<PersistentOneTimeToken> findByTokenValue(String tokenValue); }
JPA需要具体的实体类来完成实例化,使用接口作为泛型参数会导致框架尝试实例化接口,触发构造器异常。
2. 确保PersistentOneTimeToken拥有合法构造器
JPA实体必须包含无参构造器,同时可以添加全参构造器方便使用:
@Entity public class PersistentOneTimeToken implements OneTimeToken { @Id private String tokenValue; private LocalDateTime expirationTime; private String username; // 其他业务字段... // JPA要求的无参构造器 public PersistentOneTimeToken() {} // 全参构造器 public PersistentOneTimeToken(String tokenValue, LocalDateTime expirationTime, String username) { this.tokenValue = tokenValue; this.expirationTime = expirationTime; this.username = username; } // 实现OneTimeToken接口的所有方法... }
如果使用Lombok,可以用@NoArgsConstructor和@AllArgsConstructor注解替代手动编写构造器。
3. 检查OneTimeTokenService的实现逻辑
确保服务从Repository获取令牌时,返回的是PersistentOneTimeToken实例,方法返回类型可使用OneTimeToken接口实现多态,示例:
@Service public class OneTimeTokenServiceImpl implements OneTimeTokenService { private final OneTimeTokenRepository tokenRepository; public OneTimeTokenServiceImpl(OneTimeTokenRepository tokenRepository) { this.tokenRepository = tokenRepository; } @Override public Optional<OneTimeToken> findByTokenValue(String tokenValue) { // 自动向上转型为OneTimeToken接口 return tokenRepository.findByTokenValue(tokenValue); } // 其他业务方法... }
4. 修正Security配置中的OTT组件
确保Security配置里的OneTimeTokenAuthenticationProvider等组件,依赖的是你实现的OneTimeTokenService或针对具体实体的Repository,示例:
@Configuration public class SecurityConfig { @Bean public OneTimeTokenAuthenticationProvider oneTimeTokenAuthenticationProvider(OneTimeTokenService tokenService) { return new OneTimeTokenAuthenticationProvider(tokenService); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/generate-token").permitAll() .anyRequest().authenticated() ) .ott(ott -> ott .oneTimeTokenService(tokenService()) .successHandler(oneTimeTokenSuccessHandler()) ); return http.build(); } // 其他Bean定义... }
5. 清理无效配置
移除PersistentOneTimeToken上的@Primary注解(实体类不需要Spring Bean的优先级标记),同时删除手动声明的OneTimeToken类型Bean——服务返回的实例已经是合法的接口实现类,无需额外声明。
内容的提问来源于stack exchange,提问作者Jeff E Mandel
相关产品推荐
相关产品推荐

