3.1 Java应用的发展
3.1.1 Java EE架构
大多数企业级应用都是基于Java开发的。Java主要分为标准版的Java SE和企业版的Java EE。Java EE(新版本更名为Jakarta EE,为了方便读者理解,本文仍称Java EE)是使用Java开发企业应用程序的规范,它是一个独立于平台的标准,是在Java Community Process(JCP)的指导下开发的。
Java EE规范是一组基于Java SE构建的API。它为运行多线程、事务、安全和可扩展的企业应用程序提供了运行时环境。需要注意的是,与Java SE不同,Java EE主要是API的一组标准规范,实现这些API的运行时环境通常称为应用程序服务器,也就是我们常说的传统意义上的中间件。
Java EE中的对象大致有三类:POJO、JavaBean、EJB。
·POJO全称是Plain Ordinary Java Object/Pure Old Java Object,中文可以翻译成“普通Java类”。
·JavaBean是一种Java语言写成的可重用组件。写成JavaBean的类必须是具体、公共的,并且具有无参数的构造器。JavaBean通过提供符合一致性设计模式的公共方法将内部域暴露,我们称之为属性。JavaBean可分为两种:一种是有用户界面(User Interface,UI)的JavaBean,一种是没有用户界面、主要负责处理事务(如数据运算、访问数据库)的JavaBean。
·企业JavaBean(EJB)是一种Java EE组件,通常用于在企业应用程序中封装业务逻辑。EJB与JavaBean不同,开发人员必须明确地实现多线程、并发、事务和安全等概念,应用程序服务器在运行时提供了这些功能,使开发人员可以专注于编写应用程序的业务逻辑。EJB分为两类:Session Bean(又分为有状态和无状态两种)和MessageDriven Bean。
那么,相比于Java SE,使用Java EE给企业应用带来的好处是什么呢?主要有以下几点。
·可以实现跨符合Java EE标准的应用程序服务器间的迁移。
·Java EE规范提供了大量通常由企业应用程序使用的API,例如Web服务、异步消息传递、事务、数据库连接、线程池、批处理实用程序和安全性。开发人员必要手动开发这些组件,从而缩短开发时间。
·针对特定领域(如金融、保险、电信和其他行业)的大量第三方即用型应用程序和组件已通过认证,可以运行并与Java EE应用程序服务器集成。
·大量先进的工具,如IDE、监控系统、企业应用程序集成(EAI)框架和性能测量工具可用于第三方供应商的Java EE应用程序。
Java EE包含对多个配置文件或API子集的支持。Java EE规范定义了两个配置文件:Full Profile和Web Profile。后来基于Java EE的微服务架构又提出了MicroProfile,所以Java EE的配置文件现在有三个。Java EE Web Profile专为Web应用程序开发而设计,并支持与Java EE相关的基于Web技术定义的API的一部分,Java EE的Web Profile和Full Profile的对比如图3-1所示。
Spring是Java开发的开源框架,于2003年6月首次发布。Spring主要作为Enterprise JavaBean 1.0和2.0的替代品。Enterprise JavaBean中存在很多问题,而Spring是出于对EJB的改进而创建的。Spring架构如图3-2所示。
Spring Boot可看作是Spring框架的扩展,它消除了设置Spring应用程序所需的XML配置,为更快、更高效的开发生态系统铺平了道路。
Spring Boot主要特征如下。
·可创建独立的Spring应用。
·嵌入式Tomcat、Jetty、Undertow容器。
·提供starters简化构建配置。
·尽可能自动配置Spring应用。
·提供生产指标,例如指标、健壮检查和外部化配置。
·完全没有代码生成和XML配置要求。
图3-1 Java EE 8 Profile
图3-2 Spring架构
在介绍了Java EE和Spring Boot后,接下来我们介绍Java应用的打包。
3.1.2 Java应用的打包与JDK
Java SE应用程序的首选方法是将应用程序打包为Java Archive(JAR)文件。JAR文件可以通过添加清单条目(与JAR文件内部的Java类一起打包的纯文本文件)来指定主要可运行类,从而使其可执行。
Java EE应用程序由多个组件组成,这些组件依赖于运行时所需的大量JAR文件。Java EE应用程序部署在与Java EE兼容的应用程序服务器上,这些部署可以有不同的类型。
·JAR文件:应用程序的各个模块和Enterprise JavaBean(EJB)可以作为单独的JAR文件进行部署。第三方库和框架也可以打包为JAR文件。如果你的应用程序依赖于这些库,则库JAR文件应该部署在应用程序服务器上。JAR文件具有.jar扩展名。
·Web归档(WAR)文件:如果你的Java EE应用程序具有基于Web的前端或提供RESTful服务端点,与Web前端和服务相关的代码和资产可以打包为WAR文件。WAR文件具有.war扩展名,实质上是一个包含代码、静态HTML、图像、CSS和JS资产、XML部署描述符文件以及打包在其中的相关JAR文件的压缩文件。
·FatJar文件:FarJar又称作uber-Jar,是包含所有依赖的Jar包。Jar包中嵌入了除Java虚拟机以外的所有依赖。FatJar包可以直接通过java-jar运行。
在第2章中,我们介绍过应用的编译分为本机编译和解释编译。Java就是典型的解释型语言,而JVM是Java语言的解释器。JRE提供JVM以及Java程序运行所需的库。JDK是Java程序的开发环境,除了提供JRE之外,还包括编译器、调试器等。三者的关系如图3-3所示。
图3-3 JVM、JRE、JDK的关系示意图
JDK主要分为OpenJDK、Oracle JDK、IBM JDK三种。Ora-cle JDK就是传统的Sun JDK的延续,大多数Java程序都用Oracle JDK。OpenJDK是2006年由Sun公司开源的,随着Sun公司被Oracle公司收购,OpenJDK作为开源的JDK,受到业内的重视。OpenJDK的主要维护者是Red Hat。IBM也开发了自己的JDK,用于其特殊的硬件和操作系统中,比如Java for AS400等。
目前在开源界,我们使用最多的是OpenJDK,这也是云原生界主要采用的JDK。本书后续的内容均基于OpenJDK进行阐述。
Java EE环境,包括EJB容器和Web容器。
·Web容器:只运行Web应用的容器,例如Tomcat就是开源的Web容器,它可以运行JSP、Servlet等。这也是我们常说的Web Server。Tomcat是用Java语言开发的Web服务器,因为运行Java应用需要JVM,所以安装Tomcat之前要部署好JDK。
·EJB容器:运行在EJB组件的容器,提供EJB组件的状态管理、事务管理、线程管理、远程数据资源访问、连接管理和安全性管理等系统级服务。JBoss EAP同时提供EJB容器和Web容器,这也是我们常说的App Server。有的App Server本身就包含JDK,例如Weblogic,所以不必提前安装JDK。但是,App Server的运行是需要JDK的。
Spring Boot类应用主要是Web类应用,因此应用在打包的时候,既可以打成传统的WAR包,也可以打成FatJar包。将Java应用打成WAR还是Jar包,取决于pom.xml的maven-plugin,以及我们执行maven打包命令时调用的pom.xml中的plugin。
我们以在《OpenShift在企业中的实践:PaaS DevOps微服务》使用过的名为customer的微服务的代码为例,查看其pom.xml文件(https://github.com/ocp-msa-devops/istiotutorial/blob/master/customer/java/springboot/pom.xml)。
maven-plugin为spring-boot-maven-plugin,因此应用构建完打包成Jar包,如下所示:
<plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins>
接下来,我们再查看pom.xml中对Web依赖的引用,引用了spring-boot-starter-web,如下所示:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
spring-boot-starter-web默认把嵌入式Tomcat作为Web容器来对外提供HTTP服务,默认使用8080端口对外监听和提供服务。也就是说,我们据此打成的Jar包将会包含内嵌的Tomcat,直接可以通过Java-jar运行,而无须依赖外置的Tomcat。如果运行在OpenShift,也就不需要使用Tomcat的容器镜像,使用OpenJDK的容器镜像即可。在Spring Boot应用打包时,如果我们想使用其他的嵌入式Web Container,则可以引入类似spring-boot-starter-jetty或spring-boot-starter-undertow的依赖,替换掉默认的嵌入式Tomcat。
编译customer微服务。
# cd customer/java/springboot/ # mvn package [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 07:27 min [INFO] Finished at: 2019-04-28T09:34:49-07:00 [INFO] ------------------------------------------------------------------------
编译成功后,生成customer.jar包:
# ls -al target/customer.jar -rw-r--r--. 1 root root 23011020 Apr 28 09:34 target/customer.jar
运行customer.jar文件:
# java -jar customer.jar
运行结果如图3-4所示,已经成功启动。
图3-4 应用启动成功
在Web类应用中,基于Spring Boot开发的应用默认会打成FatJar的包,可以在OpenJDK环境中独立运行。基于Java EE开发的应用主要打成War包,运行在Tomcat的容器中。
我们查看Red Hat发布的基于OpenShift的Tomcat的企业级容器镜像,即JBoss Web Server,如图3-5所示。
图3-5 OpenShift提供的Tomcat容器镜像
查看JBoss Web Server 3.1-Tomcat8容器镜像所包含的软件包,包含OpenJDK和Tomcat的软件包,如图3-6、图3-7所示。
图3-6 查看容器镜像中包含的OpenJDK包
图3-7 查看容器镜像中包含的Tomcat包
接下来,我们查看Red Hat OpenShift提供的OpenJDK容器镜像包含的软件包Open-JDK 11,如图3-8所示。
图3-8 OpenShift提供的OpenJDK容器镜像包
我们查看OpenJDK 11镜像中包含的文件,OpenJDK没有Tomcat,如图3-9和图3-10所示。
图3-9 查看OpenJDK 11包含的软件包
图3-10 查看OpenJDK 11包含的软件包
在介绍了Java应用的发展后,接下来我们分析Kubernetes时代Java应用面临的问题。