使用 Spring + 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_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 服务
<!DOCTYPE html>
<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 等技术。