近期,因工作需要,接触到CXF与spring集成发布Rest服务,并实现客户端与服务器端的交互,上网查阅相关资料发现CXF与spring集成发布Rest服务的相关文章较多,但涉及到客户端访问服务器的相关资料确很少,几经周折,整合前人的经验,搭建好此框架之后,觉得有必要记录一下,一方面可以巩固一下流程,另一方面,希望能帮助更多有需要的人!
服务器端的搭建
第一步 Spring 框架环境搭建
1.maven 创建普通 java 工程并调整整体工程环境
2.项目目录:
第二步 配置相关文件
1.添加maven依赖(以下没有用到的可以不添加)
<dependencies>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 数据库相关 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.15</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.5</version>
</dependency>
<!-- 日志相关 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.26</version>
</dependency>
<!--CXF-->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-service-description</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-extension-providers</artifactId>
<version>${cxf.version}</version>
</dependency>
<!--Jackdon-->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.13</version>
</dependency>
<!-- aspectJ AOP 织入器 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<!-- apache lang3工具包 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
</dependencies>
2.配置web.xml文件
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<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>
第三步、REST服务接口以及实现类
1.在项目目录下新建bean包,在bean文件夹下创建Product类
package com.spring.rest.bean;
public class Product {
private long id;
private String name;
private int price;
public Product() {
}
public Product(long id, String name, int price) {
this.id = id;
this.name = name;
this.price = price;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
2.在项目目录下新建service包,在service包下新建impl包和inter包,在impl下新建ProductServiceImpl类,在inter包下新建ProductService接口(项目目录如上)
ProductServiceImpl类中内容:
package com.spring.rest.service.impl;
import com.lenovo.rest.bean.Product;
import com.lenovo.rest.service.inter.ProductService;
import java.lang.reflect.Field;
import java.util.*;
public class ProductServiceImpl implements ProductService {
private static final List<Product> productList = new ArrayList<Product>();
static {
productList.add(new Product(1, "iphone63", 5000));
productList.add(new Product(2, "ipad mini", 2500));
}
@Override
public List<Product> retrieveAllProducts() {
Collections.sort(productList, new Comparator<Product>() {
@Override
public int compare(Product p1, Product p2) {
return (p1.getId() > p2.getId()) ? -1 : 1;
}
});
return productList;
}
@Override
public Product retrieveProductById(long id) {
Product targetProduct = null;
for (Product product : productList) {
if (product.getId() == id) {
targetProduct = product;
break;
}
}
return targetProduct;
}
@Override
public List<Product> retrieveProductsByName_param(String name){
List<Product> targetList = new ArrayList<Product>();
for (Product product : productList) {
if (product.getName().equals(name)) {
targetList.add(product);
}
}
return targetList;
}
@Override
public List<Product> retrieveProductsByName_form(String name) {
List<Product> targetList = new ArrayList<Product>();
for (Product product : productList) {
if (product.getName().equals(name)) {
targetList.add(product);
}
}
return targetList;
}
@Override
public Product createProduct(Product product) {
product.setId(new Date().getTime());
productList.add(product);
return product;
}
@Override
public Product createProduct(String name,int price){
Product product = new Product();
product.setId(new Date().getTime());
product.setName(name);
product.setPrice(price);
productList.add(product);
return product;
}
@Override
public Product updateProductById(long id, Map<String, Object> fieldMap) {
Product product = retrieveProductById(id);
if (product != null) {
try {
for (Map.Entry<String, Object> fieldEntry : fieldMap.entrySet()) {
Field field = Product.class.getDeclaredField(fieldEntry
.getKey());
field.setAccessible(true);
field.set(product, fieldEntry.getValue());
}
} catch (Exception e) {
e.printStackTrace();
}
}
return product;
}
@Override
public Product updateProduct(Product product){
if(product != null){
Product targetProduct = retrieveProductById(product.getId());
if(targetProduct != null){
targetProduct.setName(product.getName());
targetProduct.setPrice(product.getPrice());
}
return targetProduct;
}
return null;
}
@Override
public Product updateProduct(long id,String name,int price){
Product product = retrieveProductById(id);
if(product != null){
product.setName(name);
product.setPrice(price);
}
return product;
}
@Override
public Product deleteProductById(long id) {
Product targetProduct = null;
Iterator<Product> it = productList.iterator();
while (it.hasNext()) {
Product product = it.next();
if (product.getId() == id) {
targetProduct = product;
it.remove();
break;
}
}
return targetProduct;
}
@Override
public Product deleteProductById_param(long id){
Product targetProduct = null;
Iterator<Product> it = productList.iterator();
while (it.hasNext()) {
Product product = it.next();
if (product.getId() == id) {
targetProduct = product;
it.remove();
break;
}
}
return targetProduct;
}
}
ProductService接口中的内容:
package com.spring.rest.service.inter;
import com.spring.rest.bean.Product;
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 javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
public interface ProductService {
@GET
@Path("/products")
@Produces(MediaType.APPLICATION_JSON)
List<Product> retrieveAllProducts();
@GET
@Path("/product/{id}")
@Produces(MediaType.APPLICATION_JSON)
Product retrieveProductById(@PathParam("id")long id);
/**
* 参数查询
* @param name
* @return
*/
@GET
@Path("/products/name")
@Produces(MediaType.APPLICATION_JSON)
List<Product> retrieveProductsByName_param(@QueryParam("name")String name);
/**
* 提交表单查询
* @param name
* @return
*/
@POST
@Path("/products/form/name")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
List<Product> retrieveProductsByName_form(@FormParam("name")String name);
@POST
@Path("/product")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
Product createProduct(Product product);
@POST
@Path("/product/create")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
Product createProduct(@FormParam("name")String name,@FormParam("price")int price);
@PUT
@Path("/product/{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
Product updateProductById(@PathParam("id")long id,Map<String,Object> fieldMap);
@PUT
@Path("/product")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
Product updateProduct(Product product);
@PUT
@Path("/product/update")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
Product updateProduct(@FormParam("id")long id,@FormParam("name")String name,@FormParam("price")int price);
@DELETE
@Path("/product/{id}")
@Produces(MediaType.APPLICATION_JSON)
Product deleteProductById(@PathParam("id")long id);
@DELETE
@Path("/product")
@Produces(MediaType.APPLICATION_JSON)
Product deleteProductById_param(@QueryParam("id")long id);
}
3.配置xml文件
在main文件下新建resources文件,如下图,点击右上角,将resources文件设置成源文件
在resources文件下新建spring.xml和spring-cxf.xml
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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="productServiceImpl" class="com.lenovo.rest.service.impl.ProductServiceImpl"></bean>
<import resource="spring-cxf.xml"/>
</beans>
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-3.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="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
</beans>
第四步,调用REST服务
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Demo</title>
<link href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
<link href="http://cdn.bootcss.com/bootstrap/3.2.0/css/colorbox.css" rel="stylesheet" type="text/css" />
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://apps.bdimg.com/libs/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/handlebars.js/4.1.0/handlebars.js"></script>
</head>
<body>
<br>
<br>
<div class="container">
<form role="form" id="form_name">
<div class="form-group">
<label for="input_name">根据名称检索</label>
<input type="text" class="form-control" id="input_name" placeholder="名称" name="name"/>
</div>
<button id="submit_name" type="button" class="btn btn-default">检索</button>
</form>
<form role="form" id="form_create">
<div class="form-group">
<label for="input_create_name">名称</label>
<input type="text" class="form-control" id="input_create_name" placeholder="名称" name="name"/>
</div>
<div class="form-group">
<label for="input_create_price">价格</label>
<input type="text" class="form-control" id="input_create_price" placeholder="价格" name="price"/>
</div>
<button id="submit_create" type="button" class="btn btn-default">添加</button>
</form>
<div class="panel panel-default">
<button id="all" type="button" class="btn btn-default">RetrieveAll</button>
<button id="byID" type="button" class="btn btn-default">RetrieveByID</button>
<button id="name" type="button" class="btn btn-default">RetrieveByName</button>
</div>
<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 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() {
//检索所有
$("#all").click(function(){
$("#product").html("");
$.ajax({
type: 'get',
url: 'http://localhost:8080/springCxfREST/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);
}
});
});
//根据ID检索
$("#byID").click(function(){
$("#product").html("");
$.ajax({
type: 'get',
url: 'http://localhost:8080/springCxfREST/ws/rest/product/1',
dataType: 'json',
success: function(data) {
var template = $("#product_table_template").html();
var render = Handlebars.compile(template);
var html = render({
data: data
});
$('#product').html(html);
}
});
});
//根据名称检索
$("#name").click(function(){
$("#product").html("");
$.ajax({
type: 'get',
url: 'http://localhost:8080/springCxfREST/ws/rest/products/name?name=ipad mini',
dataType: 'json',
success: function(data) {
var template = $("#product_table_template").html();
var render = Handlebars.compile(template);
var html = render({
data: data
});
$('#product').html(html);
}
});
});
//提交表单,根据名称检索
$("#submit_name").click(function(){
$("#product").html("");
$.ajax({
type: 'post',
url: 'http://localhost:8080/springCxfREST/ws/rest/products/form/name?'+$("#form_name").serialize(),
dataType: 'json',
success: function(data) {
var template = $("#product_table_template").html();
var render = Handlebars.compile(template);
var html = render({
data: data
});
$('#product').html(html);
}
});
});
/* 提交表单,添加数据 */
$("#submit_create").click(function(){
$("#product").html("");
$.ajax({
type: 'post',
url: 'http://localhost:8080/springCxfREST/ws/rest/product/create?'+$("#form_create").serialize(),
dataType: 'json',
success: function(data) {
var template = $("#product_table_template").html();
var render = Handlebars.compile(template);
var html = render({
data: data
});
$('#product').html(html);
}
});
});
/*使用jQuery发送基于JSONP的AJAX请求*/
$.ajax({
type: 'get',
url: 'http://localhost:8080/springCxfREST/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);
}
});
});
function goColorBox(){
$("#goOne").colorbox({ opacity:0.65,width: 500, height:500, close: "关闭", overlayClose: true});
}
</script>
</body>
</html>
第五步,发布并访问
1.配置tomcat及端口(pom.xml)
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/springCxfREST</path>
<uriEncoding>UTF-8</uriEncoding>
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
</build>
2.将打包的压缩文件设置为.war文件
在pom.xml文件中加入<packaging>war</packaging>
如下:
<groupId>com.spring.REST</groupId>
<artifactId>REST</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
3.点击右上角,Maven下的install开始打包
打包成功后开始运行
客户端搭建
重新搭建一个spring框架,环境搭建和服务器端一样
1.项目目录:
2.配置pom.xml
<!--CXF-->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-service-description</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>${cxf.version}</version>
</dependency>
<!--Jackdon-->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.13</version>
</dependency>
3.将服务器端Product类和ProductService接口复制过来
新建WebClientTest类
package com.spring.rest.client;
import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import java.util.ArrayList;
import java.util.List;
public class JAXRSClient {
public static void main(String[] args) {
JacksonJsonProvider jsonProvider = new JacksonJsonProvider();
List<Object> providerList = new ArrayList<Object>();
providerList.add(jsonProvider);
ProductService us = JAXRSClientFactory.create("http://localhost:8080/springCxfREST/ws/rest",ProductService.class,providerList);
List<Product> products = us.retrieveAllProducts();
System.out.println(products.size());
Product product = us.retrieveProductById(1);
System.out.println(product.toString());
}
}
启动服务器端,运行客户端main方法
运行结果