You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
6.7 KiB
126 lines
6.7 KiB
<?xml version="1.0" encoding="UTF-8"?> |
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" |
|
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> |
|
<chapter id="rest"> |
|
<title>REST support</title> |
|
|
|
<section id="rest-introduction"> |
|
<title>Introduction</title> |
|
|
|
<para>The goal of Spring's REST support is to make the development of |
|
RESTful Web services and applications easier.</para> |
|
|
|
<para>Client-side access to RESTful resources is greatly simplified using |
|
Spring <classname>RestTemplate</classname>. |
|
<classname>RestTemplate</classname> follows in the footsteps of other |
|
template classes in Spring such as <classname>JdbcTemplate</classname> and |
|
<classname>JmsTemplate</classname>. Instead of dealing with a verbose |
|
lower level API such as Apache Commons <classname>HttpClient</classname> |
|
to create RESTful request, RestTemplate provides one liner methods that |
|
are purpose built for RESTful programming.</para> |
|
|
|
<para>On the server-side, Spring's REST support is based upon Spring's |
|
existing annotation based MVC framework. (For those interested in the |
|
rational for that decision, and for not implementing JAX-RS, read Arjen |
|
Poutsma's SpringSource TeamBlog <ulink |
|
url="http://blog.springsource.com/2009/03/08/rest-in-spring-3-mvc/">entry</ulink>.) |
|
With little effort, you can marshall data out of a RESTful request using |
|
<classname>@RequestMapping</classname> and |
|
<classname>@PathVariable</classname> annotations and return different |
|
views as determined by the request's <literal>Context-Type</literal> |
|
header.</para> |
|
|
|
<para>In this chapter we describe all the features of Spring's REST |
|
support. It is divided into two main chapters, one for the server-side and |
|
one for the client-side. For those new to Spring's <link linkend="mvc">MVC |
|
framework</link>, you may want to read through the reference documentation |
|
on <link linkend="mvc-annotation">annotation-based controller |
|
configuration</link> to understand the general programming model.</para> |
|
</section> |
|
|
|
<section id="rest-method-conversion"> |
|
<title>HTTP Method Conversion</title> |
|
|
|
<para>A key principle of REST is the use of the Uniform Interface. This |
|
means that all resources (URLs) can be manipulated using the same four |
|
HTTP methods: GET, PUT, POST, and DELETE. For each methods, the HTTP |
|
specification defines the exact semantics. For instance, a GET should |
|
always be a safe operation, meaning that is has no side effects, and a |
|
PUT or DELETE should be idempotent, meaning that you can repeat these |
|
operations over and over again, but the end result should be the same. |
|
While HTTP defines these four methods, HTML only supports two: GET and |
|
POST. Fortunately, there are two possible workarounds: you can either |
|
use JavaScript to do your PUT or DELETE, or simply do a POST with the |
|
'real' method as an additional parameter (modeled as a hidden input |
|
field in an HTML form). This latter trick is what Spring's |
|
<classname>HiddenHttpMethodFilter</classname> does. This filter is a |
|
plain Servlet Filter and therefore it can be used in combination with |
|
any web framework (not just Spring MVC). Simply add this filter to your |
|
web.xml, and a POST with a hidden _method parameter will be converted |
|
into the corresponding HTTP method request.</para> |
|
|
|
<section id="rest-form-tags"> |
|
<title>Supporting Spring form tags</title> |
|
|
|
<para>To support HTTP method conversion the Spring MVC form tag was |
|
updated to support setting the HTTP method. For example, the following |
|
snippet taken from the updated Petclinic sample</para> |
|
|
|
<programlisting language="xml"><form:form method="delete"> |
|
<p class="submit"><input type="submit" value="Delete Pet"/></p> |
|
</form:form></programlisting> |
|
|
|
<para>This will actually perform an HTTP POST, with the 'real' DELETE |
|
method hidden behind a request parameter, to be picked up by the |
|
<classname>HiddenHttpMethodFilter</classname>. The corresponding |
|
@Controller method is shown below</para> |
|
|
|
<programlisting language="java">@RequestMapping(method = RequestMethod.DELETE) |
|
public String deletePet(@PathVariable int ownerId, @PathVariable int petId) { |
|
this.clinic.deletePet(petId); |
|
return "redirect:/owners/" + ownerId; |
|
}</programlisting> |
|
</section> |
|
</section> |
|
|
|
<section id="rest-etag"> |
|
<title>ETag support</title> |
|
|
|
<para>An <ulink |
|
url="http://en.wikipedia.org/wiki/HTTP_ETag">ETag</ulink> (entity tag) |
|
is an HTTP response header returned by an HTTP/1.1 compliant web server |
|
used to determine change in content at a given URL. It can be considered |
|
to be the more sophisticated successor to the |
|
<literal>Last-Modified</literal> header. When a server returns a |
|
representation with an ETag header, the client can use this header in |
|
subsequent GETs, in an <literal>If-None-Match</literal> header. If the |
|
content has not changed, the server will return <literal>304: Not |
|
Modified</literal>.</para> |
|
|
|
<para>Support for ETags is provided by the servlet filter |
|
<classname>ShallowEtagHeaderFilter</classname>. Since it is a plain |
|
Servlet Filter, and thus can be used in combination with any web |
|
framework. The <classname>ShallowEtagHeaderFilter</classname> filter |
|
creates so-called shallow ETags (as opposed to deep ETags, more about |
|
that later). The way it works is quite simple: the filter simply caches |
|
the content of the rendered JSP (or other content), generates an MD5 |
|
hash over that, and returns that as an ETag header in the response. The |
|
next time a client sends a request for the same resource, it uses that |
|
hash as the <literal>If-None-Match</literal> value. The filter notices |
|
this, renders the view again, and compares the two hashes. If they are |
|
equal, a <literal>304</literal> is returned. It is important to note |
|
that this filter will not save processing power, as the view is still |
|
rendered. The only thing it saves is bandwidth, as the rendered response |
|
is not sent back over the wire.</para> |
|
|
|
<para>Deep ETags are a bit more complicated. In this case, the ETag is |
|
based on the underlying domain objects, RDMBS tables, etc. Using this |
|
approach, no content is generated unless the underlying data has |
|
changed. Unfortunately, implementing this approach in a generic way is |
|
much more difficult than shallow ETags. Spring may provide support for |
|
deep ETags in a later release by relying on JPA's @Version annotation, |
|
or an AspectJ aspect.</para> |
|
</section> |
|
|
|
|
|
</chapter>
|
|
|