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

Posted

技术标签:

【中文标题】将现有的 Spring 应用程序转换为 Spring-Boot【英文标题】:Convert existing Spring application to Spring-Boot 【发布时间】:2015-05-26 13:08:20 【问题描述】:

我已经配置并运行了基于 Spring 的 REST 应用程序,但现在我想将其转换为 Spring-Boot。

我的应用程序在带有 Hibernate 提供程序的 JPA 数据源之上使用 Spring-Data-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;
    

我的 REST 端点使用 SpringMVC 实现,配置如下:

@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 应用程序类,但我不能100% 确定我的配置类是否被使用,因为在这种情况下我得到java.lang.ClassCastException: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean$$EnhancerBySpringCGLIB$$ba21071f cannot be cast to javax.persistence.EntityManagerFactory

我还尝试从应用程序类中丢弃 @EnableAutoConfiguration 注释并手动将 TomcatEmbeddedServletContainerFactory bean 添加到我的上下文中,但在这种情况下,嵌入式 tomcat 配置不正确。

如果有人能给我提示如何解决我的问题,那就太好了。我相信我需要做的就是以某种方式将我的 WebInitilizer 替换为 Spring-Boot 配置。

【问题讨论】:

我建议使用自动配置功能,因为这可以让您基本上放弃大部分配置或放入application.properties。最好的可维护代码是不写的代码。 我完全同意你的观点,自动配置是一个很好的功能,但这是我的教育项目,我认为手动配置对于了解所有这些功能的工作原理以及它们与“传统 SpringMVC" 所以你基本上不想使用 Spring Boot 或者至少正在努力尽可能少地使用它。但是,如果你真的必须放弃你的 WebInitializer 并用扩展 SpringBootServletInitializer 类来替换它。 部分你是对的。我想在我的项目中包含 Spring-Boot 的唯一一个目的是,我需要将我的应用程序打包到带有嵌入式 servlet 容器的可执行 jar 中。现在花了一些时间研究后,我正在努力用SpringBootServletInitializer替换我的WebInitializer 【参考方案1】:

经过一天的研究,我终于找到了解决问题的方法。 首先,我必须修改我的 entityManagerFactory() 和 transactionManager() bean:

    @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;
    

我还完全删除了我的WebInitializerclass 并从MvcConfig 中删除了@EnableWebMvc 注释。在 Spring-Boot 中,不可能从类路径中的 WebMvcConfigurerAdapter 扩展类,因为如果 Spring-Boot 找到它,所有与 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 中配置了此功能。 Bun 也可以让它保持自动配置,但在这种情况下,我必须在 application.properties 配置文件中调整允许的文件大小,或者将 MultipartConfigElement bean 添加到我的类路径中。

【讨论】:

以上是关于将现有的 Spring 应用程序转换为 Spring-Boot的主要内容,如果未能解决你的问题,请参考以下文章

将现有的域类与 Spring Security 插件一起使用

如何将现有的 AngularJS 2 Web 应用程序转换为 Cordova 应用程序?

将现有的 vuejs 应用程序转换为使用 nuxt s-s-r 有多难?

如何将现有的 Angular 2 Web 应用程序转换为原生脚本应用程序

如何将现有的 Angular1 Web 应用程序转换为 Cordova 应用程序?

将现有的数据库模式转换为星型模式