前言
Quarkus和RESTEasy团队非常高兴地宣布了Quarkus中的RESTEasy Reactive集成已进入master分支,并将成为下一个Quarkus 1.11发行版的一部分。我们期待每个人对其进行测试。并为我们提供尽可能多的反馈。以典型的Quarkus方式,该项目可作为一组新的扩展使用。这是一个非常令人兴奋的消息,所以博主用自己蹩脚的英语 google翻译翻译了官方的公告,迫不及待的想要和大家分享。
Quarkus Graalvm技术QQ群:871808563,点我加群
Quarkus blog地址:https://quarkus.io/blog/resteasy-reactive/
它是什么?
正如您可能从名称中猜到的那样,该工作是从头开始编写的新JAX-RS实现,可在我们的通用Vert.x层上工作,因此具有完全的反应性,同时还与Quarkus紧密集成,因此移动了很多特定于框架的工作(例如注释扫描和元模型生成)以建立时间。
为什么非常重要?
最简单的答案是,您可以继续利用广泛使用且功能强大的JAX-RS API为应用程序公开REST层,同时显着提高应用程序可以实现的最大吞吐量。该应用程序还应该稍微加快启动速度,并占用更少的内存。
我们的基准测试表明,此新扩展的可测量性能几乎与我们使用Quarkus的Reactive Routes API(它本身是一个非常有趣的API,但通常级别较低)所达到的性能相同,更不用说这是开发人员需要学习的新API)。
此外,将我们的结果与提供基于注释的REST层的其他竞争企业Java框架进行比较时,根据基准,Quarkus提供的吞吐量是原来的两倍。
还有什么其他好处?
好像熟悉的API和新扩展的改进的运行时特性还不够,我们添加了一些真正令人兴奋且方便的新功能(这些功能不是JAX-RS规范的一部分),这些功能是社区所要求的,或者我们觉得可以改善开发人员的体验,并减轻某些规范的毛病。这些新功能是:
- 默认不阻塞:现在,默认情况下,所有端点都在IO线程上运行。您可以@Blocking用来更改它。
- 计分系统:在开发人员模式启动时,该应用程序将为您显示端点列表,以及性能得分,告诉您为什么端点比最佳版本慢。这有助于弄清楚如何提高REST性能。
新的请求/响应过滤器设计
JAX-RS过滤器需要实现一个接口并将上下文对象作为字段注入,这既昂贵又不灵活。基于我们在Quarkus构建系统中的成功,现在过滤器只是带有注释的方法,并且会自动注入任何参数:
代码语言:javascript复制public class CustomContainerRequestFilter {
@ServerRequestFilter
public void whatever(UriInfo uriInfo, HttpHeaders httpHeaders, ContainerRequestContext requestContext) {
String customHeaderValue = uriInfo.getPath() "-" httpHeaders.getHeaderString("some-input");
requestContext.getHeaders().putSingle("custom-header", customHeaderValue);
}
}
此外,如果过滤器需要执行阻止操作,则它们可以返回Uni并且RESTEasy Reactive在执行过滤器时不会阻止事件循环线程。
最后,尽管我们还没有完成,但是可以很容易地将此方法扩展到其他类型的JAX-RS Provider,从而完全不需要@Context在其代码中使用。
新*Param注解
这些注释意味着要用来代替JAX-RS @PathParam,@QueryParam等注释,而不必需要指定一个名称。我们选择不重用相同的批注名称的原因是为了避免与JAX-RS或其他EE规范冲突:
代码语言:javascript复制@POST
@Path("params/{p}")
public String params(@RestPath String p,
@RestQuery String q,
@RestHeader int h,
@RestForm String f,
@RestMatrix String m,
@RestCookie String c) {
return "params: p: " p ", q: " q ", h: " h ", f: " f ", m: " m ", c: " c;
}
更简单的参数和上下文注入
使用RESTEasy Reactive,您甚至不需要使用,@PathParam或者@RestPath您的参数与path参数具有相同的名称,并且类似地,您可以跳过@Context所有已知的上下文类型,这使它更加简单:
代码语言:javascript复制@POST
@Path("params/{p}")
public String params(String p, UriInfo info) {
return "params: p: " p ", info: " info;
}
新的最佳消息正文阅读器/编写器
如果在为端点提供服务时未调用任何筛选器和拦截器,则可以使用更高效的消息正文编写器,这些编写器直接写入vert.x,并且不需要反射和注释:
代码语言:javascript复制@Provider
public class ServerVertxBufferMessageBodyWriter extends VertxBufferMessageBodyWriter
implements ServerMessageBodyWriter{
@Override
public boolean isWriteable(Class type, ResteasyReactiveResourceInfo target, MediaType mediaType) {
return true;
}
@Override
public void writeResponse(Buffer buffer, ServerRequestContext context) {
context.serverResponse().end(buffer.getBytes());
}
}
默认内容类型
返回String的端点默认为产生文本/纯文本。我们计划对JSON和其他类型执行相同的操作。
CDI整合
通过JAX-RS的@Context进行的所有注入都委托给Arc。这为用户提供了Arc带给Quarkus所有其他部分的构建时间注入的好处。
每类异常映射器
在JAX-RS规范中,无法对特定的JAX-RS资源类以不同的方式处理异常-所有异常映射都是以全局方式完成的。但是在RESTEasy Reactive中,您可以简单地执行以下操作:
代码语言:javascript复制@Path("first")
public class FirstResource {
@GET
@Produces("text/plain")
public String throwsVariousExceptions(@RestQuery String name) {
if (name.startsWith("IllegalArgument")) {
throw new IllegalArgumentException();
} else if (name.startsWith("IllegalState")) {
throw new IllegalStateException("IllegalState");
} else if (name.startsWith("My")) {
throw new MyException();
}
throw new RuntimeException();
}
@ServerExceptionMapper({ IllegalStateException.class, IllegalArgumentException.class })
public Response handleIllegal() {
return Response.status(409).build();
}
@ServerExceptionMapper(MyException.class)
public Response handleMy(SimpleResourceInfo simplifiedResourceInfo, MyException myException,
ContainerRequestContext containerRequestContext, UriInfo uriInfo, HttpHeaders httpHeaders, Request request) {
return Response.status(410).entity(uriInfo.getPath() "->" simplifiedResourceInfo.getMethodName()).build();
}
}
为了自定义某些资源类的异常处理。还要注意,@ServerExceptionMapper可以像JAX-RS使用那样以全局方式处理异常ExceptionMapper。为此,只需使用注释不属于Resource类的方法@ServerExceptionMapper。
其他扩展程序也可以使用吗?
绝对!与现有quarkus-resteasy扩展集成的扩展也与quarkus-resteasy-active扩展集成。因此,您可以继续使用CDI,Security,Metrics,JSON,Qute,Bean Validation,OpenAPI, 并享受开箱即用和完善的开发经验。
该如何尝试?
该项目已降落在Quarkus主分支,所以,如果你渴望尝试一下,你就必须按照从源代码编译Quarkus这和使用遵循正确BOM和版本此。可用的RESTEasy Reactive扩展为:
- quarkus-resteasy-reactive
- quarkus-resteasy-reactive-jackson
- quarkus-resteasy-reactive-jsonb
- quarkus-resteasy-reactive-qute
些扩展等效于现有的quarkus-resteasy *扩展,因此只需在应用程序中从quarkus-resteasy-jackson切换到quarkus-resteasy-reactive-jackson,即可让您尝试通过Jackson集成进行RESTEasy Reactive。
此外,如果需要使用JAX-RS客户端,则可以使用quarkus-jaxrs-client扩展(这不是声明性的MicroProfile REST客户端,而是JAX-RS规范指定的程序化客户端)。
应该注意什么?
首先要注意的是,目前暂时将这组扩展视为实验性的。尽管该项目几乎通过了JAX-RS TCK的全部,但它只是第一个发行版,因此请记住,它可能比典型的经过战斗的库具有更多的错误,而某些新的API和SPI可能会损坏。尽管这是第一个发行版,但我们确实预想这项工作将在不久的将来成为Quarkus的默认REST层。
如新功能部分所述,默认情况下,请求是在事件循环线程上处理的。这样可以确保最大的吞吐量,但是也意味着不应在这些线程上执行任何阻塞工作。如果您使用Blocking IO(例如,通过使用Hibernate Panache访问数据库),请确保@Blocking在方法或类上使用注释。这将确保该请求将在工作线程上得到服务。不用说,我们也非常有兴趣听到您对此默认设置的反馈。
尚无文档。文档将在1.11正式版之前添加,并将逐步增强。该电子邮件应包含您入门所需的所有信息,但是如果您遇到任何麻烦,我们可以在任何常用渠道(Zulip聊天,邮件列表,GitHub问题,StackOverflow)上为您提供帮助。
缺少哪些JAX-RS功能?
我们决定专注于现代REST层上大多数用户的需求,而不是实现JAX-RS TCK所需的每个功能。因此,就这一点而言,RESTEasy Reactive中不提供XML支持,同时也不支持该规范的各种奥秘功能(例如javax.activation.DataSource,javax.annotation.ManagedBean,javax.ws.rs.core.StreamingOutput)。
此外,值得注意的是,第一个发行版将不包含基于新的JAX-RS客户端(具有专用扩展)的MicroProfile REST客户端的实现。这很可能在不久的将来改变。
下一步计划是什么?
尽管新的扩展将随常规的1.11版本一起提供,但我们正在考虑1.11.0.Alpha1发布一个版本,以使您尽可能容易地尝试新的扩展并提供早期反馈。我们非常期待听到您在Quarkus中使用RESTEasy Reactive的想法和经验,并计划充分利用它来进一步改进该项目。