Привет всем, я не писал новые статьи в течение длительного периода времени. Было накоплено много материалов, которые должны быть размещены в моем блоге в ближайшее время. Но теперь я хочу поговорить о конфигурациях приложений 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"
)
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 в основной класс конфигурации и назначьте ему оставшиеся классы конфигурации (в данном случае это был бы просто класс DataBaseConfig ) с помощью аннотации @Import .
01020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
@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
Код класса 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 более элегантными. Теперь вы тоже можете это сделать. Удачи