使用cxf开发REST服务

什么是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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值