Этот пост является логическим продолжением предыдущего . Единственное отличие — это контейнер, который мы собираемся использовать: вместо Jetty это будет наш старый приятель Apache Tomcat . Удивительно, но было очень легко встроить последнюю версию Apache Tomcat 7, поэтому позвольте мне показать это сейчас. Я не буду повторять последний пост в полном объеме, поскольку нет никаких изменений, за исключением файла POM и класса Starter . Помимо этих двух, мы повторно используем все, что мы сделали раньше. Для файла POM нам нужно удалить зависимости Jetty и заменить их на Apache Tomcat . Первое изменение будет в разделе свойств , мы заменим org.eclipse.jetty.version на org.apache.tomcat .
Итак, эта строка:
|
1
|
<org.eclipse.jetty.version>8.1.8.v20121106</org.eclipse.jetty.version> |
будет выглядеть так:
|
1
|
<org.apache.tomcat>7.0.34</org.apache.tomcat> |
Вторым изменением будут сами зависимости, мы заменим эти строки:
|
01
02
03
04
05
06
07
08
09
10
11
|
<dependency> <groupid>org.eclipse.jetty</groupid> <artifactid>jetty-server</artifactid> <version>${org.eclipse.jetty.version}</version></dependency> <dependency> <groupid>org.eclipse.jetty</groupid> <artifactid>jetty-webapp</artifactid> <version>${org.eclipse.jetty.version</version></dependency> |
с этими:
|
01
02
03
04
05
06
07
08
09
10
11
|
<dependency> <groupid>org.apache.tomcat.embed</groupid> <artifactid>tomcat-embed-core</artifactid> <version>${org.apache.tomcat}</version></dependency> <dependency> <groupid>org.apache.tomcat.embed</groupid> <artifactid>tomcat-embed-logging-juli</artifactid> <version>${org.apache.tomcat}</version></dependency> |
Отлично, эта часть сделана. Последняя часть посвящена изменениям в реализации нашего основного класса, где мы заменим Jetty на Apache Tomcat .
|
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
|
package com.example;import java.io.File;import java.io.IOException;import org.apache.catalina.Context;import org.apache.catalina.loader.WebappLoader;import org.apache.catalina.startup.Tomcat;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.cxf.transport.servlet.CXFServlet;import org.springframework.web.context.ContextLoaderListener;import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;import com.example.config.AppConfig;public class Starter { private final static Log log = LogFactory.getLog( Starter.class ); public static void main(final String[] args) throws Exception { final File base = createBaseDirectory(); log.info( "Using base folder: " + base.getAbsolutePath() ); final Tomcat tomcat = new Tomcat(); tomcat.setPort( 8080 ); tomcat.setBaseDir( base.getAbsolutePath() ); Context context = tomcat.addContext( "/", base.getAbsolutePath() ); Tomcat.addServlet( context, "CXFServlet", new CXFServlet() ); context.addServletMapping( "/rest/*", "CXFServlet" ); context.addApplicationListener( ContextLoaderListener.class.getName() ); context.setLoader( new WebappLoader( Thread.currentThread().getContextClassLoader() ) ); context.addParameter( "contextClass", AnnotationConfigWebApplicationContext.class.getName() ); context.addParameter( "contextConfigLocation", AppConfig.class.getName() ); tomcat.start(); tomcat.getServer().await(); } private static File createBaseDirectory() throws IOException { final File base = File.createTempFile( "tmp-", "" ); if( !base.delete() ) { throw new IOException( "Cannot (re)create base folder: " + base.getAbsolutePath() ); } if( !base.mkdir() ) { throw new IOException( "Cannot create base folder: " + base.getAbsolutePath() ); } return base; } } |
Код выглядит довольно простым, но многословным из-за того, что кажется невозможным запустить Apache Tomcat во встроенном режиме без указания какого-либо рабочего каталога. Небольшая функция createBaseDirectory () создает временную папку, которую мы передаем в Apache Tomcat в качестве baseDir . Реализация показывает, что мы запускаем экземпляр сервера Apache Tomcat на порту 8080 , настраиваем сервлет Apache CXF для обработки всех запросов по пути / rest / * , добавляем прослушиватель контекста Spring и, наконец, запускаем сервер.
После того, как мы построили проект в виде толстой или одной банки , у нас есть полноценный сервер, на котором размещено наше приложение JAR-RS :
|
1
2
|
mvn clean packagejava -jar target/spring-one-jar-0.0.1-SNAPSHOT.one-jar.jar |
И мы должны увидеть результат так:
|
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
|
Jan 28, 2013 5:54:56 PM org.apache.coyote.AbstractProtocol initINFO: Initializing ProtocolHandler ['http-bio-8080']Jan 28, 2013 5:54:56 PM org.apache.catalina.core.StandardService startInternalINFO: Starting service TomcatJan 28, 2013 5:54:56 PM org.apache.catalina.core.StandardEngine startInternalINFO: Starting Servlet Engine: Apache Tomcat/7.0.34Jan 28, 2013 5:54:56 PM org.apache.catalina.startup.DigesterFactory registerWARNING: Could not get url for /javax/servlet/jsp/resources/jsp_2_0.xsdJan 28, 2013 5:54:56 PM org.apache.catalina.startup.DigesterFactory registerWARNING: Could not get url for /javax/servlet/jsp/resources/jsp_2_1.xsdJan 28, 2013 5:54:56 PM org.apache.catalina.startup.DigesterFactory registerWARNING: Could not get url for /javax/servlet/jsp/resources/jsp_2_2.xsdJan 28, 2013 5:54:56 PM org.apache.catalina.startup.DigesterFactory registerWARNING: Could not get url for /javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtdJan 28, 2013 5:54:56 PM org.apache.catalina.startup.DigesterFactory registerWARNING: Could not get url for /javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtdJan 28, 2013 5:54:56 PM org.apache.catalina.startup.DigesterFactory registerWARNING: Could not get url for /javax/servlet/jsp/resources/web-jsptaglibrary_2_0.xsdJan 28, 2013 5:54:56 PM org.apache.catalina.startup.DigesterFactory registerWARNING: Could not get url for /javax/servlet/jsp/resources/web-jsptaglibrary_2_1.xsdJan 28, 2013 5:54:57 PM org.apache.catalina.loader.WebappLoader setClassPathINFO: Unknown loader com.simontuffs.onejar.JarClassLoader@187a84e4 class com.simontuffs.onejar.JarClassLoaderJan 28, 2013 5:54:57 PM org.apache.catalina.core.ApplicationContext logINFO: Initializing Spring root WebApplicationContextJan 28, 2013 5:54:57 PM org.springframework.web.context.ContextLoader initWebApplicationContextINFO: Root WebApplicationContext: initialization startedJan 28, 2013 5:54:58 PM org.springframework.context.support.AbstractApplicationContext prepareRefreshINFO: Refreshing Root WebApplicationContext: startup date [Mon Jan 28 17:54:58 EST 2013]; root of context hierarchyJan 28, 2013 5:54:58 PM org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFiltersINFO: JSR-330 'javax.inject.Named' annotation found and supported for component scanningJan 28, 2013 5:54:58 PM org.springframework.web.context.support.AnnotationConfigWebApplicationContext loadBeanDefinitionsINFO: Successfully resolved class for [com.example.config.AppConfig]Jan 28, 2013 5:54:58 PM org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor INFO: JSR-330 'javax.inject.Inject' annotation found and supported for autowiringJan 28, 2013 5:54:58 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletonsINFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@62770d2e: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,appConfig,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,cxf,jaxRsServer,jaxRsApiApplication,peopleRestService,peopleService,jsonProvider]; root of factory hierarchyJan 28, 2013 5:54:59 PM org.apache.cxf.endpoint.ServerImpl initDestinationINFO: Setting the server's publish address to be /apiJan 28, 2013 5:54:59 PM org.springframework.web.context.ContextLoader initWebApplicationContextINFO: Root WebApplicationContext: initialization completed in 1747 msJan 28, 2013 5:54:59 PM org.apache.coyote.AbstractProtocol startINFO: Starting ProtocolHandler ['http-bio-8080'] |
Давайте выполним несколько HTTP-запросов, чтобы убедиться, что все работает так, как мы ожидали:
|
01
02
03
04
05
06
07
08
09
10
11
|
> curl http://localhost:8080/rest/api/people?page=2[ {'email':'person+6@at.com','firstName':null,'lastName':null}, {'email':'person+7@at.com','firstName':null,'lastName':null}, {'email':'person+8@at.com','firstName':null,'lastName':null}, {'email':'person+9@at.com','firstName':null,'lastName':null}, {'email':'person+10@at.com','firstName':null,'lastName':null}]> curl http://localhost:8080/rest/api/people -X PUT -d 'email=a@b.com'{'email':'a@b.com','firstName':null,'lastName':null} |
И мы все еще на 100% свободны от XML ! Одно важное замечание : мы создаем временную папку каждый раз, но никогда не удаляем ее (вызов deleteOnShutdown для базы не работает должным образом для непустых папок). Пожалуйста, имейте это в виду (например, добавьте свой собственный способ отключения), так как я решил оставить код чистым.
Ссылка: http://aredko.blogspot.gr/2013/01/going-rest-embedding-tomcat-with-spring.html от нашего партнера по JCG Андрея Редько в блоге Андрея Редько .