"Autowire" 将 spring 模块化应用程序部署到 tomcat 后失败
"Autowire" fails after deploying spring modular application to tomcat
我需要一些帮助,因为我自己找不到解决方案而且 google 也没有帮助。
我有一个模块化 spring 应用程序,我可以使用 SpringBoot 从命令行 运行 毫无问题。
我使用 gradle war
命令创建了一个 war。我已经在带有 PostgreSQL 数据库和 JRE 8 的服务器上安装了 Tomcat 8。我已将 war 放入 webapps 文件夹,并将我的外部 conf 文件放入 conf 文件夹。
我的所有其他模块都存在于 war 文件的 libs 文件夹中。
当我 运行 和 Tomcat 时,出现以下错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personDetailsService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private eu.bato.anyoffice.serviceapi.service.PersonService eu.bato.anyoffice.frontend.config.PersonDetailsService.personService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [eu.bato.anyoffice.serviceapi.service.PersonService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
这是我的主要 conf 文件的一部分:
@Configuration
@EnableAutoConfiguration
@ComponentScan(value = {"eu.bato.anyoffice"})
@EnableWebMvc
public class Application extends WebMvcConfigurerAdapter{
@Autowired
SchedulerService scheduler;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@PostConstruct
protected void startScheduler(){
scheduler.start();
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
@Autowired
private MessageSource messageSource;
定义 PersonDetailsService bean 的安全配置:
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class);
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(personDetailsService()).passwordEncoder(new StandardPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(authenticationFilter(), LogoutFilter.class)
.csrf().disable()
.authorizeRequests()
......
.permitAll();
}
@Bean
PersonDetailsService personDetailsService() {
return new PersonDetailsService();
}
@Bean
Filter authenticationFilter() {
BasicAuthenticationFilter basicAuthFilter = new BasicAuthenticationFilter(customAuthenticationManager(), new BasicAuthenticationEntryPoint());
return basicAuthFilter;
}
@Bean
ProviderManager customAuthenticationManager() {
List<AuthenticationProvider> providers = new LinkedList<>();
providers.add(daoAuthPovider());
ProviderManager authenticationManager = new ProviderManager(providers);
authenticationManager.setEraseCredentialsAfterAuthentication(true);
return authenticationManager;
}
@Bean
DaoAuthenticationProvider daoAuthPovider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(personDetailsService());
provider.setPasswordEncoder(new StandardPasswordEncoder());
//TODO: add salt
return provider;
}
PersonDetailsService 的一部分 class:
public class PersonDetailsService implements UserDetailsService {
private static final Logger log = LoggerFactory.getLogger(PersonDetailsService.class);
private static final StandardPasswordEncoder encoder = new StandardPasswordEncoder();
@Autowired
private PersonService personService;
@Autowired
private Environment environment;
@PostConstruct
protected void initialize() {
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("Authenticating: " + username);
PersonService 接口在包 eu.bato.anyoffice.serviceapi.service
中,它的实现在 eu.bato.anyoffice.backend.service.impl
中,并且有标签 @Service
和 @Transactional
如有任何提示,我将不胜感激。我可以提供任何进一步的日志和信息。
您的配置中的问题是 PersonService
是由 Servlet Context
中声明的 @ComponentScan
加载的。
这样 PersonService
在 Application Context
中无法访问 SecurityConfig
。
Servlet Context
中的 beans 可以引用 Application Context
中的 bean,反之则不行!
因此将 @ComponentScan
放入 SecurityConfig
允许该组件可访问。
我需要一些帮助,因为我自己找不到解决方案而且 google 也没有帮助。
我有一个模块化 spring 应用程序,我可以使用 SpringBoot 从命令行 运行 毫无问题。
我使用 gradle war
命令创建了一个 war。我已经在带有 PostgreSQL 数据库和 JRE 8 的服务器上安装了 Tomcat 8。我已将 war 放入 webapps 文件夹,并将我的外部 conf 文件放入 conf 文件夹。
我的所有其他模块都存在于 war 文件的 libs 文件夹中。
当我 运行 和 Tomcat 时,出现以下错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personDetailsService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private eu.bato.anyoffice.serviceapi.service.PersonService eu.bato.anyoffice.frontend.config.PersonDetailsService.personService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [eu.bato.anyoffice.serviceapi.service.PersonService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
这是我的主要 conf 文件的一部分:
@Configuration
@EnableAutoConfiguration
@ComponentScan(value = {"eu.bato.anyoffice"})
@EnableWebMvc
public class Application extends WebMvcConfigurerAdapter{
@Autowired
SchedulerService scheduler;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@PostConstruct
protected void startScheduler(){
scheduler.start();
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
@Autowired
private MessageSource messageSource;
定义 PersonDetailsService bean 的安全配置:
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class);
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(personDetailsService()).passwordEncoder(new StandardPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(authenticationFilter(), LogoutFilter.class)
.csrf().disable()
.authorizeRequests()
......
.permitAll();
}
@Bean
PersonDetailsService personDetailsService() {
return new PersonDetailsService();
}
@Bean
Filter authenticationFilter() {
BasicAuthenticationFilter basicAuthFilter = new BasicAuthenticationFilter(customAuthenticationManager(), new BasicAuthenticationEntryPoint());
return basicAuthFilter;
}
@Bean
ProviderManager customAuthenticationManager() {
List<AuthenticationProvider> providers = new LinkedList<>();
providers.add(daoAuthPovider());
ProviderManager authenticationManager = new ProviderManager(providers);
authenticationManager.setEraseCredentialsAfterAuthentication(true);
return authenticationManager;
}
@Bean
DaoAuthenticationProvider daoAuthPovider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(personDetailsService());
provider.setPasswordEncoder(new StandardPasswordEncoder());
//TODO: add salt
return provider;
}
PersonDetailsService 的一部分 class:
public class PersonDetailsService implements UserDetailsService {
private static final Logger log = LoggerFactory.getLogger(PersonDetailsService.class);
private static final StandardPasswordEncoder encoder = new StandardPasswordEncoder();
@Autowired
private PersonService personService;
@Autowired
private Environment environment;
@PostConstruct
protected void initialize() {
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("Authenticating: " + username);
PersonService 接口在包 eu.bato.anyoffice.serviceapi.service
中,它的实现在 eu.bato.anyoffice.backend.service.impl
中,并且有标签 @Service
和 @Transactional
如有任何提示,我将不胜感激。我可以提供任何进一步的日志和信息。
您的配置中的问题是 PersonService
是由 Servlet Context
中声明的 @ComponentScan
加载的。
这样 PersonService
在 Application Context
中无法访问 SecurityConfig
。
Servlet Context
中的 beans 可以引用 Application Context
中的 bean,反之则不行!
因此将 @ComponentScan
放入 SecurityConfig
允许该组件可访问。