Jakarta EE 10版本中的7大功能

2,397 阅读6分钟

Jakarta EE 10版本中的7大功能

详细了解Jakarta EE 10版本中增加的前7个功能

Java EE是Java中所有企业开发的主导力量。最近,它被更名为Jakarta EE,从JCP过渡到Eclipse Foundation。

这一转变为开放管理、开放兼容测试(早期的技术兼容工具包-TCK是闭源的),当然还有开源的大门。这意味着没有特定的厂商比其他厂商有更大的影响力;现在是更加分散的。

Jakarta EE是Java生态系统的一个组成部分。25-35%的java应用运行在JakartaEE应用服务器上。WildFly、JBoss EAP、Payara、WebSphere/Liberty、WebLogic等,都是应用服务器的一些例子。这些应用服务器是由不同的供应商开发和维护的。然而,作为一种技术,Jakarta EE仍然是供应商中立的,这意味着同样的应用程序代码应该在任何应用服务器中运行,因为所有供应商都遵守Jakarta EE的规范

70-80%的java应用以这种或那种方式使用Jakarta EE的API。例如Tomcat, Hibernate, ActiveMQ, Jetty, CXF, Jersey, RESTEasy, Quarkus, Microprofile, Spring。如果我们再深入一点,就会发现Java应用背后的Jakarta EE APIs。

Jakarta EE是一个生动的生态系统。我们有Jakarta EE 9,Jakarta EE 9,MicroProfile,和Helidon。在Micronaut和Helidon之后推出的Quarkus,仍然是一个受欢迎的框架。许多应用程序还没有迁移;这就是为什么Java EE 8仍然存在。然而,Jakarta EE 9也许被认为是创新的基础,以推动即将发布的Jakarta EE 10的新功能。

Jakarta EE 9将所有相关的规范javax 到Jakarta命名空间。不幸的是,这导致了一些破坏性的变化,但迁移看起来相当容易。有一些工具可以做到这一点。它还删除了旧的废弃技术,并将Java 8移至Java 11。

在进入Jakarta EE 10的许多特性中,我将讨论最重要的7个特性。

1.@ManagedExecutorDefinition

在Jakarta Concurrency API中最常用的服务之一是ManagedExecutorService。它被用来在Jakarta EE环境中创建一个线程池,以一种更易于管理的方式产生线程。尽管它与ExecutorService基本相同,但我们在Java SE环境中使用它。

为了配置线程池,我们有一个供应商特定的设置。现在只需用注解就可以定义它。这是配置线程池的一种更标准的方式。

package ca.bazlur;

import static jakarta.enterprise.concurrent.ContextServiceDefinition.APPLICATION;
import static jakarta.enterprise.concurrent.ContextServiceDefinition.SECURITY;

import jakarta.annotation.Resource;
import jakarta.ejb.Asynchronous;

import jakarta.enterprise.concurrent.ContextServiceDefinition;
import jakarta.enterprise.concurrent.ManagedExecutorDefinition;
import jakarta.enterprise.concurrent.ManagedExecutorService;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Named;
import java.time.Duration;
import java.time.LocalDate;
import java.util.concurrent.CompletableFuture;

@Named
@ApplicationScoped
@ManagedExecutorDefinition(
    name = "java:module/concurrent/MyExecutor",
    context = "java:module/concurrent/MyExecutorContext",
    hungTaskThreshold = 120000,
    maxAsync = 5)
@ContextServiceDefinition(
    name = "java:module/concurrent/MyExecutorContext",
    propagated = {SECURITY, APPLICATION})
public class WorkService {
  
  @Resource(name = "java:app/concurrent/MyExecutorService")
  private ManagedExecutorService executor;

  @Asynchronous
  public CompletableFuture<Long> hoursWorked(LocalDate from, LocalDate to) {

    return CompletableFuture.supplyAsync(() -> heavyAPICall(from, to), executor);
  }

  private static long heavyAPICall(LocalDate from, LocalDate to) {

    return Duration.between(from, to).toMillis();
  }
}

2.@Asynchronous

在EJB中也有一个类似的注解。用这个注解的方法应该是异步运行的。然而不幸的是,EJB的注释有点过时了。

另外,在EJB中,我们不能指定线程池。它曾经使用应用服务器的默认线程池。现在的新注解是jakarta.enterprise.concurrent.Asynchronous

伴随着Jakarta EE Concurrency 3.0而来,它不需要使用EJB,我们可以指定线程池。它可以与任何CDI bean一起使用。每个异步方法的执行都对应于一个托管的java.util.concurrent.CompletableFuture 实例,该实例由jakarta.enterprise.concurrent.ManagedExecutorService 作为其默认的异步执行设施。

package ca.bazlur;

import jakarta.enterprise.concurrent.Asynchronous;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Named;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;

@Named
@ApplicationScoped
public class PaymentService {

  @Asynchronous(executor = "java:app/concurrent/MyExecutorService")
  public CompletableFuture<Confirmation> processPayment(final Order order) {
    try {
      var status = processOrder(order);
      return CompletableFuture.completedFuture(status);
    } catch (PaymentException ex) {
      throw new CompletionException(ex);
    }
  }

  private Confirmation processOrder(Order order) {
    return new Confirmation();
  }
}

class PaymentException extends RuntimeException {}
record Confirmation() {}
record Order() {}

3.Bootstrap API。

如果你在Jakarta EE环境之外调用一个休息服务,例如单元测试、集成测试等,有一个独立的API来做这件事是很好的。有了这个,你就不需要运行整个容器了。因此,它变得非常方便。

4.多部分/表单数据

Jakarta RESTful Web Service是开发者中流行的暴露restful端点的功能之一。然而,它并没有以一种标准的方式合理地支持多部分表单数据。这就是为什么多年来,开发人员需要Servlets或供应商特定的REST API来处理多部分媒体类型。有了Jakarta REST 3.1,我们不再需要处理这样的问题,它增加了对多部分表单数据的全面支持,这是标准的。

package ca.bazlur;

import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.EntityPart;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.io.InputStream;

@Path("/job")
public class FileResource {

  @Path("/apply")
  @POST
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  public Response applyForJob(
      @FormParam("name") String name, @FormParam("recentPhoto") EntityPart photo,
      @FormParam("resume") EntityPart resume) {
    processApplication(name,
        photo.getMediaType(), photo.getContent(), resume.getMediaType(), resume.getContent());

    return Response.ok("Application received").build();
  }

  private void processApplication(String name, MediaType mediaType, InputStream content,
      MediaType mediaType1, InputStream content1) {
  }
}

5.@OpenIdAuthenticationDefinition

好吧,多年来,我们一直在使用用户名和密码来验证Web应用程序中的用户。然而,在现代应用中,使用其他服务来登录已经变得很普遍,例如Facebook、Google、Twitter等。OpenID Connect协议为这种认证提供了动力。有了Jakarta Security 3.0,我们现在有了一种标准的方式来遵守OpenID Connect,只需使用一个注释,即@OpenIdAuthenticationDefinition。现在的生活简单多了;指定所需的属性,如提供者URI、clientId、clientSecret、重定向URI等。

Java

@OpenIdAuthenticationDefinition(
       providerURI = "https://sample-openid-server.com",
       clientId = "87068hgfg5675htfv6mrucov57bknst.apps.sample.com",
       clientSecret = "{my-secret}",
       redirectURI = "${baseURL}/callback",
       extraParameters = {
            "testKey=testValue", 
            "testKey2=testValue2"
       }
)

public class SecurityConfig {
}

6.UUID密钥

Jakarta Persistence 3.1带来的java.util.UUID 是作为一个基本类型的字段,这对云环境的实体ID非常方便,因为许多数据库不会自动生成UUID。

爪哇

package ca.bazlur;


import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.util.UUID;

@Entity
public class User {

  @Id
  @GeneratedValue(strategy = GenerationType.UUID)
  private UUID id;

  private String username;
  private String password;
}

此外,它还为查询语言和Criteria API带来了几个功能。这些新的功能分为三类:

  • 数字函数(CEILING, EXP, FLOOR, LN, POWER, ROUND, SIGN)
  • 使用Java.time类型返回当前本地日期和时间的函数(LOCAL DATE, LOCAL DATETIME, LOCAL TIME)。
  • EXTRACT函数从一个给定的日期中提取数字部分(YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND)。

7.使用纯Java的Jakarta Faces视图

Jakarta Faces 4.0带来了一个新的API,可以只用Java代码定义完整的视图(HTML页面)。因此,如果你对编写任何类型的标记语言特别不感兴趣,你现在可以用纯Java面孔视图完全用Java编写你的UI代码。我喜欢它。

现在介绍一下Jakarta EE的大使们。我们是一个独立的草根团体,致力于通过积极的社区参与和宣传来推动Jakarta EE的发展。如果你想加入并做出贡献,请在这里了解更多:https://jakartaee-ambassadors.io/。整个Jakarta 10平台的最终发布将在下个月晚些时候。在这里了解更多。Jakarta EE 10的发布计划
最后,如果你想了解更多关于Jakarta EE的情况,请观看Reza Rahman的这个会议

今天的内容就到这里了。