Привет всем, я не писал новые статьи в течение длительного периода времени. Было накоплено много материалов, которые должны быть размещены в моем блоге в ближайшее время. Но теперь я хочу поговорить о конфигурациях приложений Spring MVC. Если быть более точным, я хочу поговорить о конфигурациях Spring на основе Java.
Несмотря на то, что конфигурация Spring на основе Java была представлена в версии 3.0, многие разработчики все еще используют подход на основе XML. Лично я использую конфигурации на основе аннотаций, потому что они более удобны в управлении, разработке и обслуживании. Если вы читали мой блог раньше, вы могли заметить, что во всех примерах кода я использовал именно конфигурации на основе Java.
Не так давно я сделал обзор кода одного моего проекта. Я заметил, что что-то не так со структурой конфигураций. Два аспекта были плохими для меня:
- Все бины были настроены в одном классе
- Инициализация в контексте веб-приложения была слишком сложной
Вы можете увидеть эти два недостатка во всех моих примерах приложений Spring MVC. Например, вы можете открыть одно из моих последних руководств о сервисах Spring REST с CNVR . Взгляните там на два класса: WebAppConfig и Initializer .
WebAppConfig
Первый представляет первый пункт в этой статье. Определенно мне нужно сделать что-то, чтобы логически разделить конфигурацию бобов. Чтобы решить эту проблему, я решил сделать два шага:
- Переместить конфигурации БД в отдельный класс
0102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
@Configuration@EnableTransactionManagement@EnableJpaRepositories("com.mobapp.repository")publicclassDataBaseConfig {privatestaticfinalString PROPERTY_NAME_DATABASE_DRIVER ="db.driver";privatestaticfinalString PROPERTY_NAME_DATABASE_PASSWORD ="db.password";privatestaticfinalString PROPERTY_NAME_DATABASE_URL ="db.url";privatestaticfinalString PROPERTY_NAME_DATABASE_USERNAME ="db.username";privatestaticfinalString PROPERTY_NAME_HIBERNATE_DIALECT ="hibernate.dialect";privatestaticfinalString PROPERTY_NAME_HIBERNATE_SHOW_SQL ="hibernate.show_sql";privatestaticfinalString PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN ="entitymanager.packages.to.scan";@ResourceprivateEnvironment env;@BeanpublicDataSource dataSource() {DriverManagerDataSource dataSource =newDriverManagerDataSource();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));returndataSource;}@BeanpublicLocalContainerEntityManagerFactoryBean entityManagerFactory() {LocalContainerEntityManagerFactoryBean entityManagerFactoryBean =newLocalContainerEntityManagerFactoryBean();entityManagerFactoryBean.setDataSource(dataSource());entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistence.class);entityManagerFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));entityManagerFactoryBean.setJpaProperties(hibProperties());returnentityManagerFactoryBean;}privateProperties hibProperties() {Properties properties =newProperties();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));returnproperties;}@BeanpublicJpaTransactionManager transactionManager() {JpaTransactionManager transactionManager =newJpaTransactionManager();transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());returntransactionManager;}} - Преобразуйте класс WebAppConfig в основной класс конфигурации и назначьте ему оставшиеся классы конфигурации (в данном случае это был бы просто класс DataBaseConfig ) с помощью аннотации @Import .
01020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
@Configuration@EnableWebMvc@Import({DataBaseConfig.class})@ComponentScan("com.mobapp")@PropertySource("classpath:application.properties")publicclassWebAppConfigextendsWebMvcConfigurerAdapter {@ResourceprivateEnvironment env;@OverridepublicvoidaddResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");}@OverridepublicvoidconfigureContentNegotiation(ContentNegotiationConfigurer configurer) {configurer.favorPathExtension(true).useJaf(false).ignoreAcceptHeader(true).mediaType("html", MediaType.TEXT_HTML).mediaType("json", MediaType.APPLICATION_JSON).defaultContentType(MediaType.TEXT_HTML);}@BeanpublicViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {List< ViewResolver > resolvers =newArrayList< ViewResolver >();InternalResourceViewResolver r1 =newInternalResourceViewResolver();r1.setPrefix("/WEB-INF/pages/");r1.setSuffix(".jsp");r1.setViewClass(JstlView.class);resolvers.add(r1);JsonViewResolver r2 =newJsonViewResolver();resolvers.add(r2);ContentNegotiatingViewResolver resolver =newContentNegotiatingViewResolver();resolver.setViewResolvers(resolvers);resolver.setContentNegotiationManager(manager);returnresolver;}/*** View resolverforreturning JSON in a view-based system. Always returns a* {@linkMappingJacksonJsonView}.*/publicclassJsonViewResolverimplementsViewResolver {publicView resolveViewName(String viewName, Locale locale)throwsException {MappingJacksonJsonView view =newMappingJacksonJsonView();view.setPrettyPrint(true);returnview;}}}Таким образом, вы можете разделить один большой класс конфигурации на несколько меньших, которые будут содержать специальные конфигурации для них.
Initializer
Код класса Initializer слишком многословен в примере, который я упомянул выше и дал ссылку на него. Я зарегистрировал там корневую конфигурацию веб-приложения, отображение и фильтр. Как я могу уменьшить количество строк кода? Ответ я получил, посмотрев на класс AbstractAnnotationConfigDispatcherServletInitializer . Посмотрите на класс, и вы заметите, что он реализует интерфейс WebApplicationInitializer , который я реализовал в моей предыдущей версии класса Initializer. Итак, вот новая версия инициализатора :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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 более элегантными. Теперь вы тоже можете это сделать. Удачи