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 .