使用 CXF 开发 REST 服务

REST 全称是 Representational State Transfer(表述性状态转移),它是 Roy Fielding 博士在 2000 年写的一篇关于软件架构风格的论文,此文一出,威震四方!许多知名互

联网公司开始采用这种轻量级 Web 服务,大家习惯将其称为 RESTful Web Services,或简称 REST 服务。

那么 REST 到底是什么呢?

REST 本质上是使用 URL 来访问资源的一种方式。众所周知,URL 就是我们平常使用的请求地址了,其中包括两部分:请求方式 与 请求路径,比较常见的请求方式是 GET 与

POST,但在 REST 中又提出了几种其它类型的请求方式,汇总起来有六种:GET、POST、PUT、DELETE、HEAD、OPTIONS。尤其是前四种,正好与 CRUD(增删改查)

四种操作相对应:GET(查)、POST(增)、PUT(改)、DELETE(删),这正是 REST 的奥妙所在!

实际上,REST 是一个“无状态”的架构模式,因为在任何时候都可以由客户端发出请求到服务端,最终返回自己想要的数据。也就是说,服务端将内部资源发布 REST 服务,客

户端通过 URL 来访问这些资源,这不就是 SOA 所提倡的“面向服务”的思想吗?所以,REST 也被人们看做是一种轻量级的 SOA 实现技术,因此在企业级应用与互联网应用中

都得到了广泛使用。

在 Java 的世界里,有一个名为 JAX-RS 的规范,它就是用来实现 REST 服务的,目前已经发展到了 2.0 版本,也就是 JSR-339 规范,如果您想深入研究 REST,请深入阅读

此规范。

JAX-RS 规范目前有以下几种比较流行的实现技术:

Jersey:https://jersey.java.net/

Restlet:http://restlet.com/

RESTEasy:http://resteasy.jboss.org/

CXF:http://cxf.apache.org/

本文以 CXF 为例,我努力用最精炼的文字,让您快速学会如何使用 CXF 开发 REST 服务,此外还会将 Spring 与 CXF 做一个整合,让开发更加高效!

那么还等什么呢?咱们一起出发吧!

1. 使用 CXF 发布与调用 REST 服务

第一步:添加 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>demo.ws</groupId>
    <artifactId>rest_cxf</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <cxf.version>3.0.0</cxf.version>
        <jackson.version>2.4.1</jackson.version>
    </properties>

    <dependencies>
        <!-- CXF -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <!-- Jackson -->
        <dependency>
            <groupId>com.fasterxml.jackson.jaxrs</groupId>
            <artifactId>jackson-jaxrs-json-provider</artifactId>
            <version>${jackson.version}</version>
        </dependency>
    </dependencies>

</project>
以上添加了 CXF 关于 REST 的依赖包,并使用了 Jackson 来实现 JSON 数据的转换。

第二步:定义一个 REST 服务接口

package demo.cxf.rest_cxf;

import java.util.List;
import java.util.Map;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import static javax.ws.rs.core.MediaType.*;

public interface ProductService {

    @GET
    @Path("/products")
    @Produces(APPLICATION_JSON)
    List<Product> retrieveAllProducts();

    @GET
    @Path("/product/{id}")
    @Produces(APPLICATION_JSON)
    Product retrieveProductById(@PathParam("id") long id);

    @POST
    @Path("/products")
    @Consumes(APPLICATION_FORM_URLENCODED)
    @Produces(APPLICATION_JSON)
    List<Product> retrieveProductsByName(@FormParam("name") String name);

    @POST
    @Path("/product")
    @Consumes(APPLICATION_JSON)
    @Produces(APPLICATION_JSON)
    Product createProduct(Product product);

    @PUT
    @Path("/product/{id}")
    @Consumes(APPLICATION_JSON)
    @Produces(APPLICATION_JSON)
    Product updateProductById(@PathParam("id") long id, Map<String, Object> fieldMap);

    @DELETE
    @Path("/product/{id}")
    @Produces(APPLICATION_JSON)
    Product deleteProductById(@PathParam("id") long id);
}
以上 ProductService 接口中提供了一系列的方法,在每个方法上都使用了 JAX-RS 提供的注解,主要包括以下三类:

请求方式注解,包括:@GET、@POST、@PUT、@DELETE

请求路径注解,包括:@Path,其中包括一个路径参数

数据格式注解,包括:@Consumes(输入)、@Produces(输出),可使用 MediaType 常量

相关参数注解,包括:@PathParam(路径参数)、@FormParam(表单参数),此外还有 @QueryParam(请求参数)

针对 updateProductById 方法,简单解释一下:

该方法将被 PUT:/product/{id} 请求来调用,请求路径中的 id 参数将映射到 long id 参数上,请求体中的数据将自动转换为 JSON 格式并映射到 Map<String, Object> fieldMap 参数上,返回的 Product 类型的数据将自动转换为 JSON 格式并返回到客户端。

注意:由于 Product 类与 ProductService 接口的实现类并不是本文的重点,因此省略了,本文结尾处会给出源码链接。

第三步:使用 CXF 发布 REST 服务

package demo.cxf.rest_cxf;

import java.util.ArrayList;
import java.util.List;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.lifecycle.ResourceProvider;
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class Server {

    public static void main(String[] args) {
        // 添加 ResourceClass
        List<Class<?>> resourceClassList = new ArrayList<Class<?>>();
        resourceClassList.add(HelloServiceImpl.class);
        resourceClassList.add(ProductServiceImpl.class);

        // 添加 ResourceProvider
        List<ResourceProvider> resourceProviderList = new ArrayList<ResourceProvider>();
        resourceProviderList.add(new SingletonResourceProvider(new HelloServiceImpl()));
        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 服务,只需为该类的实例对象指定四个属性即可:

Address:REST 基础地址

ResourceClasses:一个或一组相关的资源类,即接口对应的实现类(注意:REST 规范允许资源类没有接口)

ResourceProviders:资源类对应的 Provider,此时使用 CXF 提供的 org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider 进行装饰

Providers:REST 服务所需的 Provider,此时使用了 Jackson 提供的 org.codehaus.jackson.jaxrs.JacksonJsonProvider,用于实现 JSON 数据的序列化与反序列化

运行以上 Server 类,将以 standalone 方式发布 REST 服务,下面我们通过客户端来调用以发布的 REST 服务。

第四步:使用 CXF 调用 REST 服务

首先添加如下 Maven 依赖:

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-rs-client</artifactId>
    <version>${cxf.version}</version>
</dependency>
CXF 提供了三种 REST 客户端,下面将分别进行展示。

第一种:JAX-RS 1.0 时代的客户端

package demo.ws.rest_cxf;

import java.util.ArrayList;
import java.util.List;
import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class JAXRSClient {

    public static void main(String[] args) {
        String baseAddress = "http://localhost:8080/ws/rest";

        List<Object> providerList = new ArrayList<Object>();
        providerList.add(new JacksonJsonProvider());

        ProductService productService = JAXRSClientFactory.create(baseAddress, ProductService.class, providerList);
        List<Product> productList = productService.retrieveAllProducts();
        for (Product product : productList) {
            System.out.println(product);
        }
    }
}
本质是使用 CXF 提供的 org.apache.cxf.jaxrs.client.JAXRSClientFactory 工厂类来创建 ProductService 代理对象,通过代理对象调用目标对象上的方法。客户端同样也需要使

用 Provider,此时仍然使用了 Jackson 提供的 org.codehaus.jackson.jaxrs.JacksonJsonProvider。

第二种:JAX-RS 2.0 时代的客户端

package demo.ws.rest_cxf;

import java.util.List;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.MediaType;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class JAXRS20Client {

    public static void main(String[] args) {
        String baseAddress = "http://localhost:8080/ws/rest";

        JacksonJsonProvider jsonProvider = new JacksonJsonProvider();

        List productList = ClientBuilder.newClient()
            .register(jsonProvider)
            .target(baseAddress)
            .path("/products")
            .request(MediaType.APPLICATION_JSON)
            .get(List.class);
        for (Object product : productList) {
            System.out.println(product);
        }
    }
}
在 JAX-RS 2.0 中提供了一个名为 javax.ws.rs.client.ClientBuilder 的工具类,可用于创建客户端并调用 REST 服务,显然这种方式比前一种要先进,因为在代码中不再依赖 CXF API 了。
如果想返回带有泛型的 List<Product>,那么可以使用以下代码片段:
List<Product> productList = ClientBuilder.newClient()
    .register(jsonProvider)
    .target(baseAddress)
    .path("/products")
    .request(MediaType.APPLICATION_JSON)
    .get(new GenericType<List<Product>>() {});
for (Product product : productList) {
    System.out.println(product);
}
第三种:通用的 WebClient 客户端
package demo.ws.rest_cxf;

import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

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);
        }
    }
}
CXF 还提供了一种更为简洁的方式,使用 org.apache.cxf.jaxrs.client.WebClient 来调用 REST 服务,这种方式在代码层面上还是相当简洁的。

如果想返回带有泛型的 List<Product>,那么可以使用以下代码片段:

List<Product> productList = WebClient.create(baseAddress, providerList)
    .path("/products")
    .accept(MediaType.APPLICATION_JSON)
    .get(new GenericType<List<Product>>() {});
for (Product product : productList) {
    System.out.println(product);
}

2. 使用 Spring + CXF 发布 REST 服务

第一步:添加 Maven 依赖

<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>demo.ws</groupId>
    <artifactId>rest_spring_cxf</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>4.0.6.RELEASE</spring.version>
        <cxf.version>3.0.0</cxf.version>
        <jackson.version>2.4.1</jackson.version>
    </properties>

    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- CXF -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <!-- Jackson -->
        <dependency>
            <groupId>com.fasterxml.jackson.jaxrs</groupId>
            <artifactId>jackson-jaxrs-json-provider</artifactId>
            <version>${jackson.version}</version>
        </dependency>
    </dependencies>

</project>
这里仅依赖 Spring Web 模块(无需 MVC 模块),此外就是 CXF 与 Jackson 了。

第二步:配置 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <!-- Spring -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- CXF -->
    <servlet>
        <servlet-name>cxf</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>cxf</servlet-name>
        <url-pattern>/ws/*</url-pattern>
    </servlet-mapping>

</web-app>
使用 Spring 提供的 ContextLoaderListener 去加载 Spring 配置文件 spring.xml;使用 CXF 提供的 CXFServlet 去处理前缀为 /ws/ 的 REST 请求。
第三步:将接口的实现类发布 SpringBean
package demo.ws.rest_spring_cxf;

import org.springframework.stereotype.Component;

@Component
public class ProductServiceImpl implements ProductService {
    ...
}
使用 Spring 提供的 @Component 注解,将 ProductServiceImpl 发布为 Spring Bean,交给 Spring IOC 容器管理,无需再进行 Spring XML 配置。
第四步:配置 Spring
以下是 spring.xml 的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <context:component-scan base-package="demo.ws"/>

    <import resource="spring-cxf.xml"/>

</beans>
在以上配置中扫描 demo.ws 这个基础包路径,Spring 可访问该包中的所有 Spring Bean,比如,上面使用 @Component 注解发布的 ProductServiceImpl。此外,加载了另一个配置文件 spring-cxf.xml,其中包括了关于 CXF 的相关配置。
以下是 spring-cxf.xml 的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxrs="http://cxf.apache.org/jaxrs"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://cxf.apache.org/jaxrs
       http://cxf.apache.org/schemas/jaxrs.xsd">

    <jaxrs:server address="/rest">
        <jaxrs:serviceBeans>
            <ref bean="productServiceImpl"/>
        </jaxrs:serviceBeans>
        <jaxrs:providers>
            <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider"/>
        </jaxrs:providers>
    </jaxrs:server>

</beans>
使用 CXF 提供的 Spring 命名空间来配置 Service Bean(即上文提到的 Resource Class)与 Provider。注意,这里配置了一个 address 属性为“/rest”,表示 REST 请求的相对路径,与 web.xml 中配置的“/ws/*”结合起来,最终的 REST 请求根路径是“/ws/rest”,在 ProductService 接口方法上 @Path 注解所配置的路径只是一个相对路径。
第五步:调用 REST 服务
<html>
<head>
    <meta charset="UTF-8">
    <title>Demo</title>
    <link href="http://cdn.bootcss.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>

<div class="container">
    <div class="page-header">
        <h1>Product</h1>
    </div>
    <div class="panel panel-default">
        <div class="panel-heading">Product List</div>
        <div class="panel-body">
            <div id="product"></div>
        </div>
    </div>
</div>

<script src="http://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="http://cdn.bootcss.com/handlebars.js/1.3.0/handlebars.min.js"></script>

<script type="text/x-handlebars-template" id="product_table_template">
    {{#if data}}
        <table class="table table-hover" id="product_table">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Product Name</th>
                    <th>Price</th>
                </tr>
            </thead>
            <tbody>
                {{#data}}
                    <tr data-id="{{id}}" data-name="{{name}}">
                        <td>{{id}}</td>
                        <td>{{name}}</td>
                        <td>{{price}}</td>
                    </tr>
                {{/data}}
            </tbody>
        </table>
    {{else}}
        <div class="alert alert-warning">Can not find any data!</div>
    {{/if}}
</script>

<script>
    $(function() {
        $.ajax({
            type: 'get',
            url: 'http://localhost:8080/ws/rest/products',
            dataType: 'json',
            success: function(data) {
                var template = $("#product_table_template").html();
                var render = Handlebars.compile(template);
                var html = render({
                    data: data
                });
                $('#product').html(html);
            }
        });
    });
</script>

</body>
</html>
使用一个简单的 HTML 页面来调用 REST 服务,也就是说,前端发送 AJAX 请求来调用后端发布的 REST 服务。这里使用了 jQuery、Bootstrap、Handlebars.js 等技术。

3. 关于 AJAX 的跨域问题

如果服务端部署在 foo.com 域名下,而客户端部署在 bar.com 域名下,此时从 bar.com 发出一个 AJAX 的 REST 请求到 foo.com,就会出现报错:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
要想解决以上这个 AJAX 跨域问题,有以下两种解决方案:
方案一:使用 JSONP 解决 AJAX 跨域问题
JSONP 的全称是 JSON with Padding,实际上是在需要返回的 JSON 数据外,用一个 JS 函数进行封装。
可以这样来理解,服务器返回一个 JS 函数,参数是一个 JSON 数据,例如:callback({您的 JSON 数据}),虽然 AJAX 不能跨域访问,但 JS 脚本是可以跨域执行的,因此客户端将执行这个 callback 函数,并获取其中的 JSON 数据。
如果需要返回的 JSON 数据是:
{"id":2,"name":"ipad mini","price":2500},{"id":1,"name":"iphone 5s","price":5000}
那么对应的 JSONP 格式是:
callback([{"id":2,"name":"ipad mini","price":2500},{"id":1,"name":"iphone 5s","price":5000}]);
CXF 已经提供了对 JSONP 的支持,只需要通过简单的配置即可实现。
首先,添加 Maven 依赖:
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-rs-extension-providers</artifactId>
    <version>${cxf.version}</version>
</dependency>
然后,添加 CXF 配置:
<jaxrs:server address="/rest">
    <jaxrs:serviceBeans>
        <ref bean="productServiceImpl"/>
    </jaxrs:serviceBeans>
    <jaxrs:providers>
        <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider"/>
        <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpPreStreamInterceptor"/>
    </jaxrs:providers>
    <jaxrs:inInterceptors>
        <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpInInterceptor"/>
    </jaxrs:inInterceptors>
    <jaxrs:outInterceptors>
        <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpPostStreamInterceptor"/>
    </jaxrs:outInterceptors>
</jaxrs:server>
注意:JsonpPreStreamInterceptor 一定要放在 <jaxrs:providers> 中,而不是 <jaxrs:inInterceptors> 中,这也许是 CXF 的一个 Bug,可以点击以下链接查看具体原因:

http://cxf.547215.n5.nabble.com/JSONP-is-not-works-td5739858.html

最后,使用 jQuery 发送基于 JSONP 的 AJAX 请求:

$.ajax({
    type: 'get',
    url: 'http://localhost:8080/ws/rest/products',
    dataType: 'jsonp',
    jsonp: '_jsonp',
    jsonpCallback: 'callback',
    success: function(data) {
        var template = $("#product_table_template").html();
        var render = Handlebars.compile(template);
        var html = render({
            data: data
        });
        $('#product').html(html);
    }
});
以上代码中有三个选项需要加以说明:
dataType:必须为“jsonp”,表示返回的数据类型为 JSONP 格式
jsonp:表示 URL 中 JSONP 回调函数的参数名,CXF 默认接收的参数名是“_jsonp”,也可以在 JsonpInInterceptor 中配置
jsonpCallback:表示回调函数的名称,若未指定,则由 jQuery 自动生成
方案二:使用 CORS 解决 AJAX 跨域问题
CORS 的全称是 Cross-Origin Resource Sharing(跨域资源共享),它是 W3C 提出的一个 AJAX 跨域访问规范,可以从以下地址了解此规范:
http://www.w3.org/TR/cors/
相比 JSONP 而言,CORS 更为强大,因为它弥补了 JSONP 只能处理 GET 请求的局限性,但是只有较为先进的浏览器才能全面支持 CORS。
CXF 同样也提供了对 CORS 的支持,通过简单的配置就能实现。
首先,添加 Maven 依赖:
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-rs-security-cors</artifactId>
    <version>${cxf.version}</version>
</dependency>
然后,添加 CXF 配置:
<jaxrs:server address="/rest">
    <jaxrs:serviceBeans>
        <ref bean="productServiceImpl"/>
    </jaxrs:serviceBeans>
    <jaxrs:providers>
        <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider"/>
        <bean class="org.apache.cxf.rs.security.cors.CrossOriginResourceSharingFilter">
            <property name="allowOrigins" value="http://localhost"/>
        </bean>
    </jaxrs:providers>
</jaxrs:server>
在 CrossOriginResourceSharingFilter 中配置 allowOrigins 属性,将其设置为客户端的域名,示例中为“http://localhost”,需根据实际情况进行设置。
最后,使用 jQuery 发送 AJAX 请求:
就像在相同域名下访问一样,无需做任何配置。
注意:在 IE8 中使用 jQuery 发送 AJAX 请求时,需要配置 $.support.cors = true,才能开启 CORS 特性。

4. 总结

本文让您学会了如何使用 CXF 发布 REST 服务,可以独立使用 CXF,也可以与 Spring 集成。此外,CXF 也提供了一些解决方案,用于实现跨域 AJAX 请求,比如:JSONP 或 CORS。CXF 3.0 以全面支持 JAX-RS 2.0 规范,有很多实用的功能需要您进一步学习,可以点击以下地址:
http://cxf.apache.org/docs/jax-rs.html

源码地址:http://git.oschina.net/huangyong/cxf_demo

原文地址:https://my.oschina.net/huangyong/blog/294324

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值