在最近半个世纪里,计算机软件的作用发生了很大的变化。硬件性能的极大提高、计算机结构的巨大变化、存储容量的大幅度增加以及种类繁多的输入、输出方法都促使基于计算机的系统更加先进和复杂。Web应用属于计算机软件的子集,在此期间也在快速的发展中。从早期的企业黄页,到现在的各种移动端应用、云服务,都离不开Web技术的不断迭代升级。从架构层面上看,早期的应用大部分是C/S结构的,C/S结构系统大多分为两层,客户端实现用户展示和部分逻辑,服务端实现数据存储和部分逻辑。到了面向对象出现的时候,应用开始转向三层结构即表现层展示用户界面,领域层实现业务逻辑,数据层存取数据。这样的分层使不同层级的开发人员可以专注于各自部分的技术,通过服务接口调用彼此合作。上个世纪90年代Web的出现,应用结构开始从C/S结构转变成B/S结构,Web应用的兴起,也让Web技术得到了巨大的发展。Web技术的发展很多也是遵循着分层思想,分层使层与层之间实现了解耦和复用,慢慢的层级之间结构化越来越清晰,实现了层级的标准化。下面我们沿着Web的发展阶段,分析一下一些主要的Web技术。
Web早期阶段主要是通过浏览器向服务端请求静态HTML信息,最早用于科学家之间互相共享和传递信息,后来被人们用来宣传企业信息。这时候Web服务器上直接存储静态页面,浏览器通过HTTP协议请求服务器,服务器直接将静态页面返回给浏览器,流程如下:
随着技术的发展,CGI(Common Gateway Interface 通用网关接口)的出现使Web上可以展示动态信息。CGI定义了Web服务器与程序间通信的接口标准,使Web服务器可以通过CGI接口执行程序,完成动态请求的处理,最后拼接成HTML代码返回给Web服务器。这种模式,简单应用还可以应对,面对比较复杂的应用,可读性和可维护性是比较大的问题,而且CGI程序面对并发大的情况,性能也不好。
1994年,PHP语言诞生了,PHP可以把程序嵌入到HTML代码中去执行,不仅能更好的组织Web应用的内容,而且执行效率比外部程序更高。后来Apache Group成立了,并发布了Web服务器领域的元老Apache,因为其安全性、跨平台,成为当时Web服务器的最佳选择。PHP和Apache的组合由于开源、成本低、开发周期短等特点,成为了搭建动态网站首选。直到今天仍然有相当一部分Web应用使用他们的组合——LAMP(Linux Apache Mysql PHP)。
Apache作为一款Web服务器,提供了两种模式运行PHP应用,一种是mod_php模式,另外一种是mod_fastcgi模式。mod_php模式主要是通过Apache的PHP Module解析PHP程序,PHP执行完毕,整个HTML页面也就完成了;mod_fastcgi模式其实就是CGI模式,不过CGI已经被FastCGI取代了,CGI是处理一个请求,就会启动一个CGI进程,执行完毕会退出CGI进程,资源利用率不高,效率也比较低,而FastCGI不需要每次新启动,它会在请求到来之前,先启动起来,然后通过响应逻辑管理这些CGI进程,并且在请求执行完成后,不退出CGI进程,这样会快很多。
另一方面,1996年Java的第一个版本发布,作为一款面向对象的编程语言,Java语言可能更符合这个时代的业务场景,并且逐渐成为应用最多的开发语言。其实本质上看,编程语言就是工具,每一个工具都有各自的使用场景和使用方法。作为一名Java程序员,对于Java语言的特点,总结如下:
面向对象:开发应用就像用编程语言来描述“应用”所在的业务场景,面向对象和面向过程就是你描述这些场景的方法,当然,我们不可能会覆盖“应用”所处的所有场景。面向过程就是直接用编程语言就构建你所想到的业务场景的动作过程;而面向对象,首先要抽象出参与业务场景的各个元素(对象),然后,通过组合各个对象的动作,来模拟各个业务场景。显然,面向过程开发起来会更快、更直接,面向对象会更清晰、更健壮。从软件工程角度看的话,面向对象开发周期可能会更长,不过代码复用程度更好,应用扩展性也更好,更适合构建周期更长、结构更复杂的系统。
JDK(java development kit):JDK是Java语言的开发工具包,不仅提供Java的开发环境、编译环境,还包括丰富的类库。使Java开发更加简单和便捷。
JVM(Java Virtual Machine Java虚拟机):JVM是Java语言的运行环境,就像应用进程在计算机系统运行一样。JVM对于计算机来说就是一个应用程序,可以有不同系统的实现,这就使Java具有平台无关性,一次编译,到处运行。
JVM有一套自己的内存结构,包括一套字节码指令集、一组寄存器、用于存储的堆栈结构,当Java程序运行期间,通过JVM管理Java的运行时内存。JVM提供很多配置参数,根据具体Java应用程序的特点动态调优。
多线程:Java提供了丰富多线程工具和模型,使Java应用可以应对多线程环境下的开发工作。
面对企业应用的火爆发展,Sun公司发布了J2EE(后更名为JavaEE,现在叫Jakarta EE),J2EE是一套企业级应用的标准,包含了一系列构建应用的核心组件,像JDBC、JSP、Servlet、EJB等等。有了这些标准化组件的支持,使开发大型应用有了很大的支撑,JavaEE开始不断发展壮大,成为了企业级应用的解决方案。
下面让我们从J2EE角度出发,重新梳理一下这些核心技术:
Servlet是Java平台的CGI技术,Servlet接口定义了初始化、执行、销毁方法,Java程序通过实现Servlet接口,可以处理对应路径的请求,我们看到Servlet的service方法接收的是ServletRequest和ServletResponse,这两个参数就是Servlet的请求和响应对象。每当有一个HTTP请求到来,Web服务器(也叫容器)会为每个请求启动一个线程,将请求数据、响应数据封装成上面的两个对象去调用相应的Servlet的service方法,Servlet执行完成后,Web服务器再将ServletResponse解析之后,封装成HTTP的响应返回回去。
相比于CGI程序,Servlet应用程序使用Java虚拟机管理的Java线程来执行逻辑,比CGI创建进程的方式节省时间和资源。Servlet应用本身不能直接运行,需要部署在Web服务器中,如Tomcat。Tomcat可以实现HTTP协议与Servlet应用程序的通信;Tomcat维护着线程池,并会为每个请求分配一个线程;Tomcat控制着Servlet的生命周期,包括实例、初始化、调用和销毁等。
与Apache比较的话,Apache是Web服务器,可以处理静态资源。Tomcat也具有Web服务器处理静态资源的功能,不过它的优势在于运行Servlet应用程序。现在很多Web架构会部署Apache(正在被Nginx替代)专门负责处理静态资源,而动态请求由Apache转发给Tomcat处理。
JSP实际上本质还是Servlet技术,因为PHP可以实现在HTML代码中编码,使构建页面逻辑比较清晰,于是Java Servlet也实现了这一点,允许在HTML中嵌入Java代码,就产生了Jsp。而Jsp实际运行起来,会被Servlet容器给编译成Servlet代码执行的。
JavaBean是用于数据封装的一种组件,在开发Jsp应用时,将数据、处理逻辑、数据库访问对象或者其他逻辑代码通过使用JavaBean技术将Bean对象嵌入到Jsp页面中,将业务逻辑和显示逻辑分离开,简化Jsp页面逻辑,增强Jsp开发的可读性,实现功能的复用。定义JavaBean的类一般遵循一定的格式,需要有无参构造、属性私有化并提供属性的getter和setter方法等,JavaBean技术是一种面向对象思想的应用。
JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API。可以为多种关系型数据库提供统一访问。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。有了JDBC,向各种关系数据发送SQL语句就是一件很容易的事。同时,将Java语言和JDBC结合起来使程序员不必为不同的平台编写不同的应用程序,只须写一遍程序就可以让它在任何平台上运行。
XML(EXtensible Markup Language 可扩展标记语言)是一种类似于HTML的可扩展标记语言,它的标记都是自定义的,其设计宗旨是用来传输和存储数据的;HTML是用于描述网页文件的描述标记语言,HTML设计的核心是显示数据。
RMI(Remote Method Invocation 远程方法调用)是一种用于实现远程过程调用的应用程序编程接口,它能让Java程序去调用网络中另一台计算机的Java对象的方法,调用效果就像调用本机方法一样。利用Java对象的序列化,将对象数据转化成字节流,以便在网络中传输,利用远程调用协议调用远程的方法时,在反序列化将字节流转化成对象数据,进行方法调用。
SPI(Service Provider Interface)是一种将服务接口与服务实现分类已达到解耦、大大提升程序扩展性的机制,引入服务提供者就是引入SPI接口的实现者,通过本地的服务注册发现获取到具体的实现类,从而完成真正的服务调用关系。
JNDI(Java Naming and Directory Interface Java命名和目录接口)是一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI服务供应接口(SPI)的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。
JMS(Java Message Service Java消息服务)是一个Java平台中关于消息中间件的API,类似于JDBC与各个关系型数据库之间的关系,通过JMS实现消息的产生、发送、接收,从而进行异步通信。
JTA(Java Transaction API)允许应用程序执行分布式事务处理,支持多个计算机对于网络资源的访问和更新。JTA与JTS(Java Transaction Service)为J2EE平台提供了分布式事务服务。一个分布式事务包括一个事务管理器和多个网络资源。和JDBC事务比较的话,JDBC事务只支持单一的一个数据库连接;而JTA事务可以包括多个资源,JDBC连接,JMS、EJB等资源。
JPA(Java Persistence API Java持久层API)用于描述Java对象与关系表的映射关系,并将运行期的实体对象持久化到数据库中。JPA不是一个框架,是一种Java应用程序以统一方式访问持久层的API,是一种ORM的规范。而我们使用的Hibernate、MyBatis框架是JPA规范的实现。
EJB(Enterprise JavaBean)是构建企业级服务端应用组件的标准。设计目标与核心应用是部署分布式应用程序,简化企业应用的开发。EJB规范为企业级应用开发人员实现业务逻辑提供一整套标准方案,集成了数据持久化,分布式事务处理、基于JMS的事件驱动、基于JNDI的名字和空间管理、基于RMI的远程调用、应用服务器端的软件组件化部署、以及如何将EJB部署至EJB容器当中。
从J2EE诞生,EJB就一直被视为J2EE的核心,不过发展到今天,越来越多的人开始认识到,EJB制定了太多的规范,反而束缚了其应用构建的灵活性。在J2EE遭遇失败的场景中,我们发现这些应用原本不需要过分复杂的设计,历史的经验告诉我们最成功的标准都是从实践中发展出来的。
在整个J2EE的发展过程中,从很多方面都表明,J2EE都是一个伟大的成功,它成功的从没有标准到建立了标准,大大的提升了企业级软件的开放程度。后来各种“轻量级”容器的出现,也正是由于J2EE规范的指引。J2EE是企业级应用的一整套标准,不过现在这些开源的、轻量级的解决方案,可以更好地组织现在的企业应用,因为往往我们不需要整个J2EE。
未完待续……
1、《软件工程 实践者的研究方法》
2、《企业应用架构模式》
3、《Expert One-on-One J2EE Design and Development》
4、https://github.com/lifesinger/blog/issues/184
5、https://www.smashingmagazine.com/2019/01/web-standards-guide/
6、https://www.tianmaying.com/tutorial/web-history#0
7、https://www.jianshu.com/p/d095cbcbcf1b
8、https://blog.csdn.net/jojo52013145/article/details/5783677