大家好,我很久没有写新文章了。 积累了很多资料,需要在不久的将来在我的博客中发布。 但是现在我想谈谈Spring MVC应用程序配置。 确切地说,我想谈谈基于Java的Spring配置。
尽管在3.0版本中引入了基于Spring Java的配置,但是许多开发人员仍然使用基于XML的方法。 我个人使用基于注释的配置,因为它们在管理,开发和维护方面更加方便。 如果您已经阅读过我的博客,那么您可能会注意到在所有代码示例中,我都完全使用基于Java的配置。
不久前,我对我的项目进行了代码审查。 我注意到配置结构有问题。 对我来说,有两个方面很糟糕:
- 所有bean都配置在一个类中
- 在Web应用程序上下文中初始化太复杂
您可以在我所有的Spring MVC应用程序示例中看到这两个缺点。 例如,您可以打开我关于CNVR的Spring REST服务的最新教程之一 。 看一下两个类: WebAppConfig和Initializer 。
WebAppConfig
第一个代表本文的第一点。 绝对我需要做一些事情来逻辑上拆分bean配置。 为了解决此问题,我决定执行两个步骤:
- 将数据库配置移到单独的类中
@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; } }
- 在主配置类中转换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应用程序的配置更加优雅。 现在您也可以这样做。 祝好运
翻译自: https://www.javacodegeeks.com/2013/11/spring-make-your-java-based-configuration-more-elegant.html