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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29212018/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 14:52:54  来源:igfitidea点击:

Convert existing Spring application to Spring-Boot

javaspringspring-mvcjpaspring-boot

提问by Alex

I have configured and working Spring-based REST application, but now I'd like to convert it to Spring-Boot.

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

My application uses Spring-Data-JPA on top of JPA datasource with Hibernate provider:

我的应用程序在带有 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;
    }
}

My REST endpoints implemented using SpringMVC with following configuration:

我的 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 initializer:

网页初始化程序:

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[]{"/"};
    }
}

The problem is that I don't want to use Spring-Boot auto configuration because I'd like to reuse my existing configuration classes with minimal changes, but I cannot find correct way to do this. I tried to implement Spring-boot application class annotated with @SpringBootApplication, but I'm not 100% sure that my config classes is used, because in this case I get java.lang.ClassCastException: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean$$EnhancerBySpringCGLIB$$ba21071f cannot be cast to javax.persistence.EntityManagerFactory.

问题是我不想使用 Spring-Boot 自动配置,因为我想以最少的更改重用现有的配置类,但我找不到正确的方法来做到这一点。我试图实现与注释春天启动的应用程序类@SpringBootApplication,但我相信我的配置类是使用不是100%,因为在这种情况下,我得到java.lang.ClassCastException: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean$$EnhancerBySpringCGLIB$$ba21071f cannot be cast to javax.persistence.EntityManagerFactory

Also I tried throw away @EnableAutoConfiguration annotation from application class and add TomcatEmbeddedServletContainerFactorybean to my context manually, but in this case the embedded tomcat is not configured properly.

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

It would be great if somebody can give me a hint how to solve my problem. I believe that all I need to do is somehow replace my WebInitilizer with Spring-Boot config.

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

采纳答案by Alex

After spending a day in a research, I finally found a solition of my problem. First of all I had to modify my entityManagerFactory() and transactionManager() beans:

经过一天的研究,我终于找到了解决我的问题的方法。首先,我必须修改我的 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;
    }

Also I totally removed my WebInitializerclass and removed @EnableWebMvcannotation from MvcConfig. In Spring-Boot it's not possible to have class extended from WebMvcConfigurerAdapterin classpath because if Spring-Boot find it, all automatic configuration related to SpringMVC will be skipped. Here is the final version of my MvcConfigclass:

此外,我完全删除了我的WebInitializer课程并@EnableWebMvcMvcConfig. 在 Spring-Boot 中,不能从WebMvcConfigurerAdapter类路径中扩展类,因为如果 Spring-Boot 找到它,所有与 SpringMVC 相关的自动配置将被跳过。这是我的MvcConfig课程的最终版本:

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

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

I used the version of Spring-Boot application class which shown in doc:

我使用了文档中显示的 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);
    }
}

Note, that in my case I had to exclude MultipartAutoConfigurationfrom auto configuration because I've already have this feature configured in MvcConfig. Bun it is also possible to leave it autoconfigured, but in this case I had to tune allowed file size in application.properties config file or add a MultipartConfigElement bean to my classpath.

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