做网站 简单外包,个体户 做网站,所有购物软件,官方微信公众号怎么创建这次#xff0c;我们将讨论一些有关JAX-RS 2.0 API的内容#xff0c;并涉及该规范的一个非常有趣的方面#xff1a; 动态功能以及它们的有用性。 传统上#xff0c;当配置和部署JAX-RS 2.0 API#xff08;使用Application类#xff0c;从servlet引导或通过RuntimeDelega… 这次我们将讨论一些有关JAX-RS 2.0 API的内容并涉及该规范的一个非常有趣的方面 动态功能以及它们的有用性。 传统上当配置和部署JAX-RS 2.0 API使用Application类从servlet引导或通过RuntimeDelegate创建时可以选择注册其他提供程序和功能 。 其中一个很好的例子是bean验证JSR 349或用于JSON处理的Java APIJSR-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 ListPerson getAll(Range(min 1, max 10) QueryParam(count) int count) {return Collections.nCopies(count, new Person(ab.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;charsetiso-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 ListPerson getAll(Range(min 1, max 10) QueryParam(count) int count) {return Collections.nCopies(count, new Person(ab.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