A simplified explanation of REST
Imagine you are surfing the net and come to a web page of a nice car (a resource). The page is identified by a URL and the content is a HTML document (a representation of the car). Inside the web page, it contains other resources (e.g. tyres), which are also identified by another set URLs. When you follow one of the links and traverse to another resource, you are transferring the state to the representation of another resource.This sequence of operations is well captured by Roy’s explanation in his dissertation - "The name "Representational State Transfer" is intended to evoke an image of how a well-designed Web application behaves: a network of web pages (a virtual state-machine), where the user progresses through the application by selecting links (state transitions), resulting in the next page (representing the next state of the application) being transferred to the user and rendered for their use."
In REST, everything is identified by a URI, and the response is a representation of the resource. It can be a HTML document, an image, or an XML document. REST is just a style of how a state changes. It is not a standard.
RESTful Web Services
REST was initially described in the context of HTTP and HTML, but it is not limited to that protocol. It has been widely adopted in the web services interfaces to become RESTful Web Services.RESTful Web Services API is built on top of the simple HTTP request and response protocol and use the REST style for the representation state transfer. It basically uses the following HTTP methods to mimic the CRUD operations, and the payload is usually in XML or JSON.
The Provider
Our application is a simple CRUD system for managing a list of persons. We'll start our project with the provider service which produces XML and JSON representations of our data.1. Domain Layer
A Pojo, annotated with JAXB annotation, so that it can output in XML file. Besides, later we use this model to display in different views.package com.saurabh.common.model; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "fruit") public class Fruit { String name; int quality; public String getName() { return name; } @XmlElement public void setName(String name) { this.name = name; } public int getQuality() { return quality; } @XmlElement public void setQuality(int quality) { this.quality = quality; } public Fruit(String name, int quality) { this.name = name; this.quality = quality; } public Fruit() { } }
2. JSON and XML View
To output JSON and XML views, you don’t need to do any extra works, Spring MVC will handle the conversion automatically.
3. RSS View
To output RSS View, you need to extendAbstractRssFeedView.package com.saurabh.common.rss; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.view.feed.AbstractRssFeedView; import com.mkyong.common.model.Fruit; import com.sun.syndication.feed.rss.Channel; import com.sun.syndication.feed.rss.Content; import com.sun.syndication.feed.rss.Item; public class RssFeedView extends AbstractRssFeedView { @Override protected void buildFeedMetadata(Map<String, Object> model, Channel feed, HttpServletRequest request) { feed.setTitle("Sample Title"); feed.setDescription("Sample Description"); feed.setLink("http://google.com"); super.buildFeedMetadata(model, feed, request); } @Override protected List<Item> buildFeedItems(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { Fruit fruit = (Fruit) model.get("model"); String msg = fruit.getName() + fruit.getQuality(); List<Item> items = new ArrayList<Item>(1); Item item = new Item(); item.setAuthor("saurabh"); item.setLink("http://springfollowers.com"); Content content = new Content(); content.setValue(msg); item.setContent(content); items.add(item); return items; } }
4. JSP View
A JSP page to display the model data.File : list.jsp
<html> <body> <h1>Spring @MVC ContentNegotiatingViewResolver</h1> Fruit Name : ${model.name} <br /> Fruit Quality : ${model.quality} </body> </html>
5. Controller
Spring controller, to generate a “fruit” model and return it.package com.saurabh.common.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.mkyong.common.model.Fruit; @Controller @RequestMapping("/fruit") public class FruitController { @RequestMapping(value="{fruitName}", method = RequestMethod.GET) public String getFruit(@PathVariable String fruitName, ModelMap model) { Fruit fruit = new Fruit(fruitName, 1000); model.addAttribute("model", fruit); return "list"; } }
6. ContentNegotiatingViewResolver example
The code should be self-explanatory. However, you have to define the “order” property, where lower value get higher priority. In this case, when a URL is requested, Spring MVC will use “ContentNegotiatingViewResolver” (order=1) to return a suitable view (based on file extension declared in “mediaTypes” property), if not match, then use “InternalResourceViewResolver” (order=2) to return a default JSP page.applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <context:component-scan base-package="com.mkyong.common.controller" /> <mvc:annotation-driven /> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="order" value="1" /> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> <entry key="rss" value="application/rss+xml" /> </map> </property> <property name="defaultViews"> <list> <!-- JSON View --> <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"> </bean> <!-- RSS View --> <bean class="com.mkyong.common.rss.RssFeedView" /> <!-- JAXB XML View --> <bean class="org.springframework.web.servlet.view.xml.MarshallingView"> <constructor-arg> <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound"> <list> <value>com.mkyong.common.model.Fruit</value> </list> </property> </bean> </constructor-arg> </bean> </list> </property> <property name="ignoreAcceptHeader" value="true" /> </bean> <!-- If no extension matched, use JSP view --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="order" value="2" /> <property name="prefix"> <value>/WEB-INF/pages/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> </beans>
Together with the default HTML view resolver, as shown in the configuration above,
it can now accept requests, like /apple.html, /apple.xml,/apple.rss or /apple.json,
and returns the appropriate format, such as HTML, XML,RSS or JSON respectively.
7. Demo
Same model and display in different views, viaContentNegotiatingViewResolver.http://localhost:8080/SpringMVC/fruit/banana.xml , display as XML file.
Er. Saurabh Kumar
Very helpful blog, Please continue with latest blogs.
ReplyDeleteThanks
Manoj