将现有的Spring应用程序转换为Spring-Boot

8

我已经配置好一个基于Spring的REST应用程序并且它正在运行,但是现在我想将它转换为Spring-Boot。

我的应用程序使用Spring-Data-JPA在Hibernate提供程序上的JPA数据源。

@Configuration
@EnableJpaRepositories("foo.bar.web.repository")
@EnableTransactionManagement
public class RepositoryConfig {

    // properties ommited

    @Bean
    public DataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(className);
        dataSource.setUrl(url);
        dataSource.setUsername(userName);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean
    public EntityManagerFactory entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        factory.setPackagesToScan("foo.bar.web.domain");
        factory.setDataSource(dataSource());
        factory.setJpaPropertyMap(new HashMap<String, Object>() {{
            put("hibernate.dialect", dialect);
            put("hibernate.hbm2ddl.auto", hbm2ddl);
        }});
        factory.afterPropertiesSet();
        return factory.getObject();
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory());
        return transactionManager;
    }
}

我使用以下配置实现了基于SpringMVC的REST端点:

@Configuration
@EnableWebMvc
@ComponentScan("foo.bar.web.controller")
public class MvcConfig extends WebMvcConfigurerAdapter {

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

    @Bean
    public MultipartResolver multipartResolver() {
        return new CommonsMultipartResolver();
    }
}

Web初始化器:

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{
                ApplicationConfig.class,
                RepositoryConfig.class
        };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{MvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

问题在于我不想使用Spring-Boot自动配置,因为我想尽量少更改现有的配置类并重用它们,但我找不到正确的方法来实现这一点。我尝试实现带有@SpringBootApplication注解的Spring-Boot应用程序类,但我不能百分之百确定我的配置类是否被使用,因为这种情况下会出现java.lang.ClassCastException: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean$$EnhancerBySpringCGLIB$$ba21071f无法转换为javax.persistence.EntityManagerFactory的错误。
另外,我尝试从应用程序类中删除@EnableAutoConfiguration注解,并手动将TomcatEmbeddedServletContainerFactory bean添加到我的上下文中,但在这种情况下,嵌入式Tomcat没有正确配置。
如果有人能给我提示如何解决我的问题,那就太好了。我相信我所需要做的就是以某种方式用Spring-Boot配置替换我的WebInitilizer。

1
我建议使用自动配置功能,这将允许您基本上放弃大部分配置或将其放入 application.properties 中。而最可维护的代码是未编写的代码。 - M. Deinum
我完全同意您的观点,自动配置是一个很好的功能,但这是我的教育项目,我认为手动配置更有用,可以更好地理解所有这些功能是如何工作的,以及它们与“传统SpringMVC”的关系。 - Oleksii
所以基本上你不想使用Spring Boot,或者至少在使用时尽可能少用它。但如果你真的必须使用它,只需放弃你的WebInitializer并将其替换为扩展SpringBootServletInitializer类的一个即可。 - M. Deinum
部分你是对的。我之所以想将Spring-Boot包含在我的项目中,唯一的目的就是需要将我的应用打包成可执行的JAR文件,并带有嵌入式servlet容器。现在,在做了一些研究后,我正在努力用“SpringBootServletInitializer”替换我的“WebInitializer”。 - Oleksii
1个回答

7

在进行了一天的研究后,我终于找到了解决问题的方法。 首先,我需要修改我的entityManagerFactory()和transactionManager() beans:

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        factory.setPackagesToScan("foo.bar.web.domain");
        factory.setDataSource(dataSource());
        factory.setJpaPropertyMap(new HashMap<String, Object>() {{
            put("hibernate.dialect", dialect);
            put("hibernate.hbm2ddl.auto", hbm2ddl);
        }});
        factory.afterPropertiesSet();
        return factory;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
        return transactionManager;
    }

我完全删除了WebInitializer类,并从MvcConfig中移除了@EnableWebMvc注解。在Spring Boot中,如果类路径中存在扩展自WebMvcConfigurerAdapter的类,则所有与SpringMVC相关的自动配置都将被跳过。这是最终版本的MvcConfig类:

@Configuration
@ComponentScan("foo.bar.web.controller")
public class MvcConfig {

    @Bean
    public MultipartResolver multipartResolver() {
        return new CommonsMultipartResolver();
    }
}

我使用了文档中所述的Spring-Boot应用程序类的版本:

@SpringBootApplication(exclude = MultipartAutoConfiguration.class)
public class Application extends SpringBootServletInitializer {

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

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }
}

请注意,在我的情况下,我必须从自动配置中排除MultipartAutoConfiguration,因为我已经在MvcConfig中配置了此功能。但是也可以将其保留为自动配置,但在这种情况下,我必须调整application.properties配置文件中允许的文件大小或将MultipartConfigElement bean添加到我的类路径中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接