基于 Spring MVC 注解的多模块项目配置

Posted

技术标签:

【中文标题】基于 Spring MVC 注解的多模块项目配置【英文标题】:Spring MVC annotation based Configuration for multimodule project 【发布时间】:2016-11-03 18:31:30 【问题描述】:

我实现了两个使用 Spring MVC、hibernate 和 Jax-RS 实现的基于 maven 的独立 Web 项目。

但是我的要求发生了变化,现在我需要将两个项目作为子项目合并到另一个项目中,即我们的父项目。所以我使用 maven 多模块配置。

项目 1:父项目

<packaging>pom</packaging>
<modules>
    <module>../child1</module>
    <module>../child2</module>
</modules>

孩子 1:

<packaging>jar</packaging>
<parent>
    <groupId>com.xyz.alpha</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <relativePath>../parent</relativePath>
</parent>

孩子 2:

<packaging>jar</packaging>

<dependency>
        <groupId>com.xyz.alpha</groupId>
        <artifactId>child1</artifactId>
        <version>2.0.2</version>
</dependency>
<parent>
    <groupId>com.xyz.alpha</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <relativePath>../parent</relativePath>
</parent>

但我需要在 Java 中配置项目,使其扫描父项目和子项目的组件并执行项目。 目前我对每个项目都有单独的配置:

AppIntializer.java

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer 

    @Override
    protected Class<?>[] getRootConfigClasses() 
        return new Class[]  AppConfig.class ;
    
 
    @Override
    protected Class<?>[] getServletConfigClasses() 
        return null;
    
 
    @Override
    protected String[] getServletMappings() 
        return new String[]  "/" ;
    

AppConfig.java

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.x.y")
public class AppConfig extends WebMvcConfigurerAdapter
     
    @Bean
    public ViewResolver viewResolver() 
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    
    
    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**");
    
    
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) 
        configurer.enable();
    
    
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
      
    

HibernateConfiguration.java

@Configuration
@EnableTransactionManagement
@ComponentScan( "com.x.y.configuration" )
@PropertySource(value =  "classpath:application.properties" )
public class HibernateConfiguration 
 
    @Autowired
    private Environment environment;
 
    @Bean
    public LocalSessionFactoryBean sessionFactory() 
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(new String[]  "com.x.y.model" );
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
     
     
    @Bean
    public DataSource dataSource() 
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
        dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
        dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
        dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
        return dataSource;
    
     
    private Properties hibernateProperties() 
        Properties properties = new Properties();
        properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
        properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
        properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
        properties.put("hibernate.hbm2ddl.auto", environment.getRequiredProperty("hibernate.hbm2ddl.auto"));
        return properties;        
    
     
    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory s) 
       HibernateTransactionManager txManager = new HibernateTransactionManager();
       txManager.setSessionFactory(s);
       return txManager;
    

【问题讨论】:

Spring有很多官方教程,后面跟着多模块源码。基于此,每个模块都有自己的配置。父级是spring-boot-starter-parent 的子级。因此,您可以通过单个操作来构建它,但您仍然必须手动运行每个操作。 GitHub ref>> 您要查找的打包类型是EAR,这将允许您通过单个操作构建和执行整个项目并解决跨模块依赖关系。 我不明白,为什么要扫描父母?父级是这里的根 POM,它不应该包含 Java 源代码。您要启动什么 JAR 以及如何启动? 【参考方案1】:

最好的配置是使用一个叫做 Maven Reactor 的项目。好在你似乎正在使用它。

首先,你的父级不应该有任何 spring 组件,它应该只由 POM(BOM - 物料清单)组成,以仅定义依赖版本,也许还有一些插件可以跨子模块共享。这些依赖项应该在 DependencyManagement 标记中,插件应该在 PluginManagement 中,但这实际上取决于您是否需要强制执行子模块中的某些行为。

如果您有父 POM 和两个子模块,并且您想扫描两个子模块中的 Spring 组件,那么我将亲自创建具有相同父 POM 和两个子模块作为依赖项的第三个子模块。在您的主类中,我将简单地使用自定义@ComponentScan 定义@SpringBootApplication,它有一个定义要扫描的包的参数。您可以使用两个模块的包前缀填充该参数,然后就可以开始了。

另一种方法是创建完全独立的项目,该项目依赖于这些子模块。但是,这要求您将这些子模块安装在本地 maven 存储库中。在第一个解决方案中,如果您总是一次构建整个项目,则不能在您的存储库中安装这些。

【讨论】:

【参考方案2】:

第二个模块如果它的spring Mvc或任何webapplication模块,那么它应该有第一个模块的依赖。在下面起草一个示例结构,希望这会有所帮助:

child1 pom:

<parent>
    <groupId>com.xyz.alpha</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>child1-app</artifactId>
<packaging>jar</packaging>
<build>
</build>
<dependencies>
</dependencies>

child2 pom:

<parent>
    <groupId>com.xyz.alpha</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>child2-Webapp</artifactId>
<packaging>war</packaging>
<build>
</build>
<dependencies>
    <dependency>
        <groupId>org.sonatype.mavenbook.multi</groupId>
        <artifactId>child1-app</artifactId>
        <version>1.0</version>
      </dependency>
</dependencies>

此外,您可以在应用程序配置中连接取决于 Hibernate 配置,例如:

@Import(HibernateConfiguration.class)
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.x.y")
public class AppConfig extends WebMvcConfigurerAdapter
    @Bean
    public ViewResolver viewResolver() 
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    

    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**");
    

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) 
        configurer.enable();
    

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    

【讨论】:

以上是关于基于 Spring MVC 注解的多模块项目配置的主要内容,如果未能解决你的问题,请参考以下文章

基于注解的Spring MVC整合Hibernate(所需jar包,spring和Hibernate整合配置,springMVC配置,重定向,批量删除)

Dubbo 3 于 Spring MVC 下使用注解配置

Dubbo 3 于 Spring MVC 下使用注解配置

Dubbo 3 于 Spring MVC 下使用注解配置

Spring6:基于注解的Spring MVC(上篇)

如何将 Spring Boot 项目集成到已经存在的多模块 Maven 项目中?