CXF系列之JAX-RS:CXF与spring集成发布REST服务
来源:互联网 发布:js控制滚动条位置 编辑:程序博客网 时间:2024/06/05 15:35
第一步、添加maven依赖
<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>这里仅依赖 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>/WEB-INF/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 请求。
第三步、REST服务接口以及实现类
REST服务接口
package com.test.rest.service.inter;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;import com.test.rest.bean.Product;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);}
接口所对应的实现类:
package com.test.rest.service.impl;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.Date;import java.util.Iterator;import java.util.List;import java.util.Map;import com.test.rest.bean.Product;import com.test.rest.service.inter.ProductService;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));}@Overridepublic List<Product> retrieveAllProducts() {Collections.sort(productList, new Comparator<Product>() {@Overridepublic int compare(Product p1, Product p2) {return (p1.getId() > p2.getId()) ? -1 : 1;}});return productList;}@Overridepublic Product retrieveProductById(long id) {Product targetProduct = null;for (Product product : productList) {if (product.getId() == id) {targetProduct = product;break;}}return targetProduct;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic Product createProduct(Product product) {product.setId(new Date().getTime());productList.add(product);return product;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic Product updateProduct(long id,String name,int price){Product product = retrieveProductById(id);if(product != null){product.setName(name);product.setPrice(price);}return product;}@Overridepublic 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;}@Overridepublic 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;}}
第四步、配置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-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.test.rest.service.impl.ProductServiceImpl"></bean> <import resource="spring-cxf.xml"/></beans>将REST服务接口的实现类配置成SpringBean。
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>使用 CXF 提供的 Spring 命名空间来配置 Service Bean(即上文提到的 Resource Class)与 Provider。注意,这里配置了一个 address 属性为“/rest”,表示 REST 请求的相对路径,与 web.xml 中配置的“/ws/*”结合起来,最终的 REST 请求根路径是“/ws/rest”,在 ProductService 接口方法上 @Path 注解所配置的路径只是一个相对路径。
第五步、调用REST服务
<%@ 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://localhost:8080/springCxfREST/css/bootstrap.min.css" rel="stylesheet"> <link href="http://localhost:8080/springCxfREST/css/colorbox.css" rel="stylesheet" type="text/css" /></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 src="http://localhost:8080/springCxfREST/script/jquery.js" type="text/javascript"></script><script type="text/javascript" src="http://localhost:8080/springCxfREST/script/bootstrap.min.js"></script><script type="text/javascript" src="http://localhost:8080/springCxfREST/script/handlebars-v4.0.5.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() { //检索所有 $("#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); } }); }); }); function goColorBox(){ $("#goOne").colorbox({ opacity:0.65,width: 500, height:500, close: "关闭", overlayClose: true}); }</script></body></html>使用一个简单的 HTML 页面来调用 REST 服务,也就是说,前端发送 AJAX 请求来调用后端发布的 REST 服务。这里使用了 jQuery、Bootstrap、Handlebars.js 等技术。
第六步、发布并访问
将项目部署到tomcat服务器中,启动tomcat服务器后,访问:http://localhost:8080/springCxfREST(项目名称)/index.jsp。
第七步、CXF对AJAX跨域的支持
AJAX跨域问题解决通常有两种方案,分别是JSONP和CORS,CXF分别对其都有很好的支持。
1、JSONP
添加JSONP依赖
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-extension-providers</artifactId> <version>${cxf.version}</version></dependency>修改spring中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 自动生成
2、CORS
添加CORS依赖
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-security-cors</artifactId> <version>${cxf.version}</version></dependency>修改CXF在spring配置文件中的配置如下:
<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 特性。
0 0
- CXF系列之JAX-RS:CXF与spring集成发布REST服务
- CXF系列之JAX-RS:CXF发布与调用REST服务
- cxf jax-rs spring client
- REST,JAX-RS与Jersey,CXF,RESTEasy之间的关系
- WebService之CXF整合Spring框架发布REST服务
- CXF系列之JAX-WS:SOAP服务
- 使用CXF和spring发布rest服务
- 使用Spring与CXF编写rest服务
- REST:JAX-RS 与 Spring
- REST service example using CXF 2.2, JAX-RS 1.0, JAXB and Spring
- 框架 day64 WebService(注解),CXF框架(jax-ws,Jax-rs,与spring整合)
- WebService(注解),CXF框架(jax-ws,Jax-rs,与spring整合)
- CXF系列之JAX-WS:与Spring3集成并在tomcat部署
- webservice--CXF+Spring整合发布REST的服务
- 使用cxf发布rest服务接口,和spring的整合
- Spring整合CXF之发布WebService服务
- Spring整合CXF之发布WebService服务
- Spring整合CXF之发布WebService服务
- MACOSX下查看某个端口被哪个程序占用及杀进程方法
- 11月英语总结
- ZigBee Standard Security
- Gradle for Android 第一章:初识Gradle和Android Studio(上)
- lua 中continue的实现
- CXF系列之JAX-RS:CXF与spring集成发布REST服务
- UEditor 公式插件
- 快速访问StackOverFlow等未被墙但很慢的国外网站
- php之权限系统
- redo与append关系
- python学习笔记
- 基于nxp LPC1768开发板的U盘MP3播放
- IIR+全通滤波器实现相位平衡_matlab仿真
- 二分法查找元素