您的JAX-RS API并非天生就等于:使用动态功能

这次,我们将讨论一些有关JAX-RS 2.0 API的内容,并涉及该规范的一个非常有趣的方面: 动态功能以及它们的有用性。

传统上,当配置和部署JAX-RS 2.0 API(使用Application类,从servlet引导或通过RuntimeDelegate创建)时,可以选择注册其他提供程序和功能 。 其中一个很好的例子是bean验证(JSR 349)或用于JSON处理的Java API(JSR-353)支持。 这些提供程序和功能将被应用于所有JAX-RS 2.0资源,并且在大多数使用情况下,这是理想的行为。 但是,有时需要仅为某些资源启用特定的提供程序或功能 ,而使其他资源不受影响。 这正是动态功能将为我们带来很大帮助的用例。

在本文中,我们将使用出色的Apache CXF框架的最新版本3.1.5 ,但是动态功能是JAX-RS 2.0规范的一部分,并且大多数(如果不是全部)实现都支持这些功能。

让我们考虑一个非常简单的JAX-RS 2.0 API,用一种方法来处理HTTP GET请求来管理人员。 让我们假设这是API的版本1 ,尽管为count查询参数指定了@Range批注,但从未实现过对它的支持,并且它在代码中仅用于文档目的。

@Path("/v1/people")
public class PeopleRestService {@Produces( { MediaType.APPLICATION_JSON } )@GETpublic List<Person> getAll(@Range(min = 1, max = 10) @QueryParam("count") int count) {return Collections.nCopies(count, new Person("a@b.com", "A", "B"));}
}

在这种情况下,为count查询参数传递无效值将导致Internal Server Error 。 让我们确保这就是正在发生的事情:

$ curl -i http://localhost:8080/rest/api/v1/people?count=-1HTTP/1.1 500 Server Error
Cache-Control: must-revalidate,no-cache,no-store
Content-Type: text/html;charset=iso-8859-1
Content-Length: 377
Connection: close
Server: Jetty(9.3.7.v20160115)

一段时间后,我们意识到了该API的问题,并决定使用Bean Validation 1.1与JAX-RS 2.0的集成来实施适当的验证机制。 但是,我们决定创建该API的版本2 ,并保持版本1不变,因为其客户端不希望返回除200500之外的任何其他HTTP状态代码(不幸的是,在现实生活中,它经常发生) 。

有两种不同的方法可以实现这种基于API的自定义,但是最简单的方法可能是通过引入专用注释,例如@EnableBeanValidation ,并使用它来注释JAX-RS 2.0资源类:

@Path("/v2/people")
@EnableBeanValidation
public class ValidatingPeopleRestService {@Produces( { MediaType.APPLICATION_JSON } )@GETpublic @Valid List<Person> getAll(@Range(min = 1, max = 10) @QueryParam("count") int count) {return Collections.nCopies(count, new Person("a@b.com", "A", "B"));}
}

为了为所有使用@EnableBeanValidation注释的JAX-RS 2.0 API启用Bean验证1.1 ,我们将创建一个动态要素类BeanValidationDynamicFeature

@Provider
public class BeanValidationDynamicFeature implements DynamicFeature {private final JAXRSBeanValidationInInterceptor inInterceptor;private final JAXRSBeanValidationOutInterceptor outInterceptor;public BeanValidationDynamicFeature(final BeanValidationProvider provider) {this.inInterceptor = new JAXRSBeanValidationInInterceptor();this.inInterceptor.setProvider(provider);this.outInterceptor = new JAXRSBeanValidationOutInterceptor();this.outInterceptor.setProvider(provider);}@Overridepublic void configure(final ResourceInfo resourceInfo, final FeatureContext context) {if (resourceInfo.getResourceClass().getAnnotation(EnableBeanValidation.class) != null) {context.register(inInterceptor);context.register(outInterceptor);}}
}

它的工作非常简单,只需将JAXRSBeanValidationInInterceptorJAXRSBeanValidationOutInterceptor拦截器实例注册为有问题的JAX-RS 2.0 API的其他提供程序 。 不过,有一个小小的但重要的注意事项: 动态功能 (至少就Apache CXF实现而言)不支持异常映射器,并且应将其注册为常规提供程序 (以及动态功能本身),例如:

@Bean @DependsOn("cxf")
public Server jaxRsServer() {final JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint( jaxRsApiApplication(), JAXRSServerFactoryBean.class );factory.setServiceBean(validatingPeopleRestService());factory.setServiceBean(peopleRestService());factory.setProvider(new JacksonJsonProvider());factory.setProvider(new BeanValidationDynamicFeature(new BeanValidationProvider()));factory.setProvider(new ValidationExceptionMapper());return factory.create();
}@Bean 
public JaxRsApiApplication jaxRsApiApplication() {return new JaxRsApiApplication();
}@Bean 
public ValidatingPeopleRestService validatingPeopleRestService() {return new ValidatingPeopleRestService();
}@Bean 
public PeopleRestService peopleRestService() {return new PeopleRestService();
}

这基本上就是我们要做的。 一旦注册了BeanValidationDynamicFeature (在本例中使用JAXRSServerFactoryBean ),它将被应用于所有匹配的服务Bean。 让我们确保对于人员管理API的版本2 ,触发了正确的即用型验证:

$ curl -i http://localhost:8080/rest/api/v2/people?count=-1HTTP/1.1 400 Bad Request
Content-Length: 0
Server: Jetty(9.3.7.v20160115)

这次响应是不同的,表明客户机已经提交了无效的输入(正在运行Bean Validation 1.1的直接结果): Bad Request

希望动态功能将成为工具箱中的另一个有用工具。 我们这里介绍的示例有些虚构,但是使用具有安全性,跟踪,日志记录,性能分析等动态功能非常容易。此外,即使在特定资源方法上也可以应用动态功能 ,从而可以对API进行细粒度的控制。

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

翻译自: https://www.javacodegeeks.com/2016/02/jax-rs-apis-not-born-equal-using-dynamic-features.html

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

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

相关文章

ionic2 安装与cordova打包

1.安装&#xff1a; cnpm install -g cordova ionic ionic start name cd name cnpm install 2、环境配置&#xff1a; http://www.cnblogs.com/changyaoself/p/6544082.html 这里是具体配置。 测试环境&#xff1a; cordova platform list 如下才可以&#xff1a; 3、添加…

mysql vacuum_PostgreSQL DBA快速入门(四) - 体系架构

PostgreSQL在开源关系型数据库市场是最先进的数据库。他的第一个版本在1989年发布&#xff0c;从那时开始&#xff0c;他得到了很多扩展。根据db-enginers上的排名情况&#xff0c;PostgreSQL目前在数据库领域排名第四。 本篇博客&#xff0c;我们来讨论一下PostgreSQL的内部架…

(ab)使用Java 8 FunctionalInterfaces作为本地方法

如果您使用Scala或Ceylon甚至JavaScript等更高级的语言进行编程&#xff0c;则“嵌套函数”或“本地函数”是您非常常见的习惯用法。 例如&#xff0c;您将编写诸如fibonacci函数之类的东西&#xff1a; def f() {def g() "a string!"g() "– says g" …

mysql的配置实现远程访问_MySQL 远程连接配置的正确实现 | 学步园

此文章主要向大家描述的是MySQL远程连接配置的实际操作步骤&#xff0c;以及在其实际操作中值得我们大家注意的相关事项的描述&#xff0c; 以下就是具体方案的描述&#xff0c;希望在你今后的学习中会有所帮助。MySQL远程配置GRANT ALL PRIVILEGES ON *.* TO root% IDENTIFIED…

oracle 用户账户被锁处理

一、以管理员身份登录 SQL> conn sys/sys as sysdba; &#xff08;分号是必须的但是我是以system登录的所在这不应该写conn sys/sys as sysdba应该写conn system/orcl as sysdba;&#xff09;Connected. 二、解锁被锁用户SQL> alter user scott account unlock;User alte…

总结mysql的基础语法_mysql 基础sql语法总结 (二)DML

二、DML(增、删、改)1)插入数据第一种写法&#xff1a;INSERT INTO 表名 (列名1&#xff0c;列名2&#xff0c;&#xff0c;......)VALUES(列值1&#xff0c;列值2&#xff0c;......)第二种写法&#xff1a;INSERT INTO 表名 VALUES(列值1&#xff0c;列值2&#xff0c;......…

提高团队协作效率

提高团队协作效率 分工合理&#xff0c;责任明确 团队是由个人组成的&#xff0c;团队中的个人往往经历不同、背景不同、性格有差异、水平有高低。在团队形成后、正式开工前&#xff0c;首先应该进行合理分工&#xff0c;要结合每个 人的特点和爱好&#xff0c;充分发挥出每个人…

mysql远程访问时间长无反应_远程MySQL访问需要很长时间

Running a MySQL query on a local database takes only about 20-30ms but running the same query through a remote connection(internet) takes 500ms. Is this normal? If not what could be the possible reason for such delay?This is a wireshark time extract for …

c# 利用AForge和百度AI开发实时人脸识别

baiduAIFaceIdentify项目是C#语言&#xff0c;集成百度AI的SDK利用AForge开发的实时人脸识别的小demo&#xff0c;里边包含了人脸检测识别&#xff0c;人脸注册&#xff0c;人脸登录等功能 人脸实时检测识别功能 思路是利用AForge打开摄像头&#xff0c;通过摄像头获取到的图像…

Java中Array和ArrayList之间的9个区别

array和ArrayList都是Java中两个重要的数据结构&#xff0c;在Java程序中经常使用。 即使ArrayList在内部由数组支持&#xff0c;了解Java中的数组和ArrayList之间的差异对于成为一名优秀的Java开发人员也至关重要。 如果您知道相似点和不同点&#xff0c;则可以明智地决定何时…

python读二进制文件遍历_使用python反向读取二进制文件

从这个问题中我可以看出代码中有几点需要改进。首先&#xff0c;while循环在Python中很少使用&#xff0c;因为使用for循环或使用一些内置函数几乎总是有更好的方法来表达相同的内容。在我想代码纯粹是为了培训目的。否则&#xff0c;我会首先问真正的目标是什么(因为知道了问题…

vue 在已有的购买列表中(数据库返回的数据)修改商品数量

连续加班一个月 连续通宵三天 到最后还是少了一个功能 心碎 简介&#xff1a;一个生成好的商品列表&#xff08;数据库返回的数据&#xff09; 首先拿到我们需要渲染的数组 在data中定义 我是在测试的时候 直接写了两条数据 下面开始点击删除 点击添加是一样的代码 只不过加号…

python饼状图教程_Python数据可视化:饼状图的实例讲解

使用python实现论文里面的饼状图&#xff1a;原图&#xff1a;python代码实现&#xff1a;# # 饼状图# plot.figure(figsize(8,8))labels [uCanteen, uSupermarket, uDorm, uOthers]sizes [73, 21, 4, 2]colors [red, yellow, blue, green]explode (0.05, 0, 0, 0)patches,…

小看--单例设计模式

&#xff08;一&#xff09;单例设计描述 只要了解过设计模式的同学都会知道&#xff1a;单例设计模式&#xff0c;大家都知道单例设计模式是一种创建行的设计模式。既然是创建型&#xff0c;那么先来讲讲&#xff0c;对象的创建的过程吧。 --静态成员&#xff1a;静态成员在程…

动态方法注入 grails_Grails动态下拉菜单

动态方法注入 grails最近&#xff0c;我有一个UI要求&#xff0c;客户希望从两个单独的下拉列表中选择值。 第一个下拉列表的值实质上过滤了第二个下拉列表的值。 鉴于我们支持的财务项目对UI的要求并不严格&#xff0c;因此我不得不进行一些初步的学习和试验&#xff0c;以实现…

selenium原理python_从python角度解析selenium原理

1、selenium工作流程2、selenium工作原理(1)客户端和服务端之间实际是通过http协议进行通信&#xff0c;服务端的接口文档可参考&#xff1a;https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#sessionsessionidelement(2)客户端按照服务端接口要求传入请求方式、…

Jmeter(二)Jmeter目录介绍

看过许多有关Jmeter的博客&#xff0c;算得上的收获颇丰&#xff1b;不过最牛逼的博客还是“官方文档”&#xff0c;官方文档是ApacheJmeter自己对自己产品的说明&#xff0c;论起对自己产品的理解程度&#xff0c;那肯定是自己嘛。。。因此推荐大家从Jmeter的官方文档开始学习…

使用Spring Data MongoDB和Spring Boot进行数据聚合

MongoDB聚合框架旨在对文档进行分组并将其转换为聚合结果。 聚合查询包括定义将在管道中执行的几个阶段。 如果您对有关该框架的更深入的细节感兴趣&#xff0c;那么 mongodb docs是一个很好的起点。 这篇文章的重点是编写一个用于查询mongodb的Web应用程序&#xff0c;以便从…

结合前段修改mysql表数据_jquery实现点击文字可编辑并修改保存至数据库

这个方法网上可以查到很多&#xff0c;但是好多只有点击文字编辑并保持&#xff0c;但是没有完整的代码写怎么保存到数据库。因为本人才疏学浅&#xff0c;费啦好长时间才写好把修改的内容只用一条sql语句保存到数据库&#xff0c;今天在这里和大家分享这是运行图片这是前台页面…

关于类、抽象类和接口的继承关系

关于类、抽象类和接口的继承关系 Java类的继承是单继承的&#xff0c;就是一个类只能继承一个类&#xff0c;但是可以通过接口来实现多继承&#xff0c;一个类可以实现多个接口。通过这种方式&#xff0c;Java类就可以实现多继承的关系。但是在继承类和实现接口的时候&#xff…