Spring:使基于Java的配置更加优雅

大家好,我很久没有写新文章了。 积累了很多资料,需要在不久的将来在我的博客中发布。 但是现在我想谈谈Spring MVC应用程序配置。 确切地说,我想谈谈基于Java的Spring配置。

尽管在3.0版本中引入了基于Spring Java的配置,但是许多开发人员仍然使用基于XML的方法。 我个人使用基于注释的配置,因为它们在管理,开发和维护方面更加方便。 如果您已经阅读过我的博客,那么您可能会注意到在所有代码示例中,我都完全使用基于Java的配置。

不久前,我对我的项目进行了代码审查。 我注意到配置结构有问题。 对我来说,有两个方面很糟糕:

  • 所有bean都配置在一个类中
  • 在Web应用程序上下文中初始化太复杂

您可以在我所有的Spring MVC应用程序示例中看到这两个缺点。 例如,您可以打开我关于CNVR的Spring REST服务的最新教程之一 。 看一下两个类: WebAppConfigInitializer

WebAppConfig

第一个代表本文的第一点。 绝对我需要做一些事情来逻辑上拆分bean配置。 为了解决此问题,我决定执行两个步骤:

  1. 将数据库配置移到单独的类中
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories("com.mobapp.repository")
    public class DataBaseConfig {
    
        private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
        private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
        private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
        private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
    
        private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
        private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
        private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";
    
            @Resource
            private Environment env;
    
            @Bean
            public DataSource dataSource() {
                    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    
                    dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
                    dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
                    dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
                    dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
    
                    return dataSource;
            }
    
            @Bean
            public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
                    LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
                    entityManagerFactoryBean.setDataSource(dataSource());
                    entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistence.class);
                    entityManagerFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
    
                    entityManagerFactoryBean.setJpaProperties(hibProperties());
    
                    return entityManagerFactoryBean;
            }
    
            private Properties hibProperties() {
                    Properties properties = new Properties();
                    properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
                    properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
                    return properties;        
            }
    
            @Bean
            public JpaTransactionManager transactionManager() {
                    JpaTransactionManager transactionManager = new JpaTransactionManager();
                    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
                    return transactionManager;
            }
    
    }
  2. 在主配置类中转换WebAppConfig类,并通过@Import批注将其余的配置类(在当前情况下仅为DataBaseConfig类)分配给它。
    @Configuration
    @EnableWebMvc
    @Import({DataBaseConfig.class})
    @ComponentScan("com.mobapp")
    @PropertySource("classpath:application.properties")
    public class WebAppConfig extends WebMvcConfigurerAdapter {
    
            @Resource
            private Environment env;
    
            @Override
            public void addResourceHandlers(ResourceHandlerRegistry registry) {
                    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
            }
    
            @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
                    configurer.favorPathExtension(true)
                            .useJaf(false)
                            .ignoreAcceptHeader(true)
                            .mediaType("html", MediaType.TEXT_HTML)
                            .mediaType("json", MediaType.APPLICATION_JSON)
                            .defaultContentType(MediaType.TEXT_HTML);
            }
    
            @Bean
            public ViewResolver contentNegotiatingViewResolver(
                            ContentNegotiationManager manager) {
    
                    List< ViewResolver > resolvers = new ArrayList< ViewResolver >();
    
                    InternalResourceViewResolver r1 = new InternalResourceViewResolver();
                    r1.setPrefix("/WEB-INF/pages/");
                    r1.setSuffix(".jsp");
                    r1.setViewClass(JstlView.class);
                    resolvers.add(r1);
    
                    JsonViewResolver r2 = new JsonViewResolver();
                    resolvers.add(r2);
    
                    ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
                    resolver.setViewResolvers(resolvers);
                    resolver.setContentNegotiationManager(manager);
             return resolver;
    
            }
    
            /**
            * View resolver for returning JSON in a view-based system. Always returns a
            * {@link MappingJacksonJsonView}.
            */
            public class JsonViewResolver implements ViewResolver {
                    public View resolveViewName(String viewName, Locale locale)
                                    throws Exception {
                                    MappingJacksonJsonView view = new MappingJacksonJsonView();
                                    view.setPrettyPrint(true);
                                    return view;
                    }
            }
    
    }

    这样,您可以将单个大型配置类分为几个较小的类,这些类将包含针对它们的特定配置。

初始化器

在上面提到的示例中, Initializer类的代码过于冗长,并提供了指向其的链接。 我在那里注册了Web应用程序的根配置,映射和过滤器。 如何减少代码行数? 我在AbstractAnnotationConfigDispatcherServletInitializer类上找到了答案。 查看该类,您会注意到它实现了WebApplicationInitializer接口,我在上一版本的Initializer类中已实现了该接口。 所以这是Initializer的新版本:

public class Initializer extends AbstractAnnotationConfigDispatcherServletInitializer {

        @Override
        protected Class< ? >[] getRootConfigClasses() {
                return null;
        }

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

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

        @Override
        protected Filter[] getServletFilters() {
                return new Filter[] { new HiddenHttpMethodFilter() };
        }

}

由于这两个步骤,我使Spring MVC应用程序的配置更加优雅。 现在您也可以这样做。 祝好运

参考: Spring:Fruzenshtein的Notes博客上,与我们的JCG合作伙伴 Alexey Zvolinskiy一起使基于Java的配置更加优雅

翻译自: https://www.javacodegeeks.com/2013/11/spring-make-your-java-based-configuration-more-elegant.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值