1. Обзор
Это первое из серии руководств по настройке веб-приложения RESTfull с использованием Spring 3.1 с настройкой на основе Java. Статья будет посвящена начальной загрузке веб-приложения и обсуждению того, как перейти с XML на Java без полной миграции всей конфигурации XML.
2. Maven pom.xml
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
xsi:schemaLocation=" <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> <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 в Spring 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
|
01
02
03
04
05
06
07
08
09
10
11
|
@Configuration@ImportResource( { "classpath*:/rest_config.xml" } )@ComponentScan( basePackages = "org.rest" )@PropertySource({ "classpath:rest.properties", "classpath:web.properties" })public class AppConfig{ @Bean public static PropertySourcesPlaceholderConfigurer properties() { return new PropertySourcesPlaceholderConfigurer(); }} |
Во-первых, аннотация @Configuration — это основной артефакт, используемый конфигурацией Spring на основе Java; он сам мета-аннотируется с помощью @Component , что делает аннотированные классы стандартными компонентами и, следовательно , также кандидатами на сканирование компонентов. Основное назначение классов @Configuration — быть источниками определений бинов для контейнера Spring IoC. Для более подробного описания смотрите официальные документы .
Затем @ImportResource используется для импорта существующей конфигурации Spring на основе XML. Это может быть конфигурация, которая все еще переносится из XML в Java, или просто устаревшая конфигурация, которую вы хотите сохранить. В любом случае, его импорт в Контейнер необходим для успешной миграции, позволяя выполнять небольшие шаги без особого риска. Эквивалентная аннотация XML, которая заменяется:
<import resource = ”classpath *: / rest_config.xml” />
Переход к @ComponentScan — это настраивает директиву сканирования компонента, эффективно заменяя XML:
|
1
|
<context:component-scan base-package="org.rest" /> |
Начиная с Spring 3.1, @Configuration исключены из сканирования пути к классам по умолчанию — см. Эту проблему JIRA . До весны 3.1, однако, эти классы должны были быть исключены явно:
|
1
|
excludeFilters = { @ComponentScan.Filter( Configuration.class ) } |
Классы @Configuration не должны автоматически обнаруживаться, потому что они уже определены и используются Контейнером — что позволяет их повторно обнаруживать и вводить в контекст Spring, приведет к следующей ошибке:
Вызывается: org.springframework.context.annotation.ConflictingBeanDefinitionException: указанное в аннотации имя компонента «webConfig» для класса компонента [org.rest.spring.AppConfig] конфликтует с существующим несовместимым определением компонента с тем же именем и классом [org. rest.spring.AppConfig]
И, наконец, использование аннотации @Bean для настройки поддержки свойств — PropertySourcesPlaceholderConfigurer инициализируется в аннотированном методе @Bean , указывая, что он создаст bean-компонент Spring, управляемый контейнером. Эта новая конфигурация заменила следующий XML:
|
1
2
3
|
<context:property-placeholderlocation="classpath:persistence.properties, classpath:web.properties"ignore-unresolvable="true"/> |
Подробнее о том, почему необходимо было вручную зарегистрировать bean-компонент PropertySourcesPlaceholderConfigurer , см. В учебнике по свойствам со Spring .
3.1. Web.xml
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns=" xsi:schemaLocation=" id="rest" version="3.0"> <context-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context.support.AnnotationConfigWebApplicationContext </param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>org.rest.spring.root</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <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.rest</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> |
Во-первых, корневой контекст определяется и настраивается для использования AnnotationConfigWebApplicationContext вместо стандартного XmlWebApplicationContext . Более новый AnnotationConfigWebApplicationContext принимает аннотированные классы @Configuration в качестве входных данных для конфигурации контейнера и необходим для настройки контекста на основе Java.
В отличие от XmlWebApplicationContext , он не предполагает расположения классов конфигурации по умолчанию, поэтому для сервлета должен быть задан init-параметр contextConfigLocation для сервлета . Это будет указывать на пакет Java, в котором расположены классы @Configuration ; Полное имя (имена) классов также поддерживаются.
Затем DispatcherServlet настроен на использование контекста того же типа, с той лишь разницей, что он загружает классы конфигурации из другого пакета.
Кроме этого, web.xml на самом деле не меняется с XML на конфигурацию на основе Java.
4. Вывод
Представленный подход обеспечивает плавную миграцию конфигурации Spring из XML в Java, смешивая старое и новое. Это важно для более старых проектов, которые могут иметь множество конфигураций на основе XML, которые нельзя перенести сразу. Таким образом, web.xml и начальная загрузка приложения являются первым шагом в миграции, после чего оставшиеся компоненты XML можно переносить небольшими порциями.
В следующей статье о REST с Spring я расскажу о настройке MVC в проекте, настройке кодов состояния HTTP, распределении полезной нагрузки и согласовании контента. А пока вы можете проверить проект github .