Spring Boot OAuth2项目启动报错:缺失JAXBException类求助
Spring Boot OAuth2启动报错:NoClassDefFoundError: javax/xml/bind/JAXBException
问题详情
我是Spring Boot新手,参照示例搭建OAuth2项目,启动时抛出如下错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.25.jar:5.3.25] ...(省略部分栈信息) Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException ...
涉及代码
SecurityConfig类
package com.demo27.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration @Order(1) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Value("${user.oauth.user.username}") private String username; @Value("${user.oauth.user.password}") private String password; @Override protected void configure(HttpSecurity http) throws Exception { http .antMatcher("/**") .authorizeRequests() .antMatchers("/oauth/authorize**", "/login**", "/error**") .permitAll() .and() .authorizeRequests() .anyRequest().authenticated() .and() .formLogin().permitAll(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser(username).password(passwordEncoder().encode(password)).roles("USER"); } @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
AuthorizationConfig类
package com.demo27.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; @Configuration @EnableAuthorizationServer public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter { @Value("${user.oauth.clientId}") private String clientID; @Value("${user.oauth.clientSecret}") private String clientSecret; @Value("${user.oauth.redirectUris}") private String redirectURLs; @Value("${user.oauth.accessTokenValidity}") private int accessTokenValidity; @Value("${user.oauth.refreshTokenValidity}") private int refreshTokenValidity; @Autowired private BCryptPasswordEncoder passwordEncoder; @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenKeyAccess("permitAll()") .checkTokenAccess("isAuthenticated()"); } public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients .inMemory() .withClient(clientID) .secret(passwordEncoder.encode(clientSecret)) .authorizedGrantTypes("password", "authorization_code", "refresh_token") .scopes("user_info") .authorities("READ_ONLY_CLIENT") .redirectUris(redirectURLs) .accessTokenValiditySeconds(accessTokenValidity) .refreshTokenValiditySeconds(refreshTokenValidity); } }
解决方案
核心原因
JAXB API是Java EE的一部分,从Java 9开始被移出了JDK默认依赖,而Spring Security OAuth2的部分组件依赖JAXB处理XML格式的令牌或配置解析,导致启动时找不到对应类。
解决步骤
在项目的依赖管理文件中添加JAXB相关依赖即可:
Maven项目(pom.xml)
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.1</version> <scope>runtime</scope> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>2.3.0.1</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency>
Gradle项目(build.gradle)
implementation 'javax.xml.bind:jaxb-api:2.3.1' runtimeOnly 'com.sun.xml.bind:jaxb-impl:2.3.1' implementation 'com.sun.xml.bind:jaxb-core:2.3.0.1' implementation 'javax.activation:activation:1.1.1'
额外建议
如果你的Spring Boot版本在2.4及以上,建议考虑迁移到Spring Security OAuth2 Authorization Server(官方推荐的替代方案),因为原Spring Security OAuth2项目已进入维护状态。不过对于当前问题,添加JAXB依赖是最直接的修复方式。
内容的提问来源于stack exchange,提问作者Sabbir Hossain Tanvir
相关产品推荐
相关产品推荐

