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

标签 java spring spring-mvc jpa spring-boot

我已经配置并运行了基于 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();
    }
}

网络初始化程序:

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 无法转换为 javax.persistence.EntityManagerFactory

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

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

最佳答案

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

我还完全删除了我的 WebInitializer 类并从 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();
    }
}

我使用了 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);
    }
}

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

关于java - 将现有的 Spring 应用程序转换为 Spring-Boot,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29212018/

相关文章:

java - 所有spring内容初始化后如何执行代码?

java - 多模块项目的包 org.springframework.boot 不存在错误

java - 如何在 Spring MVC 中使用乐观锁

java - Spring 中的 JavaConfig 是什么?

java - Solaris - 为什么 java.lang.UNIXProcess.forkAndExec(Native Method) 挂起

java - ResultSetExtractor 类型不是通用的;它不能使用参数 <List<Employee>> 进行参数化

java - 如何实现 Java 枚举抽象类和接口(interface)?

java - 我可以通过spring-roo中的xx.java修改xx_Roo_JavaBean.aj中的setter getter吗?

jquery - 使用 Spring MVC 进行 Ajax 获取请求

java - 用java生成HTML报告