Статьи

Загрузите веб-приложение с помощью Spring 3

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-placeholder
location="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 .

Ссылка: Загрузите веб-приложение с помощью Spring 3 от нашего партнера JCG Евгения Параскива в блоге baeldung .