Quarkus的RESTEasy Reactive集成已合并master

2023-11-18 13:31:42 浏览数 (3)

前言

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的想法和经验,并计划充分利用它来进一步改进该项目。

0 人点赞