Przeglądaj źródła

Replaced web.xml with a web app initializer class

Craig Walls 13 lat temu
rodzic
commit
689e933f69

+ 46
- 31
gs-rest-service.md Wyświetl plik

3
 
3
 
4
 This Getting Started guide will walk you through the process of creating a simple REST endpoint using Spring.
4
 This Getting Started guide will walk you through the process of creating a simple REST endpoint using Spring.
5
 
5
 
6
-Setting up Gradle
6
+Setting Up Gradle
7
 -----------------
7
 -----------------
8
 We recommend you use Gradle for your Spring projects. If you’re a big Ant / Ivy, Buildr, Gradle, SBT, Leiningen, or Gant fan, that’s cool, but we use Gradle and we’ll be using Gradle in this guide. If you have any questions about how Gradle works, Building and Testing with Gradle (O'Reilly) should have what you’re looking for. (We’re assuming you know how to create a new Gradle project. If not, you can use this to get started.)
8
 We recommend you use Gradle for your Spring projects. If you’re a big Ant / Ivy, Buildr, Gradle, SBT, Leiningen, or Gant fan, that’s cool, but we use Gradle and we’ll be using Gradle in this guide. If you have any questions about how Gradle works, Building and Testing with Gradle (O'Reilly) should have what you’re looking for. (We’re assuming you know how to create a new Gradle project. If not, you can use this to get started.)
9
 
9
 
18
 dependencies {
18
 dependencies {
19
 	compile "org.springframework:spring-webmvc:3.2.2.RELEASE"
19
 	compile "org.springframework:spring-webmvc:3.2.2.RELEASE"
20
 	compile "org.codehaus.jackson:jackson-mapper-asl:1.9.9"
20
 	compile "org.codehaus.jackson:jackson-mapper-asl:1.9.9"
21
+	providedCompile "javax.servlet:servlet-api:2.5"
21
 }
22
 }
22
 ```
23
 ```
23
 
24
 
24
-Spring's REST support is based on Spring MVC. Therefore, we must add spring-webmvc as a dependency to our project. Also, so that our endpoints can produce JSON output, we needed to include the Jackson JSON library.
25
+Spring's REST support is based on Spring MVC. Therefore, we must add spring-webmvc as a dependency to our project. Also, so that our endpoints can produce JSON output, we needed to include the Jackson JSON library. And, since we'll be working with code that depends on the Servlet API, we'll need the Servlet API (as a providedCompile dependency for compile-time purposes only).
25
 
26
 
26
-Each of these dependencies has dependencies of their own that will transitively be resolved.
27
+Each of these dependencies have dependencies of their own that will transitively be resolved.
27
 
28
 
28
 We've also included the 'jetty' plugin so that we can easily run and test our code via Gradle.
29
 We've also included the 'jetty' plugin so that we can easily run and test our code via Gradle.
29
 
30
 
30
 
31
 
31
-Setting up DispatcherServlet
32
+Setting Up DispatcherServlet
32
 ----------------------------
33
 ----------------------------
33
-Spring REST endpoints are built as Spring MVC controllers. Therefore, we'll need to be sure that Spring's DispatcherServlet is configured in our application's /WEB-INF/web.xml:
34
-
35
-```xml
36
-<servlet>
37
-	<servlet-name>appServlet</servlet-name>
38
-	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
39
-	<init-param>
40
-		<param-name>contextClass</param-name>
41
-		<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
42
-	</init-param>
43
-	<init-param>
44
-		<param-name>contextConfigLocation</param-name>
45
-		<param-value>org.springframework.hello.config</param-value>
46
-	</init-param>
47
-	<load-on-startup>1</load-on-startup>
48
-</servlet>
49
-	
50
-<servlet-mapping>
51
-	<servlet-name>appServlet</servlet-name>
52
-	<url-pattern>/</url-pattern>
53
-</servlet-mapping>
34
+Spring REST endpoints are built as Spring MVC controllers. Therefore, we'll need to be sure that Spring's DispatcherServlet is configured. We can do that by creating a web application initializer class:
35
+
36
+```java
37
+package org.springframework.hello.config;
38
+
39
+import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
40
+
41
+public class HelloWorldWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
42
+
43
+	@Override
44
+	protected String[] getServletMappings() {
45
+		return new String[] { "/" };
46
+	}
47
+
48
+	@Override
49
+	protected Class<?>[] getRootConfigClasses() {
50
+		return null;
51
+	}
52
+
53
+	@Override
54
+	protected Class<?>[] getServletConfigClasses() {
55
+		return new Class[] { HelloWorldConfiguration.class };
56
+	}
57
+
58
+}
54
 ```
59
 ```
55
 
60
 
56
-Here we've configured DispatcherServlet to use AnnotationConfigWebApplicationContext as the context class so that our configuration can be expressed in Java, rather than XML. We've also set told DispatcherServlet (via the contextConfigLocation initialization parameter) that it can find our configuration classes in the org.springframework.hello.config package.
61
+By extending AbstractAnnotationConfigDispatcherServletInitializer, our web application initializer will get a DispatcherServlet that is configured with @Configuration-annotated classes. All we must do is tell it where those configuration classes are and what path(s) to map DispatcherServlet to. 
62
+
63
+With regard to the servlet path mappings, getServletMappings() returns a single-entry array of String specifying that DispatcherServlet should be mapped to "/".
57
 
64
 
58
-Now let's create the configuration class.
65
+The getRootConfigClasses() and getServletConfigClasses() methods specify the configuration classes. The Class array returned from getRootConfigClasses() specifies the classes for the root context provided to ContextLoaderListener. Similarly, the Class array returned from getServletConfigClasses() specifies the classes for the servlet application context provided to DispatcherServlet. 
59
 
66
 
67
+For our purposes there will only be a servlet application context, so getRootConfigClasses() returns null. getServletConfigClasses(), however, specifies HelloWorldConfiguration as the only configuration class.
60
 
68
 
61
 Creating a Configuration Class
69
 Creating a Configuration Class
62
 ------------------------------
70
 ------------------------------
63
-In our Spring configuration, we'll need to enable annotation-oriented Spring MVC. And we'll also need to tell Spring where it can find our endpoint controller class. The following configuration class takes care of both of those things:
71
+Now that we have setup DispatcherServlet to handle requests for our application, we need to configure the Spring application context used by DispatcherServlet.
64
 
72
 
73
+In our Spring configuration, we'll need to enable annotation-oriented Spring MVC. And we'll also need to tell Spring where it can find our endpoint controller class. The following configuration class takes care of both of those things:
65
 
74
 
66
 ```java
75
 ```java
67
 package org.springframework.hello.config;
76
 package org.springframework.hello.config;
80
 	
89
 	
81
 The @EnableWebMvc annotation turns on annotation-oriented Spring MVC. And we've also annotated the configuration class with @ComponentScan to have it look for components (including controllers) in the org.springframework.hello package. As it turns out, classes that are annotated with @Configuration are also discovered by component scanning, so we had to specify an exclude filter to keep it from discovering and using our configuration class a second time.
90
 The @EnableWebMvc annotation turns on annotation-oriented Spring MVC. And we've also annotated the configuration class with @ComponentScan to have it look for components (including controllers) in the org.springframework.hello package. As it turns out, classes that are annotated with @Configuration are also discovered by component scanning, so we had to specify an exclude filter to keep it from discovering and using our configuration class a second time.
82
 
91
 
83
-With configuration details completed, now it's time to start writing code for our endpoint.
84
-
85
 Creating a Representation Class
92
 Creating a Representation Class
86
 -------------------------------
93
 -------------------------------
94
+With the essential Spring MVC configuration out of the way, it's time to get to the nuts and bolts of our REST endpoint by creating a resource representation class and an endpoint controller.
95
+
87
 Before we get too carried away with building the endpoint controller, we need to give some thought to what our API will look like. 
96
 Before we get too carried away with building the endpoint controller, we need to give some thought to what our API will look like. 
88
 
97
 
89
 What we want is to handle GET requests for /hello-world, optionally with a name query parameter. In response to such a request, we'd like to send back JSON looking something like this:
98
 What we want is to handle GET requests for /hello-world, optionally with a name query parameter. In response to such a request, we'd like to send back JSON looking something like this:
157
 
166
 
158
 The magic is in the @ResponseBody annotation. @ResponseBody tells Spring MVC to not render a model into a view, but rather to write the returned object into the response body. It does this by using one of Spring's message converters.
167
 The magic is in the @ResponseBody annotation. @ResponseBody tells Spring MVC to not render a model into a view, but rather to write the returned object into the response body. It does this by using one of Spring's message converters.
159
 
168
 
160
-{TODO: briefly talk about what message converters do and list the ones that come out of the box with Spring}
169
+>__TODO__: briefly talk about what message converters do and list the ones that come out of the box with Spring}
161
 
170
 
162
 
171
 
163
 Building and Running the REST Endpoint
172
 Building and Running the REST Endpoint
164
 --------------------------------------
173
 --------------------------------------
174
+>**NOTE**: The following section probably needs to be reworked 
175
+	      (and the build file that goes with it) to use a Servlet 3 
176
+	      container (such as a modern Tomcat). At this point, 
177
+	      these steps do not work since the sample code uses a
178
+	      web app initializer instead of web.xml.
179
+
165
 All of the pieces of our REST endpoint are in place. All that's left to do is to build it and run it.
180
 All of the pieces of our REST endpoint are in place. All that's left to do is to build it and run it.
166
 
181
 
167
 To run the sample, issue the following Gradle command:
182
 To run the sample, issue the following Gradle command:

+ 1
- 0
hello-world-rest/build.gradle Wyświetl plik

7
 dependencies {
7
 dependencies {
8
 	compile "org.springframework:spring-webmvc:3.2.2.RELEASE"
8
 	compile "org.springframework:spring-webmvc:3.2.2.RELEASE"
9
 	compile "org.codehaus.jackson:jackson-mapper-asl:1.9.9"
9
 	compile "org.codehaus.jackson:jackson-mapper-asl:1.9.9"
10
+	providedCompile "javax.servlet:servlet-api:2.5"
10
 }
11
 }
11
 
12
 
12
 task wrapper(type: Wrapper) {
13
 task wrapper(type: Wrapper) {

+ 3
- 3
hello-world-rest/src/main/java/org/springframework/hello/HelloWorldResource.java Wyświetl plik

11
 @Controller
11
 @Controller
12
 @RequestMapping("/hello-world")
12
 @RequestMapping("/hello-world")
13
 public class HelloWorldResource {
13
 public class HelloWorldResource {
14
-  
15
-  private static final String template = "Hello, %s!";
16
-  private final AtomicLong counter = new AtomicLong();
14
+
15
+	private static final String template = "Hello, %s!";
16
+	private final AtomicLong counter = new AtomicLong();
17
 
17
 
18
 	@RequestMapping(method=RequestMethod.GET)
18
 	@RequestMapping(method=RequestMethod.GET)
19
 	public @ResponseBody Saying sayHello(@RequestParam(value="name", required=false, defaultValue="Stranger") String name) {
19
 	public @ResponseBody Saying sayHello(@RequestParam(value="name", required=false, defaultValue="Stranger") String name) {

+ 12
- 12
hello-world-rest/src/main/java/org/springframework/hello/Saying.java Wyświetl plik

2
 
2
 
3
 public class Saying {
3
 public class Saying {
4
 
4
 
5
-  private final long id;
6
-  private final String content;
5
+	private final long id;
6
+	private final String content;
7
 
7
 
8
-  public Saying(long id, String content) {
9
-    this.id = id;
10
-    this.content = content;
11
-  }
8
+	public Saying(long id, String content) {
9
+		this.id = id;
10
+		this.content = content;
11
+	}
12
 
12
 
13
-  public long getId() {
14
-    return id;
15
-  }
13
+	public long getId() {
14
+		return id;
15
+	}
16
 
16
 
17
-  public String getContent() {
18
-    return content;
19
-  }
17
+	public String getContent() {
18
+		return content;
19
+	}
20
 
20
 
21
 }
21
 }

+ 22
- 0
hello-world-rest/src/main/java/org/springframework/hello/config/HelloWorldWebAppInitializer.java Wyświetl plik

1
+package org.springframework.hello.config;
2
+
3
+import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
4
+
5
+public class HelloWorldWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
6
+
7
+	@Override
8
+	protected Class<?>[] getRootConfigClasses() {
9
+		return null;
10
+	}
11
+
12
+	@Override
13
+	protected Class<?>[] getServletConfigClasses() {
14
+		return new Class[] { HelloWorldConfiguration.class };
15
+	}
16
+
17
+	@Override
18
+	protected String[] getServletMappings() {
19
+		return new String[] { "/" };
20
+	}
21
+
22
+}

+ 0
- 43
hello-world-rest/src/main/webapp/WEB-INF/web.xml Wyświetl plik

1
-<?xml version="1.0" encoding="UTF-8"?>
2
-<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
3
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
-	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
5
-
6
-	<!-- Java-based annotation-driven Spring container definition -->
7
-	<context-param>
8
-		<param-name>contextClass</param-name>
9
-		<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
10
-	</context-param>
11
-
12
-	<!-- Location of Java @Configuration classes that configure the components that makeup this application -->
13
-	<context-param>
14
-		<param-name>contextConfigLocation</param-name>
15
-		<param-value>org.springframework.hello.config</param-value>
16
-	</context-param>
17
-	
18
-	<!-- Creates the Spring Container shared by all Servlets and Filters -->
19
-	<listener>
20
-		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
21
-	</listener>
22
-
23
-	<!-- Processes application requests -->
24
-	<servlet>
25
-		<servlet-name>appServlet</servlet-name>
26
-		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
27
-		<init-param>
28
-			<param-name>contextClass</param-name>
29
-			<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
30
-		</init-param>
31
-		<init-param>
32
-			<param-name>contextConfigLocation</param-name>
33
-			<param-value>org.springframework.hello.config</param-value>
34
-		</init-param>
35
-		<load-on-startup>1</load-on-startup>
36
-	</servlet>
37
-		
38
-	<servlet-mapping>
39
-		<servlet-name>appServlet</servlet-name>
40
-		<url-pattern>/</url-pattern>
41
-	</servlet-mapping>
42
-
43
-</web-app>