Spring Boot和多模块Maven项目

时间:2014-08-01 00:50:26

标签: spring maven spring-boot

我正在努力正确地设置多模块Spring Boot Maven项目。我可以参考哪些示例项目?目前,我的项目结构如此。

数据模块: 基本上是我的数据层。包含我的POJO和我的数据库repo接口(PagingAndSortingRepository)。该模块将是项目中其他模块的依赖项。目前我在模块中放置了一个Config类,看起来像这个

public class Config {

  @Configuration
  @Profile("cloud")
  static class CloudConfiguration extends AbstractCloudConfig {
    @Bean
    public DataSource dataSource() {
      return connectionFactory().dataSource("session-questions-sql", new DataSourceConfig(new PoolConfig(4, 4), new ConnectionConfig("")));
    }

  }


  @Configuration
  @Profile("default")
  static class LocalConfiguration {
  }
}

我认为这种配置在其他两个模块之间是通用的,所以它属于数据模块。

文字模块: 这是一个非常简单的模块,它包含一个REST API控制器,当文本消息发送到某个电话号码时将调用该控制器。它将文本消息存储在DB中,并使用cdata模块中的一个repo接口来执行此操作。该模块被构建为可执行jar文件,并包含一个实现EmbeddedServletContainerCustomizer的类。

@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableJpaRepositories
public class App implements EmbeddedServletContainerCustomizer {

  public static void main(String[] args) throws Exception {
      SpringApplication.run(App.class, args);
  }

  @Override
  public void customize(ConfigurableEmbeddedServletContainer container) {
    //Enabled UTF-8 as the default character encoding for static HTML resources.
    //If you would like to disable this comment out the 3 lines below or change
    //the encoding to whatever you would like.
    MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
    mappings.add("html", "text/html;charset=utf-8");
    container.setMimeMappings(mappings );
  }
}

当我运行jar时,我得到错误,说其他控制器类不能从我的数据模块自动装配bean。我看到一些帖子说你应该将包名添加到@ComponentScan注释中。例如

@ComponentScan(" com.example.data&#34)

这样做会让嵌入式tomcat服务器启动,但我认为单独添加该软件包会导致Spring在我的文本模块中找不到我的REST控制器,因为我在访问API时会得到404。所以我也添加了我的文本包

@ComponentScan({" com.example.data"" com.example.text"})

然而,这让我回到了同样的错误,Spring无法从数据模块中找到我的bean以自动连接到我的REST控制器。

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
    at java.lang.Thread.run(Thread.java:744)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'twilioController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.data.controllers.QuestionRepo com.example.questions.text.controller.TwilioController.questionRepo; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.data.controllers.QuestionRepo] 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)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:120)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:648)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:909)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:898)
    at com.example.text.App.main(App.java:34)
    ... 6 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.data.controllers.QuestionRepo com.example.text.controller.TwilioController.questionRepo; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.data.controllers.QuestionRepo] 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)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
    ... 22 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.data.controllers.QuestionRepo] 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)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1103)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
    ... 24 more

有没有人对如何正确地做这件事有任何指示?

3 个答案:

答案 0 :(得分:4)

从应用程序类的包(注释为@EnableAutoConfiguration的包)中自动扫描存储库。如果该默认设置不适合您,您可以使用相关软件包轻松回退@EnableJpaRepositories

我可以看到com.example.datacom.example.text。我想你可能有一个项目特定的包,因为com.example可能太宽泛了。因此,解决这个问题的一种方法是将您的应用程序放在com.example(或者应用程序的根软件包中)。

同时检查the doc

答案 1 :(得分:0)

验证需要在Application类中具有父注释的bean注释,例如@Transactional-父对象:@EnableTransactionManagement。

其中有一些提供AOP和代理对象,并在错误或缺失的情况下引发bean注入生命周期失败。发生在JPA和REST多模块项目中(例如,认为是多模块组件扫描失败)。

Bean解析层次结构

@Controller <-@服务<-@Component(存储库/聚合门面)<-@存储库

答案 2 :(得分:0)

已与start.spring.io一起考虑,请参见here