在今天的帖子中,我们将超越JAX-RS 2.0规范,并探索Apache CXF (流行的JAX-RS 2.0实现之一)为REST服务和API开发人员提供的有用扩展。 特别是,我们将讨论使用OData 2.0查询过滤器子集的搜索扩展。

简而言之,搜索扩展仅将某种过滤器表达式映射到一组匹配的类型化实体(Java类的实例)。 OData 2.0查询过滤器可能非常复杂,但是目前Apache CXF仅支持它们的子集:

操作员 描述
当量 等于 雷德蒙德市
NE 不相等 城市“伦敦”
gt 比...更棒 价格gt 20
ge 大于或等于 价格GE 10
lt 少于 价格lt 20
小于或等于 价格100
逻辑与 价格le 200和价格gt 3.5
要么 逻辑或 价格le 3.5或价格gt 200

基本上,要配置和激活JAX-RS服务的搜索扩展,只需定义两个属性search.query.parameter.namesearch.parser ,再加上一个附加提供程序SearchContextProvider

@Configuration
public class AppConfig {    @Bean( destroyMethod = "shutdown" )public SpringBus cxf() {return new SpringBus();}@Bean @DependsOn( "cxf" )public Server jaxRsServer() {final Map< String, Object > properties = new HashMap< String, Object >();        properties.put( "search.query.parameter.name", "$filter" );properties.put( "search.parser", new ODataParser< Person >( Person.class ) );final JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint( jaxRsApiApplication(), JAXRSServerFactoryBean.class );factory.setProvider( new SearchContextProvider() );factory.setProvider( new JacksonJsonProvider() );factory.setServiceBeans( Arrays.< Object >asList( peopleRestService() ) );factory.setAddress( factory.getAddress() );      factory.setProperties( properties );return factory.create();}@Bean public JaxRsApiApplication jaxRsApiApplication() {return new JaxRsApiApplication();}@Bean public PeopleRestService peopleRestService() {return new PeopleRestService();}
}

search.query.parameter.name定义用作过滤器的查询字符串参数的名称(我们将其设置为$ filter ),而search.parser定义用于解析过滤器表达式的解析器(我们设置将其与Person一起参数化为ODataParser )。 ODataParser建立在出色的Apache Olingo项目之上, 该项目当前实现了OData 2.0协议(正在支持OData 4.0 )。

配置完成后,任何JAX-RS 2.0服务都可以通过注入上下文参数SearchContext来受益于搜索功能。 让我们通过定义REST服务来管理下面的Person类所代表的人员,来了解实际情况

public class Person {private String firstName;private String lastName;private int age;// Setters and getters here
}

PeopleRestService将只允许使用来创建新的个人HTTP POST和使用进行搜索HTTP GET,/搜索端点所列:

package com.example.rs;import java.util.ArrayList;
import java.util.Collection;import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;import org.apache.cxf.jaxrs.ext.search.SearchCondition;
import org.apache.cxf.jaxrs.ext.search.SearchContext;import com.example.model.Person;@Path( "/people" )
public class PeopleRestService {private final Collection< Person > people = new ArrayList<>();@Produces( { MediaType.APPLICATION_JSON  } )@POSTpublic Response addPerson( @Context final UriInfo uriInfo,@FormParam( "firstName" ) final String firstName, @FormParam( "lastName" ) final String lastName,@FormParam( "age" ) final int age ) {      final Person person = new Person( firstName, lastName, age );people.add( person );return Response.created( uriInfo.getRequestUriBuilder().path( "/search" ).queryParam( "$filter=firstName eq '{firstName}' and lastName eq '{lastName}' and age eq {age}" ).build( firstName, lastName, age ) ).entity( person ).build();}@GET@Path("/search")@Produces( { MediaType.APPLICATION_JSON  } )public Collection< Person > findPeople( @Context SearchContext searchContext ) {        final SearchCondition< Person > filter = searchContext.getCondition( Person.class );return filter.findAll( people );}
}

findPeople方法是我们正在寻找的方法。 由于Apache CXF所做的所有努力,该方法看起来非常简单:注入了SearchContext ,并从$ filter查询字符串参数中自动提取了过滤器表达式。 最后一部分是将过滤器应用于数据,在我们的例子中,它只是一个名为people的集合。 非常干净和直接。

让我们构建项目并运行它:

mvn clean package
java -jar target/cxf-search-extension-0.0.1-SNAPSHOT.jar

使用很棒的curl工具,让我们发出几个HTTP POST请求,以生成一些数据以针对以下条件运行过滤器查询:

> curl http://localhost:8080/rest/api/people -X POST -d "firstName=Tom&lastName=Knocker&age=16"
{"firstName": "Tom","lastName": "Knocker","age": 16
}> curl http://localhost:8080/rest/api/people -X POST -d "firstName=Bob&lastName=Bobber&age=23"
{"firstName": "Bob","lastName": "Bobber","age": 23
}> curl http://localhost:8080/rest/api/people -X POST -d "firstName=Tim&lastName=Smith&age=50"
{"firstName": "Tim","lastName": "Smith","age": 50
}

有了示例数据,让我们继续前进,提出几个不同的搜索条件,这些条件足够复杂,足以展示OData 2.0查询过滤器的强大功能:

  • 查找所有名字Bob的人 ($ filter = “ firsteq eq'Bob'”
> curl -G -X GET http://localhost:8080/rest/api/people/search --data-urlencode $filter="firstName eq 'Bob'"
[{"firstName": "Bob","lastName": "Bobber","age": 23}
]
  • 查找所有姓氏Bobber姓氏 Smith名字不是Bob的人 ($ filter = “ lastName eq'Bobber'或(lastName eq'Smith'and firstName ne'Bob')” ))
> curl -G -X GET http://localhost:8080/rest/api/people/search --data-urlencode $filter="lastName eq 'Bobber' or (lastName eq 'Smith' and firstName ne 'Bob')"
[{"firstName": "Bob","lastName": "Bobber","age": 23},{    "firstName": "Tim","lastName": "Smith","age": 50}
]
  • 查找其名字开始从字母T,谁所有的人在16岁以上($ =过滤器“名字EQ‘T *’和年龄GE 16”)
> curl -G -X GET http://localhost:8080/rest/api/people/search --data-urlencode $filter="firstName eq 'T*' and age ge 16"
[{"firstName": "Tom","lastName": "Knocker","age": 16},{"firstName": "Tim","lastName": "Smith","age": 50}
]

注意 :如果在类似Linux的环境中运行此命令,则可能需要使用\ $转义$符号,例如:
curl -X GET -G http:// localhost:8080 / rest / api / people / search –data-urlencode \ $ filter =“ firstName eq'Bob'”

目前, Apache CXF仅提供OData 2.0查询过滤器的基本支持,并保留了许多强大的表达式。 但是,一旦社区对使用此功能表示出足够的兴趣,就有承诺将其推进。

值得一提的是, OData 2.0查询过滤器不是唯一可用的选项。 搜索扩展还支持FIQL (提要项查询语言),而来自Apache CXF核心开发人员之一的精彩文章也对其进行了很好的介绍。

我认为Apache CXF的这一非常有用的功能可以通过为JAX-RS 2.0服务提供简单(而不是那么简单)的搜索功能来节省大量时间和精力。 如果适合您的应用程序需求,请尝试一下。

  • 完整的项目源代码可在Github上获得 。

翻译自: https://www.javacodegeeks.com/2014/12/beyond-the-jax-rs-spec-apache-cxf-search-extension.html

超越JAX-RS规范:Apache CXF搜索扩展相关推荐

  1. Apache CXF框架简介

    Apache CXF框架是一个开源的Web Services框架,它来源于两个开源项目--ObjectWeb Celtix(ESB产品)和Codehaus XFire(SOAP堆栈软件) Apache ...

  2. Apache CXF 3.0:CDI 1.1支持替代Spring

    几周前刚刚发布了Apache CXF 3.0 ,该项目又迈出了满足JAX-RS 2.0规范要求的又一个重要步骤:与CDI 1.1集成. 在此博客文章中,我们将看几个有关Apache CXF 3.0和A ...

  3. apache-cxf 使用_使用Apache CXF进行Web服务学习

    apache-cxf 使用 在我的最后几个项目中,我使用了Web服务,在某些地方创建它们并在其他地方使用它们. 我认为标准任务(例如创建客户端,创建Web服务等)非常简单,如果遇到问题,有足够的资源. ...

  4. Apache CXF 3.0:CDI 1.1支持可替代Spring

    在几周前刚刚发布Apache CXF 3.0时 ,该项目又迈出了满足JAX-RS 2.0规范要求的又一个重要步骤:与CDI 1.1集成. 在此博客文章中,我们将看几个有关Apache CXF 3.0和 ...

  5. Apache CXF 3.0:JAX-RS 2.0和Bean验证1.1最终一起

    即将发布的出色的Apache CXF框架3.0版 (当前处于里程碑2阶段)带来了许多有趣且有用的功能,越来越接近提供完整的JAX-RS 2.0支持. Bean Validation 1.1的支持是我们 ...

  6. 使用Apache CXF进行Web服务学习

    在我的最后几个项目中,我使用了Web服务,在某些地方创建它们并在其他地方使用它们. 我觉得创建客户端,创建Web服务等标准任务非常简单,如果遇到问题,有足够的资源. 但是对于Web服务,这是一项琐碎的 ...

  7. cxf springmvc_拥抱模块化Java平台:Java 10上的Apache CXF

    cxf springmvc 自Java 9发布最终将Project Jigsaw交付给大众以来,已经过去了整整一年的时间. 这是一段漫长的旅程,但是在那里,所以发生了什么变化? 这是一个很好的问题,答 ...

  8. java cxf_拥抱模块化Java平台:Java 10上的Apache CXF

    java cxf Java 9版本终于将Project Jigsaw交付给大众已经过去了一年的时间. 这是一段漫长的旅程,但是在那里,所以发生了什么变化? 这是一个很好的问题,答案并不明显和直接. 总 ...

  9. 拥抱模块化Java平台:Java 10上的Apache CXF

    Java 9版本终于将Project Jigsaw交付给大众已经过去了一年多的时间. 这是一段漫长的旅程,但是在那里,所以发生了什么变化? 这是一个很好的问题,答案并不明显和直接. 总的来说, 拼图项 ...

最新文章

  1. python读取.so_Python入门-编译安装Python3教程
  2. 聊聊HystrixEventNotifier
  3. uC/OS-II OS_TASK.C中有关任务管理的函数
  4. shell脚本if和switch语句编写案例
  5. 分布式系统面试 - 常见问题
  6. mysql数据库别名_MySQL数据库表名、列名、别名区分大小写的问题
  7. Coding WebIDE 开放支持第三方 Git 仓库
  8. redis事务冲突问题 - 乐观锁和悲观锁
  9. cocoapods 总结
  10. zmap扫描mysql_zmap/masscan 快速扫描网络
  11. 计算机科班比其他专业有多少优势呢?
  12. android商品标签,TextView首行缩进效果(商品标签)
  13. 禁用笔记本键盘和触摸板
  14. 一步一步教你网站采集规则
  15. 毕业设计 基于JSP动漫论坛的设计与实现
  16. 30ea是什么意思_数量单位EA是什么意思?EACH? 单位EA是什么意思
  17. 浙江污水处理厂数字孪生平台建模_三维激光扫描_吉优赛维三维可视化管理平台_三维建模_3D模型
  18. 二、C++反作弊对抗实战 (进阶篇 —— 16.如何实现游戏加速瞬移与对抗)
  19. 大数据权限管理组件Apache Ranger简介和原理
  20. 15min掌握正则表达式

热门文章

  1. JS中用构造函数创建对象
  2. react-redux模型图
  3. Android中异步任务AsyncTask的使用
  4. 百度地图描绘轨迹html,百度地图API 绘制轨迹历史
  5. tp中怎么执行mysql事务_tp中使用事务
  6. ArrayList整理
  7. 本地方法(JNI)——访问域+字符串参数
  8. rest资源设计_REST资源何时应获得其自己的地址?
  9. 如何在Flutter(REST API)中进行API调用
  10. java 设计模式 示例_Java中的访问者设计模式–示例教程