1. Обзор
Это первая из серии публикаций о настройке веб-приложения RESTfull с использованием Spring 3.1 с настройкой на основе Java. Эта статья будет посвящена начальной загрузке веб-приложения и обсуждению того, как перейти с XML на Java без полной миграции всей конфигурации XML.
2. Maven pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schem aLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org</groupId>
<artifactId>rest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>${cglib.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<finalName>rest</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-maven-snapshot</id>
<name>Springframework Maven Snapshot Repository</name>
<url>http://maven.springframework.org/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<spring.version>3.2.2.RELEASE</spring.version>
<cglib.version>2.2.2</cglib.version>
</properties>
</project>
2.1. Обоснование зависимости cglib
Вы можете задаться вопросом, почему cglib является зависимостью — оказывается, есть веская причина для ее включения — вся конфигурация не может функционировать без нее. Если удалить, Spring бросит:
Причина: java.lang.IllegalStateException: CGLIB требуется для обработки классов @Configuration. Либо добавьте CGLIB в путь к классам, либо удалите следующие определения bean-компонента @Configuration
Причина, по которой это происходит, объясняется тем, как Spring работает с классами @Configuration . Эти классы фактически являются компонентами, и поэтому им необходимо знать контекст и уважать область действия и другую семантику компонентов. Это достигается путем динамического создания прокси-сервера cglib с этой осведомленностью для каждого класса @Configuration , отсюда и зависимость cglib.
Кроме того, из-за этого существует несколько ограничений для аннотированных классов Configuration :
- Классы конфигурации не должны быть окончательными
- У них должен быть конструктор без аргументов
2.2. CGLIB зависимость весной 3.2
Начиная с Spring 3.2, больше не нужно добавлять cglib в качестве явной зависимости. Это связано с тем, что в Spring сейчас встроен cglib, что обеспечит полную функциональность прокси на основе классов.
Новый код cglib находится в пакете Spring: org.springframework.cglib (заменив исходный файл net.sf.cglib ). Причина изменения пакета состоит в том, чтобы избежать конфликтов с любыми версиями cglib, уже существующими в пути к классам.
Кроме того, теперь используется новый cglib 3.0, обновленный с более старой зависимости 2.2 ( для получения дополнительной информации см. Эту проблему JIRA ).
3. Веб-конфигурация на основе Java
@Configuration
@ImportResource( { "classpath*:/rest_config.xml" } )
@ComponentScan( basePackages = "org.rest", excludeFilters = { @Filter( Configuration.class ) } )
public class WebConfig{
@Bean
public PropertyPlaceholderConfigurer properties(){
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
Resource[] resources = new ClassPathResource[ ] {
new ClassPathResource( "persistence.properties" ),
new ClassPathResource( "restfull.properties" )
};
ppc.setLocations( resources );
ppc.setIgnoreUnresolvablePlaceholders( true );
return ppc;
}
}
Во-первых, аннотация @Configuration — это основной артефакт, используемый конфигурацией Spring на основе Java; он сам мета-аннотируется с помощью @Component , что делает аннотированные классы стандартными компонентами и, следовательно , также кандидатами на сканирование компонентов. Основное назначение классов @Configuration — быть источниками определений бинов для контейнера Spring IoC. Для более подробного описания смотрите официальные документы .
Затем @ImportResource используется для импорта существующей конфигурации Spring на основе XML. Это может быть конфигурация, которая все еще переносится из XML в Java, или просто устаревшая конфигурация, которую вы хотите сохранить. В любом случае, его импорт в Контейнер необходим для успешной миграции, позволяя выполнять небольшие шаги без особого риска. Эквивалентная аннотация XML, которая заменяется:
<import resource = ”classpath *: / rest_config.xml” />
Переход к @ComponentScan — это настраивает директиву сканирования компонента, эффективно заменяя XML:
<context: component-scan base-package = ”org.rest” />
Классы конфигурации фильтруются / исключаются из сканирования компонентов; это связано с тем, что они уже определены и используются Контейнером, что позволяет повторно открыть их и ввести в контекст Spring, что приведет к следующей ошибке:
Вызывается: org.springframework.context.annotation.ConflictingBeanDefinitionException: указанное в аннотации имя компонента ‘webConfig’ для класса компонента [org.rest.spring.WebConfig] конфликтует с существующим несовместимым определением компонента с тем же именем и классом [org. rest.spring.WebConfig]
И, наконец, использование аннотации @Bean для настройки поддержки свойств — PropertyPlaceholderConfigurer инициализируется в аннотированном методе @Bean , указывая, что он создаст bean-компонент Spring, управляемый контейнером. Эта новая конфигурация заменила следующий XML:
<context: property-placeholder
location = ”classpath: persistence.properties, classpath: restfull.properties”
ignore-unresolvable = ”true” />
3.1. web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>rest</display-name> <servlet> <servlet-name>rest</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context.support.AnnotationConfigWebApplicationContext </param-value> </init-param> <init-param> <param-name>contextConfigLocation</param-name> <param-value>org.rest.spring.WebConfig</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>rest</servlet-name> <url-pattern>/api/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file /> </welcome-file-list> </web-app>
Во-первых, DispatcherServlet настроен для использования AnnotationConfigWebApplicationContext вместо стандартного XmlWebApplicationContext . Более новый AnnotationConfigWebApplicationContext принимает аннотированные классы @Configuration в качестве входных данных для конфигурации контейнера и необходим для настройки контекста на основе Java.
В отличие от XmlWebApplicationContext , он не предполагает расположения классов конфигурации по умолчанию, поэтому для сервлета должен быть задан init-параметр contextConfigLocation . Это будет указывать на полное имя (имена) конфигурации Spring на основе Java.
Кроме этого, web.xml на самом деле не меняется с XML на конфигурацию на основе Java.
4. Вывод
Представленный подход обеспечивает плавную миграцию конфигурации Spring из XML в Java, смешивая старое и новое. Это важно для более старых проектов, которые могут иметь множество конфигураций на основе XML, которые нельзя перенести сразу. Таким образом, web.xml и начальная загрузка приложения являются первым шагом в миграции, после чего оставшиеся компоненты XML можно переносить небольшими порциями.
Во второй части я расскажу о конфигурации MVC и о том, как настроить RESTful API с полезной нагрузкой JSON только с конфигурацией на основе Java. А пока вы можете проверить проект github .