Я пытаюсь разбить работоспособное весеннее приложение на логически разделенные модули. Давайте упростим условие и представим, что у нас есть только один модуль BusinessAppConf (только для целей взаимодействия с пользователем через WEB) и основной инициализатор контекста приложения.
Это работоспособная схема, но с использованием статических методов для регистрации классов конфигурации, связанных с бизнес-модулем.
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;
}
}
Модуль Business Config со статическими методами:
Файл класса 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);
}
}
Мне не нравится, что здесь используются статические методы. Вроде некорректные реализации. Итак, следующий вопрос: правильно ли настроены эти файлы? Если нет, как это должно быть настроено?




Используйте AbstractContextLoaderInitializer вместо WebApplicationInitializer, потому что
ContextLoaderListenercreateRootApplicationContext для создания корневого контекста приложения, который содержит бизнес-сервисы, и он будет предоставлен ContextLoaderListener, в вашем случае это BusinessAppConfigПривет, спасибо за вашу рекомендацию. Я пробовал этот подход, и у меня возникло непонимание того, как его следует использовать. У вас есть пример такой реализации? Как использовать AbstractContextLoaderInitializer Если мне нужно: 1) добавить новый сервлет для каждого отдельного модуля (в нашем случае это единственный бизнес-модуль) и 2) зарегистрировать все, что связано с настроенными классами бизнес-модуля (BusinessHibernateConf.class, BusinessMvcConfig.class) в одном конкретном месте?
Полный проект здесь github.com/BessonovEvgeniy/Octava