超越JAX-RS规范:Apache CXF搜索扩展

在今天的帖子中,我们将超越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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361288.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里巴巴使命、愿景、价值观、绩效管理中的六大价值观、

阿里巴巴的使命 让天下没有难做的生意 阿里巴巴的愿景 分享数据的第一平台幸福指数最高的企业“活102年”阿里巴巴的价值观 我们坚持“客户第一、员工第二、股东第三”。 阿里巴巴的六脉神剑&#xff08;绩效管理中的六大价值观&#xff09; 公司的“六脉神剑” 客户第一&#…

Angularjs基础(十)

ng-blur       描述&#xff1a;规定blur 事件的行为       实例&#xff1a;当输入框失去焦点的(onblur)时执行表达式&#xff1a;         <input ng-blur"count count 1" ng-init"count0"/>         <h1>{{co…

在命令行上操作JAR,WAR和EAR

尽管Java IDE和许多图形工具使查看和操作Java归档文件&#xff08;JAR&#xff0c;WAR和EAR&#xff09;文件的内容比以往更加容易&#xff0c;但有时我还是更喜欢使用命令行jar命令来完成这些任务。 当我必须重复做某事或作为脚本的一部分来做时&#xff0c;尤其如此。 在本文…

C#语言使用多态(接口与override) ——帮您剔除对面向对象多态性的疑惑

多态是面向对象编程中三大机制之一,其原理建立在"从父类继承而来的子类可以转换为其父类"这个规则之上,换句话说,能用父类的地方,就能用该类的子类.当从父类派生了很多子类时,由于每个子类都有其不同的代码实现,所以当用父类来引用这些子类时,同样的操作而可以表现出…

Java如何以及为什么使用Unsafe?

总览 sun.misc.Unsafe至少在Java 1.4&#xff08;2004&#xff09;中就已经存在于Java中。 在Java 9中&#xff0c;不安全将与许多其他供内部使用的类一起隐藏。 以提高JVM的可维护性。 尽管仍不确定究竟将取代Unsafe到底是什么&#xff0c;但我怀疑将取代Unsafe不仅仅是一件事…

Angularjs基础(三)

AngularJS ng-model 指令     ng-model 指令用于绑定应用程序数据到HTML 控制器&#xff08;input,select,textarea&#xff09;的值ng-model指令     ng-model指令可以将输入域的值与AngularJS 创建的变量绑定。       实例&#xff1a;         <di…

ASP.NET MVC的生命周期与网址路由

网址路由&#xff08;Routing&#xff09;在ASP.NET MVC中有两个主要用途&#xff0c;一个用途是匹配通过浏览器传来的HTTP请求&#xff0c;另一个用途则是将适当的网址返回浏览器。 首先我们来看下第一个用途&#xff0c;也就是匹配通过浏览器传来的HTTP请求。 客户端对ASP.NE…

ecshop分页类assign_pager分析和扩展

ecshop分页类assign_pager分析和扩展,我们前面的文章中介绍过ecshop ajax分页&#xff0c;他的基础都是简单单一的分页。如果我们要在ecshop分页里面传入自己的参数&#xff0c;你就必须对ecshop的assign_pager分页函数进行系统的认识和分析。 首先我们看category.php的ecshop分…

NEC css规范

CSS规范 - 分类方法 SS文件的分类和引用顺序 通常&#xff0c;一个项目我们只引用一个CSS&#xff0c;但是对于较大的项目&#xff0c;我们需要把CSS文件进行分类。 我们按照CSS的性质和用途&#xff0c;将CSS文件分成“公共型样式”、“特殊型样式”、“皮肤型样式”&#…

JDK 8中的流驱动的集合功能

这篇文章介绍了JDK 8的应用–引入了带有集合的 流 &#xff0c;以更简洁地完成通常需要的与集合相关的功能。 在此过程中&#xff0c;将演示并简要说明使用Java Streams的几个关键方面。 请注意&#xff0c;尽管JDK 8 Streams通过并行化支持提供了潜在的性能优势&#xff0c;但…

知识汇集

Oracle中锁介绍&#xff1a;http://space.itpub.net/26961876/viewspace-731300转载于:https://www.cnblogs.com/yaohonv/archive/2012/08/18/tech-col.html

jquery mobile 移动web(5)

有序列表   <div data-role"content">     <ol data-role"listview" data-theme"g">       <li><a href"#"> List 1</a></li>       <li><a href"#"> L…

cjmx:JConsole的命令行版本

当监视正在运行的Java应用程序时&#xff0c;JConsole是一个很好的工具。 但是&#xff0c;当无法使用JConsole直接连接到JVM&#xff08;例如&#xff0c;由于网络限制&#xff09;并且无法进行SSH隧道传输时&#xff0c;那么拥有命令行版本的JConsole会很棒。 jcmx是JConsol…

Android中SQLiteDatabase操作【附源码】

像我们做的很多应用程序及网站一样&#xff0c;基本都是对数据库进行增删改查来实现相应的功能。那么Android开发也一样&#xff0c;不过由于在移动客户端应用&#xff0c;所以不会像sql server、mysql那么复杂&#xff0c;Android应用程序支持本地数据库&#xff0c;SQLiteDat…

移动设备HTML5页面布局

在HTML5标准添加的新元素中&#xff0c;用于常见页面结 构的包括header footer footer nav aside aside article section hgroup 。 下面简单介绍一下这个元素&#xff1a; 1.header header>元素定义文档的页面组合&#xff0c;通 常是一些引导和导航信息&#xff0c;标签…

Hazelcast入门指南第5部分

这是我撰写的有关Hazelcast的一系列文章的延续。 我强烈建议您阅读其他内容&#xff1a; 第1 部分 &#xff0c; 第2 部分 &#xff0c; 第3 部分和第4部分 。 让人一见倾心的东西&#xff1f; 这篇文章中将没有Hazelcast专用代码。 让我重复一遍。 这篇文章中将没有Hazelcast…

【BEV感知算法概述——下一代自动驾驶感知算法】

文章目录 BEV感知算法概念BEV感知算法数据集介绍BEV感知算法分类BEV感知算法的优劣小结 BEV感知算法概念 Bird’s-Eye-View&#xff0c;鸟瞰图&#xff08;俯视图&#xff09;。BEV感知算法存在许多的优势。 首先&#xff0c;BEV视图存在遮挡小的优点&#xff0c;由于视觉的透…

jquery鼠标事件

click()   为点击事件绑定一个事件处理函数&#xff0c;或者触发元素点击事件。   .click( handler(eventObject) )     handler(eventObject)       每次事件触发时候执行的函数。   .click([eventData],handler(eventObject))     eventData      …

[LaunchPad] 超声波测试,数码管显示

1 #include "io430g2553.h"2 3 unsigned char Disp_Tab[] {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //段码控制 4 unsigned char dispbit[8]{0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F}; //位选控制 5 6 unsigned char LedOut[4];7 8 …

Spring的依赖注入陷阱

Spring框架中有三种注入变量&#xff1a; 基于二传手的注射 基于构造函数的注入 基于现场的注入 这些机制中的每一种都有优点和缺点&#xff0c;并且不仅只有一种正确的方法。 例如现场注入&#xff1a; Autowired private FooBean fooBean;在生产代码中使用它通常不是最好…