jax-rs jax-ws_您的JAX-RS API并非天生就等于:使用动态功能
jax-rs jax-ws
這次,我們將討論一些有關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 jax-ws
總結
以上是生活随笔為你收集整理的jax-rs jax-ws_您的JAX-RS API并非天生就等于:使用动态功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 康熙是哪个朝代的皇帝(清圣祖仁皇帝爱新觉
- 下一篇: tlc和qlc固态哪个好(两者有什么区别