【问题标题】:Split Spring configuration by modules按模块拆分 Spring 配置
【发布时间】:2018-04-08 19:29:30
【问题描述】:

我正在尝试将可行的 spring 应用程序拆分为逻辑上分离的模块。让我们简化条件,假设我们只有一个模块 BusinessAppConf(这个仅用于用户 WEB 交互目的)和主要的 Application Context Initializer。

这是一个可行的方案,但使用静态方法注册与业务模块相关的配置类。

WebApplicationInitializer(web.xml被这个接口的实现代替了)

public class AppInitializer implements WebApplicationInitializer {

    @Override
    @Autowired
    public void onStartup(ServletContext container) throws ServletException {
        AnnotationConfigWebApplicationContext context = getContext();
        container.addListener(new ContextLoaderListener(context));

        ServletRegistration.Dynamic mainDispatcher =
                container.addServlet("dispatcher", new DispatcherServlet(context));
        ServletRegistration.Dynamic businessDispatcher =
                container.addServlet("businessDispatcher", BusinessAppConfig.createDispatcherServlet(context));
        ServletRegistration.Dynamic ppaDispatcher =
                container.addServlet("ppaDispatcher", PpaAppConfig.createDispatcherServlet(context));

        initDispatcher(mainDispatcher, 1, "/");
        initDispatcher(businessDispatcher, 2, "/business");
        initDispatcher(businessDispatcher, 3, "/ppa");
    }

    private void initDispatcher(ServletRegistration.Dynamic dispatcher, int loadOnStartUp, String mapping) {
        if (dispatcher == null) {
            System.out.println("Servlet" + dispatcher.getName() + " is already added");
        } else {
            dispatcher.setLoadOnStartup(loadOnStartUp);
            dispatcher.addMapping(mapping);
        }
    }

    public AnnotationConfigWebApplicationContext getContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(MvcConfiguration.class);
        return context;
    }

    @Bean(name = "propertyConfigurer")
    public PropertySourcesPlaceholderConfigurer getPropertyPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer placeholderConfigurer = new PropertySourcesPlaceholderConfigurer();
        placeholderConfigurer.setLocation(new ClassPathResource("common.properties"));
        placeholderConfigurer.setLocation(new ClassPathResource("amazon.S3Storage.properties"));
        placeholderConfigurer.setLocation(new ClassPathResource("local.storage.properties"));
        placeholderConfigurer.setLocation(new ClassPathResource("log4j.properties"));
        placeholderConfigurer.setIgnoreUnresolvablePlaceholders(true);
        return placeholderConfigurer;
    }
}

带有静态方法的业务配置模块:

BusinessAppConfig 类文件

@Configuration
public class BusinessAppConfig {

    public static Servlet createDispatcherServlet(AnnotationConfigWebApplicationContext context) {
        context.register(BusinessMvcConfig.class);
        return new DispatcherServlet(context);
    }
}

BusinessMvcConfig 类配置

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ComponentScan(basePackages = {"business"})
@EnableWebMvc
public class BusinessMvcConfig extends WebMvcConfigurationSupport {

    @Bean
    public ViewResolver getViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setViewClass(JstlView.class);
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    @Bean(name = "multipartResolver")
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        multipartResolver.setMaxUploadSize(500000000L);
        return multipartResolver;
    }
}

BusinessHibernateConfig.class

@Configuration
@EnableTransactionManagement
//@EnableJpaRepositories(basePackages = {"business.dao", "business.model", "ppa.dao", "ppa.model"})
@PropertySource("classpath:rdbmsDev.properties")
public class BusinessHibernateConfig {

@Autowired
private Environment env;

@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException, IOException {
    LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();

    Properties createStrategy = new Properties();
    createStrategy.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));

    emf.setJpaProperties(createStrategy);
    emf.setPackagesToScan("business");
    emf.setJpaVendorAdapter(getJpaVendorAdapter());
    BasicDataSource dataSource = getDataSource();
    emf.setDataSource(dataSource);

    return emf;
}

@Bean
public DatabasePopulator createDatabasePopulator(BasicDataSource dataSource) {
    ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
    databasePopulator.setContinueOnError(false);
    databasePopulator.addScript(new ClassPathResource("create.sql"));
    DatabasePopulatorUtils.execute(databasePopulator, dataSource);
    return databasePopulator;
}

private JpaVendorAdapter getJpaVendorAdapter() {
    HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
    jpaVendorAdapter.setShowSql(true);
    jpaVendorAdapter.setGenerateDdl(false);
    jpaVendorAdapter.setDatabasePlatform(env.getProperty("hibernate.dialect"));
    return jpaVendorAdapter;
}

@Bean
public BasicDataSource getDataSource() {
    BasicDataSource basicDataSource = new BasicDataSource();
    basicDataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
    basicDataSource.setUsername(env.getProperty("jdbc.username"));
    basicDataSource.setPassword(env.getProperty("jdbc.password"));
    basicDataSource.setUrl(env.getProperty("jdbc.url"));
    basicDataSource.setInitialSize(Ints.tryParse(env.getProperty("connection.init_size")));
    basicDataSource.setMaxIdle(Ints.tryParse(env.getProperty("connection.pool_size")));
    return basicDataSource;
}

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    return new JpaTransactionManager(entityManagerFactory);
}

}

我不喜欢这里使用静态方法。似乎不正确的实现。那么,接下来的问题是这些文件是否已正确配置?如果没有,应该如何配置?

【问题讨论】:

标签: java spring spring-mvc configuration


【解决方案1】:

使用AbstractContextLoaderInitializer 而不是WebApplicationInitializer 因为

  • 它会为你注册一个ContextLoaderListener
  • 您可以使用您的代码注册调度程序 servlet o onStartu 方法
  • 您可以覆盖createRootApplicationContext 方法来创建包含业务服务的根应用程序上下文,并且它将提供给ContextLoaderListener 在您的情况下为BusinessAppConfig

【讨论】:

  • 您好,感谢您的推荐。我已经尝试过这种方法,但我对应该如何使用它有一些误解。你有这种实现的例子吗?如何使用 AbstractContextLoaderInitializer 如果我需要:1)为每个单独的模块添加新的 Servlet(在我们的例子中它是唯一的业务模块)和 2)注册所有与业务模块配置的类(BusinessHibernateConf.class,BusinessMvcConfig.class)相关的在一个特定的地方?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 1970-01-01
  • 2020-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多