这次,我们将讨论一些有关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

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

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

    jax-rs jax-ws 这次,我们将讨论一些有关JAX-RS 2.0 API的内容,并涉及规范的一个非常有趣的方面: 动态功能及其实用性. 传统上,当配置和部署JAX-RS 2.0 API(使用A ...

  2. python使用fpdf的multi_cell API实现长文本写入的自动换行功能实战

    python使用fpdf的multi_cell API实现长文本写入的自动换行功能实战 目录 python使用fpdf的multi_cell API实现长文本写入的自动换行功能实战

  3. 【百度地图API】暑假放假回老家——城市切换功能

    原文:[百度地图API]暑假放假回老家--城市切换功能 任务描述: 酸奶小妹放寒假啦,要从北京呼啦一下飞回重庆呢.现在百度地图API上不能直接切换城市,怎么办呢? 如何实现: 利用API先搜索到要去城 ...

  4. android敏感api函数,基于敏感API调用的Android应用程序动态监控

    摘要: 近年来,Android操作系统凭借其开源的优势,占领了移动操作系统市场.Android通过对外提供API接口重组资源,吸引了大量第三方开发人员创造出功能丰富的Android应用.但是,由于An ...

  5. 使用vue+腾讯地图API GL实现地图选房的功能

    使用vue+腾讯地图API GL实现地图选房的功能 背景介绍 公司最近想做一个地图选房的功能,在网上找了很久也没有找到这方面的demo,就只好硬着头皮自己写一个地图选房的功能 腾讯地图的官方文档.首先 ...

  6. 借助Bing Translate API翻译API实现网站多国语言翻译功能

    前几天发了篇<借助Google Translate API实现网站多国语言翻译功能>,但好心人告诉我,谷歌即将关闭一些API,其中就包括谷歌翻译的API,以下是原文: 最近Google宣布 ...

  7. jax rs mysql_liferay7-rest开发JAX-RS规范详解

    简介 JAX-RS (JSR-311) 是为 Java EE 环境下的 RESTful 服务能力提供的一种规范.它能提供对传统的基于 SOAP 的 Web 服务的一种可行替代. 在本文中,了解 JAX ...

  8. jax rs mysql_Jersey / JAX-RS ExceptionMapper MySQL

    我正在学习Jersey / JAX-RS,我需要一些ExceptionMapper的帮助 . 我有一个UserFacade类,AbstractFacade类和User类本身,都非常标准,主要是通过在N ...

  9. jax rs mysql_JAX-RS示例(Jersey)

    我们可以通过 jersey 实现创建JAX-RS示例. 为此,需要加载 jersey相关jar文件或使用Maven框架. 在这个例子中,我们使用jersey jar文件来实现JAX-RS jersey ...

最新文章

  1. 股市币市:数据分析与交易所最新公告(20190302)
  2. Science:细菌和古菌多重抗性系统抵御噬菌体和外来质粒
  3. Ruby on Rails的下载及安装以及开发环境的搭建
  4. bzoj4817: [Sdoi2017]树点涂色
  5. 实现一个通用的中英文排序工具
  6. python之路----验证客户端合法性
  7. Linux内核里的“智能指针” (续)
  8. 实现BUG自动检测 - ASP.NET Core依赖注入
  9. 使用keepalived搭建mysql主从备份、切换
  10. 10-11-010-简介-架构-架构简介
  11. amazeui学习笔记--js插件(UI增强4)--下拉组件Dropdown
  12. Lingo 的基本使用入门
  13. 赵某于2011年3月23夜被捕获
  14. C/C++ 动态检测内存错误利器 - ASan
  15. php自动生成后门代码,PHP小后门代码
  16. java去除水印_易剪辑,分享一款免费的去除水印的工具
  17. 大二女生web开发成长之路——讲述我从软妹子到女汉子的进阶过程
  18. 映秀的春天--纪念5·12汶川大地震一周年
  19. 多媒体中控软件开发流程_网络多媒体:视频工作流程提示
  20. RBC(Radio Block Center)无线闭塞中心

热门文章

  1. 接口 DataInput
  2. 【git】如何在github上推送并部署自己的项目
  3. React中的各个目录文件功能
  4. Android音频处理 PCM格式
  5. Python MySQL 插入表
  6. java schema名_关于Schema的名字空间
  7. springboot-Initializer例子及分析
  8. 局部描述符表LDT的作用+定义+初始化+跳转相关
  9. restful rest_HATEOAS的RESTful服务。 超媒体:REST的秘密要素
  10. java设计模式教程_Java设计模式教程