您的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不变,因为其客户端不希望返回除200和500之外的任何其他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);}}
}
它的工作非常简单,只需将JAXRSBeanValidationInInterceptor和JAXRSBeanValidationOutInterceptor拦截器实例注册为有问题的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
您的JAX-RS API并非天生就等于:使用动态功能相关推荐
- jax-rs jax-ws_您的JAX-RS API并非天生就等于:使用动态功能
jax-rs jax-ws 这次,我们将讨论一些有关JAX-RS 2.0 API的内容,并涉及规范的一个非常有趣的方面: 动态功能及其实用性. 传统上,当配置和部署JAX-RS 2.0 API(使用A ...
- python使用fpdf的multi_cell API实现长文本写入的自动换行功能实战
python使用fpdf的multi_cell API实现长文本写入的自动换行功能实战 目录 python使用fpdf的multi_cell API实现长文本写入的自动换行功能实战
- 【百度地图API】暑假放假回老家——城市切换功能
原文:[百度地图API]暑假放假回老家--城市切换功能 任务描述: 酸奶小妹放寒假啦,要从北京呼啦一下飞回重庆呢.现在百度地图API上不能直接切换城市,怎么办呢? 如何实现: 利用API先搜索到要去城 ...
- android敏感api函数,基于敏感API调用的Android应用程序动态监控
摘要: 近年来,Android操作系统凭借其开源的优势,占领了移动操作系统市场.Android通过对外提供API接口重组资源,吸引了大量第三方开发人员创造出功能丰富的Android应用.但是,由于An ...
- 使用vue+腾讯地图API GL实现地图选房的功能
使用vue+腾讯地图API GL实现地图选房的功能 背景介绍 公司最近想做一个地图选房的功能,在网上找了很久也没有找到这方面的demo,就只好硬着头皮自己写一个地图选房的功能 腾讯地图的官方文档.首先 ...
- 借助Bing Translate API翻译API实现网站多国语言翻译功能
前几天发了篇<借助Google Translate API实现网站多国语言翻译功能>,但好心人告诉我,谷歌即将关闭一些API,其中就包括谷歌翻译的API,以下是原文: 最近Google宣布 ...
- jax rs mysql_liferay7-rest开发JAX-RS规范详解
简介 JAX-RS (JSR-311) 是为 Java EE 环境下的 RESTful 服务能力提供的一种规范.它能提供对传统的基于 SOAP 的 Web 服务的一种可行替代. 在本文中,了解 JAX ...
- jax rs mysql_Jersey / JAX-RS ExceptionMapper MySQL
我正在学习Jersey / JAX-RS,我需要一些ExceptionMapper的帮助 . 我有一个UserFacade类,AbstractFacade类和User类本身,都非常标准,主要是通过在N ...
- jax rs mysql_JAX-RS示例(Jersey)
我们可以通过 jersey 实现创建JAX-RS示例. 为此,需要加载 jersey相关jar文件或使用Maven框架. 在这个例子中,我们使用jersey jar文件来实现JAX-RS jersey ...
最新文章
- 股市币市:数据分析与交易所最新公告(20190302)
- Science:细菌和古菌多重抗性系统抵御噬菌体和外来质粒
- Ruby on Rails的下载及安装以及开发环境的搭建
- bzoj4817: [Sdoi2017]树点涂色
- 实现一个通用的中英文排序工具
- python之路----验证客户端合法性
- Linux内核里的“智能指针” (续)
- 实现BUG自动检测 - ASP.NET Core依赖注入
- 使用keepalived搭建mysql主从备份、切换
- 10-11-010-简介-架构-架构简介
- amazeui学习笔记--js插件(UI增强4)--下拉组件Dropdown
- Lingo 的基本使用入门
- 赵某于2011年3月23夜被捕获
- C/C++ 动态检测内存错误利器 - ASan
- php自动生成后门代码,PHP小后门代码
- java去除水印_易剪辑,分享一款免费的去除水印的工具
- 大二女生web开发成长之路——讲述我从软妹子到女汉子的进阶过程
- 映秀的春天--纪念5·12汶川大地震一周年
- 多媒体中控软件开发流程_网络多媒体:视频工作流程提示
- RBC(Radio Block Center)无线闭塞中心