什么是REST
REST是继SOAP以后,另一种广泛使用的Web服务。与SOAP不同,REST没有WSDL概念,也没有叫“信封”的东西,因为REST主张用一种简单粗暴的方式来表达数据,传递的数据格式可以使JSON格式也可以是XML格式,完全由用户决定。
REST全称是表达性状态转移,源于REST之父的一篇论文,论文中提出REST6个特点,分别是:客户端-服务器的,无状态的,可缓存的,统一接口,分层系统和按需编码。
Rest是一种架构风格。在REST架构风格中,对象被抽象为一种资源,资源的命名使用概念清晰的名词来定义。表达性状态时对资源数据在某个瞬间的快照,资源的某个瞬时状态被定义为一种描述,这种描述性的状态包括资源数据的内容,表达格式等信息,一种资源可以对应多种表述。REST的资源使可寻址的,通过HTTP协议定义的通用动词方法,并使用URI协议来唯一标识某个资源公布出来的借口。
REST不是一种技术,也不是一个标准或协议,它使用既有的标准:HTTP+URI+XML(数据格式),来实现其要求的架构风格。
实际上,REST是一个无状态的架构模式,因此在任何时候都可以由客户端发出请求到服务端,最终返回自己想要的数据。REST也是一种轻量级的SOA(面向服务)实现技术,因此在企业级应用于互联网应用中都得到了广泛的提高。
导入MAVEN
maven依赖如下:包括客户端
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>1.0</groupId>
<artifactId>1.0</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>3.1.4</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.1.4</version>
</dependency>
<!--Jackson-->
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>3.1.4</version>
</dependency>
</dependencies>
</project>
定义一个服务接口及其实现类
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
/**
* Created by lizhaoz on 2016/4/25.
*/
public interface ProductService {
@GET
@Path("/products")
@Produces(MediaType.APPLICATION_JSON)
List<Product> retireveAllProducts();
@GET
@Path("/product/{id}")
@Produces(MediaType.APPLICATION_JSON)
String retireveProductById(@PathParam("id")long id);
@POST
@Path("/product")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
List<Product> retireveProductsByName(@FormParam("name") String name);
@POST
@Path("/product")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
String createProduct(String product);
@PUT
@Path("/product/{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
String updateProductById(@PathParam("id") long id,Map<String,Object> fieldMap);
@DELETE
@Path("/product/{id}")
@Produces(MediaType.APPLICATION_JSON)
String deleteProductById(@PathParam("id") long id);
}
实现类如下
import javax.ws.rs.FormParam;
import java.util.List;
import java.util.Map;
/**
* Created by lizhaoz on 2016/4/26.
*/
public class ProductServiceImpl implements ProductService {
@Override
public List<Product> retireveAllProducts() {
return null;
}
@Override
public String retireveProductById(long id) {
return null;
}
@Override
public List<Product> retireveProductsByName(@FormParam("name") String name) {
return null;
}
@Override
public String createProduct(String product) {
return null;
}
@Override
public String updateProductById(long id, Map<String, Object> fieldMap) {
return null;
}
@Override
public String deleteProductById(long id) {
return null;
}
}
在ProductService接口中提供了一系列的方法,每个都是用了JAX-RS提供的注解,主要包括以下四类:
1.请求方式:一般有四种:@GET,@POST,@PUT,@DELETE;
2.请求路径注解,包括@Path,其中包括一个路劲参数,在请求路径中我们也可以使用正则表达式,如果我们使用SpringMVC,我们会使用@RequestMapping。
3.数据格式注解,包括@Consumes(输入),@Produces(输出),可使用MediaType常量。
4.相关参数注解,包括@PathParam(路径参数),@FormParam,还有@QueryParam,遵循了JAX-RS标准。
我们在Jersey中也可以使用同样的注解。
##发布REST服务
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.lifecycle.ResourceProvider;
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
import java.util.ArrayList;
import java.util.List;
/**
* Created by lizhaoz on 2016/4/25.
*/
public class Server {
public static void main(String[] args) {
//添加ResourceClass
List<Class<?>> resourceClassList=new ArrayList<Class<?>>();
resourceClassList.add(ProductServiceImpl.class);
//添加ResourceProvider
List<ResourceProvider> resourceProviderList=new ArrayList<ResourceProvider>();
resourceProviderList.add(new SingletonResourceProvider(new ProductServiceImpl()));
//添加Provider
List<Object> providerList=new ArrayList<Object>();
providerList.add(new JacksonJsonProvider());
//发布REST服务
JAXRSServerFactoryBean factory=new JAXRSServerFactoryBean();
factory.setAddress("http://localhost:8080/ws/rest");
factory.setResourceClasses(resourceClassList);
factory.setResourceProviders(resourceProviderList);
factory.setProviders(providerList);
factory.create();
System.out.println("rest ws is published");
}
}
CXF提供了一个叫org.apache.cxf.jaxrs.JAXRSServerFactoryBean的类,专门用于发布REST服务,在这个类中我们需要指定四个属性。
1.Address:REST基础地址。
2.ResourceClasses:一个或一组相关的资源类,即接口对应的实现类。
3.ResourceProviders:资源类对应的Provider,此时使用CXF提供SingletonResourceProvider进行修饰。
4.Providers:Rest服务所需的Provider,此时使用JacksonJsonProvider。用于实现JSON数据的序列化和反序列化。
CXF实现客户端
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import org.apache.cxf.jaxrs.client.WebClient;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.List;
/**
* Created by lizhaoz on 2016/4/26.
*/
public class CXFWebClient {
public static void main(String[] args) {
String baseAddress="http://localhost:8080/ws/rest";
List<Object> providerList=new ArrayList<Object>();
providerList.add(new JacksonJsonProvider());
List productList= WebClient.create(baseAddress,providerList)
.path("/products")
.accept(MediaType.APPLICATION_JSON)
.get(List.class);
for (Object product:productList) {
System.out.println(product);
}
}
}
这这里我们需要基础路劲,以及访问路径,还有接受类型JSON,以及数据类型List。