一文读懂Spring和Java EE 本质区别?各自有哪些优缺点?

本文详细介绍了Spring和Java EE之间的本质区别、各自的优缺点,以及Spring Boot如何简化开发。Java EE曾因其复杂性和分布式架构而流行,但Spring的出现简化了企业应用开发,提供了IOC容器和AOP。Spring Boot进一步降低了Spring的使用门槛,通过Starter简化技术框架,提供了默认配置和热部署功能,改变了应用系统组织方式。然而,Spring Boot的快速迭代可能导致版本不兼容,且打包文件庞大,集成的第三方技术版本可能落后。
摘要由CSDN通过智能技术生成

1 Java EE

1.1 Java EE

我 1999年接触JSP,从2001年开始正式接触Java EE技术,当时面对JavaEE那么多组件和规范(比如,EJB技术),确实有点蒙圈。编写一个企业应用居然用到了那么多技术,曾经的电信项目,启动需要10分钟,每次发布都需要一个小时。作为新手的我是不能理解的,这也是当时大多数程序员的心态。然而Java EE ,针对复杂企业系统所指定的规范和实现,能满足复杂企业应用需求,这也是为什么JavaEE 很快就流行起来,并在电信,银行等领域广泛使用的原因。2003年Spring 横空出世,它告诉所有人,编写企业应用、Web应用,并非需要全部的JavaEE技术,也不需要有像EJB那样复杂的使用方式和部署方式。使用Spring开发和部署网站和企业应用变得很便捷。同时Spring建立在Java EE基础上,也同样可以使用Java EE的的功能。基于技术的创新和兼容传统Java EE技术,使得Spring框架很快流行起来,普遍应用在传统企业应用和互联网应用中。

看到现在JS前端技术的混乱,群雄并起,我觉得当时使用JavaEE还是很幸福的 。无疑,有一个统一的技术规范或者技术框架,是程序员的福音,也是企业的福音。

JavaEE 现在已经更名为 Jakarta EE。本书仍然以Java EE指代 Jakarta EE。

1.1.1 Java EE 架构

要应用Spring Boot技术,不一定需要先从Spring技术开始(这也是Spring Boot的初衷),更不需要了解Java EE。然而,稍微了解JavaEE和Spring技术,对掌握Spring Boot会有个更深的理解。

从根本上来说,Java EE 是一种企业应用的软件架构。在了解它之前,我们先来看看它的发展背景。它的发展背景中总是与分布式应用和互联网应用密切相关。

JavaEE与Web:互联网从根本上改变对企业软件的系统需求,软件需要处理来自互联网的大量请求,并要及时作出响应。可以说没有Web,就没有JavaEE。

JavaEE与分布式应用:20世纪80年代,个人计算机性能逐渐达到了高端工作站和服务器的水准,使分布式计算应用迅速普及。SUN公司在推出Java后,紧接着推出了远程方法调用RMI,并在90年代末期,以RMI为通信基础构建了JavaEE。在相当长的一段时间,JavaEE就是一种分布式应用,这让JavaEE战胜了CORBA和.COM+。但是也带来了巨大的系统交互开销(超出一个数量级的),毕竟不是所有的企业应用和互联网应用都是分布式的,这让一些人认为JavaEE架构有问题。然而这并不是JavaEE的错,在市场上,JavaEE需要迎合当时的分布式技术潮流。现在如果你不用分布式, JavaEE也同样提供了相关技术供你使用,如Local EJB。

作为企业应用或者互联网应用的架构,总有如下功能需求,JavaEE也都有相应的规范实现与之对应。

  • Web支持,企业应用、互联网应用越来越多地基于B/S结构。JavaEE的Servlet规范,规定了Web容器,Serlvet组件还设有JSP&JSTL。

  • 事务支持,提供事务管理器支持管理事务,如单一数据库,多个数据库,数据库和其他资源的事务协作等,JavaEE里提供了JTA、API和JTS 事务服务规范。事务支持也实现了分布式事务管理,管理多个数据库或者支持事务的资源。

  • 消息服务,企业各个系统,系统模块之间通过消息服务。JavaEE提供了JMS协议,用于与消息中间件交互。

  • 数据库持久层,JavaEE先有EJB规范,后来由又提出了更有实际操作性的JPA,这都是企业访问数据库常用的方法。

  • Container,提供了Web Container和EJB Container,提供了关键的Servlet组件和EJB组件,并提供组件需要的服务,比如JTS。

还有如下其他技术。

  • JWS,也是分布式系统交互的一种方式,通过WebService。

  • JAX-RS,通过REST交互。

  • JNDI ,查找服务和对象的接口,如查找一个配置好的数据源。

  • JAXP/JAXB,在XML流行时代,解析XML,映射到JavaBean的XML工具。

  • JAX-RPC, 分布式系统交互的一种方式,通过RPC方式调用。

  • JACC,安全认证。

  • Java EE Application Server,提供了如上所有服务的应用服务器,我们常用的Tomcat、Resin只能算是Java EE Web服务器,提供了部分服务。开源的JBoss,商业的Weblogic等称为应用服务器,实现了JavaEE规范定义的所有功能。

综上所述,Java EE 提供了企业应用技术的实现规范,简化了企业应用和Web开发,如图1-1所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-10Qle9M1-1581054513639)(/api/storage/getbykey/original?key=1911d1410170e4fea8dd)]

图1-1

1.1.2 Java EE 缺点

Java EE规范总结了企业应用,结束了WEB开发的技术无序状态,让程序员、架构师用同一种思维去思考如何架构和开发应用(想想前端架构现在的无序性,开发后端程序员有多幸福啊)。然而Java EE有其局限性。

  • 过于复杂,Java EE针对的是复杂的分布式企业应用,然而现实情况是大部分应用都比较简单。复杂的架构带来复杂的开发方式和部署方式。早期Java EE的普通系统打包部署都需要数十分钟。

  • 追求分布式,大部分应用都并非JavaEE假定的分布式系统,像EJB、JMS、JWS等技术实现门槛高,也容易出错。Spring 曾经反对过这种分布式架构,并只提供了容器管理,并因此获得了巨大成功。大型应用分布式不可避免,Spring提供了其他的技术简单支持,比如支持RESTFul架构。

  • JavaEE标准指定和实现有一个复杂的过程,不能及时与流行开源结合。比如关于消息处理,除了有标准的JMS支持外,现在还有性能更好的Rabbit MQ,以及Kaffka。Java EE并没有与之相应的标准。反而是Spring有统一的实现消息处理模式,无论你用的是JMS,还是Rabbit MQ,或者是性能更好的Kaffka,都能快速上手。

  • Java EE 应用服务器通常是商业公司提供,价格不菲,鲜有公司采用。应用服务器管理和部署应用,对初学者和自学者有一定门槛。现在很容易招聘到熟悉Tomcat使用的开发人员,很难招聘到懂Weblogic使用的人员。

1.2 Spring

Spring 是为了解决应用复杂性而生的框架,它吸取了Java EE 容器管理优点,提供了一个IOC容器来管理Bean和通过AOP方式增强Bean功能。不同的是它并没像Java EE那样详细规定容器提供的何种服务和容器里运行的具体组件类型。Spring只是提供了两种机制,控制反转(IoC)和面向切面(AOP)来提供任意的服务和增强Bean任意特性,使得的Spring本身简单易掌握,又可以通过Bean管理来无限扩展功能。

Spring 也没有像JavaEE标准制定那样有负责的流程和涉及大的厂商的利益,Spring发展来自于社区驱动。

1.2.1 Spring IOC容器和AOP

Spring架构同Java EE 一样,包含了企业应用需要的各种技术,这也是本书的主要内容。Spring 本身提供了两个最核心的技术,就是IOC 容器和AOP增强。图1-2所示是介绍Spring的一个经典图,我们沿用这个图来说明Spring。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6sVYYt4q-1581054513640)(/api/storage/getbykey/original?key=1911b373354ffdc0a19e)]

图1-2 Spring介绍

IOC Core Coanainer,Spring 容器,负责管理你的任意对象,会结合你对对象的描述进行初始化和加强。比如,对于一个用注解@Controller 申明的对象,Spring会认为这个对象是个Web Controller,这个对象里的方法如果有@RequestMapping 注解,则会将客户端发起的htttp请求映射成java方法调用,代码如下:

@Controller
public class HelloworldController {
	@RequestMapping("/sayhello.html")
	public @ResponseBody String say(String userName){
		return "hello "+userName;
	}
}

如上例子,Spring 容器初始化HelloworldController实例后,响应客户端发起的/sayhello.html请求,执行say方法,并自动将请求参数按照say方法申明的名称一一对应上。

Spring 通常提供一些@Controller 、@Service、 @Component 、@Configuration 注解,只有拥有这些注解的类才会引起Spring 容器的注意,并根据注解含义增强对象。

Spring 可以管理和增强任意对象,如常见的@Service注解对象,通常用来处理业务逻辑,Spring 容器往往会增强这类对象的事务控制能力。

容器管理还可以为被管理的Bean提供其他被管理和被增强的Bean。如一个已经被@Service 注解的UserService 类,在 HelloworldController类里,使用@Autowired 自动注入这个实例。

@Controller
public class HelloworldController {
	@Autowired UserService userService;
 
	@RequestMapping("/sayhello.html")
	public @ResponseBody String say(String userName){
		return "hello "+userService.query(userName).getDepartment().getName();
	}

}

AOP,上面提到的对象增强,离不开AOP技术,AOP(Aspect Oriented Programming)只面向切面编程。它是通过编译方式或者运行时刻,对目标对象动态添加功能,如图1-3所示,Spring容器有能力对Service类进行增强,当调用Service方法的时候,会先调用AOP的实现。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ap1sJVyr-1581054513641)(/api/storage/getbykey/original?key=19111caa1092e9c3dc5d)]

图1-3

AOP分离了企业应用的业务逻辑和系统级服务,比如事物服务、缓存服务、应用系统的审计、安全访问等. 关于AOP详细介绍,我们将在第11章详细说明。

1.2.2 Spring 缺点

随着Spring功能越来越强,在使用Spring的时候,门槛也变得越来越高。诸如搭建一个简单的基于Spring的Web程序,并不简单,需要各种配置。Spring过时的一些技术也经常无意中被引用到最新项目。新手面对同一种需求,比如处理事物是用XML配置好,还是通过注解@Tranactional好,这时会出现选择困难,这是因为Spring 通过多年发展,本身已经变得臃肿,过时的使用方式没有被淘汰,这样就会给初学者带来混乱。同时Spring也集成来越来越多第三方技术,如何方便地使用这些第三方技术,解决版本之间冲突,都需要时间。尽管Spring很强大,但它也在犯Java EE的错误,存在如下缺点。

  • 使用门槛升高,要入门Spring 需要较长时间。

  • 过时技术兼容,导致使用复杂度升高。

  • XML 配置已经不是流行的配置系统方式。

  • 集成第三方工具时候,程序员第三方工具还要考虑相互兼容性。

  • 系统启动慢,不具备热部署功能,完全依赖虚拟机或者web服务器的热部署。

  • 大型系统都朝着系统拆分小系统或者微服务架构演讲,Spring框架不具备这个能力。

庆幸的是,Spring的开发者们及时认识到这个问题,推出了基于Spring技术的Spring Boot,解决了Spring的如上问题,尤其是上手难,技术使用不统一这个个问题。经过快速发展,Spring也逐渐被开发人员喜爱,成为搭建系开发框架非常好的选择。正如本书一直强调的,Spring Boot能极速开发Web系统,也能容易的架构大的分布式系统。

1.2.3 Spring和Java EE 本质区别

Spring和Java EE 都很强大,从前面对JavaEE的和Spring的介绍来看,两者有两个本质区别。

  • Spring 没有像Java EE那样规定容器和服务规范,因此能提供无限扩展的服务,这是Spring最成功的地方。

  • Spring 功能来自于社区,JavaEE 功能来自大公司组织的技术委员会。Spring有着相当的灵活性,能广泛接纳社区的建议和功能。

想知道大公司的技术专家们在对JavaEE做什么,可以访问https://jcp.org/en/home/index。

1.3 Spring Boot

Spring Boot 简化了Spring应用开发,不需要配置就能运行Spring应用。Spring Boot管理Spring容器、第三方插件,并提供很多默认的系统级服务。大部分Spring应用,无论是简单的Web系统,还是复杂的系统构建,都只需要少量配置和代码就能完成,这有点像每个公司的基于Spring框架做的公司开发框架,不同的是,Spring Boot更完善,更强大。

1.3.1 功能完备的技术框架

在上一节里描述了Spring的缺点,因此国内使用Spring的公司,都曾经有一个自有基于Spring的技术框架:基于Spring集成多种技术工具。 笔者所在公司就有一套这样的技术框架和使用方法。而在之前的公司也有一套类似的Spring技术框架和使用规范,一千个公司,便有一千个Spring技术框架。Spring Boot结束了这种较为混乱的使用Spring的方式,提供了一个统一的技术框架,也选择了多种流行开源技术作为框架的一部分。可以说,公司使用了Spring Boot技术框架,那技术选型和架构就变得更为简单和统一。

1.3.2 使得开发再次简单

我们知道,Spring使得Java EE开发变得简单,Spring Boot 使得 Spring开发更为简单。Spring Boot通过Starter来提供系统级服务,Spring Boot已经提供了一系列Starter。比如需要开发一个Web应用,要在pom.xml申明一下即可,代码如下:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

如果你的应用用到了Redis,则使用 spring-boot-starter-data-redis,Spring Boot会自动为你配置Redis需要的各种配置以及Redis的jar包、依赖包、合适的版本,如下是Spring Boot提供的常用Starter(TODO)。

名称作用
spring-boot-starter-webWeb开发支持,默认使用Tomcat8
spring-boot-starter-aopAOP开发支持,使用AspectJ
spring-boot-starter-jdbcSpring JDBC
spring-boot-starter-data-jpaJPA方式访问数据库,使用Hibernate作为JPA实现
spring-boot-starter-data-elasticsearch集成Elastic Search,默认访问localhost:9200
spring-boot-starter-data-redis集成Redis,使用 Lettuce.,默认连接localhost:6379
spring-boot-starter-cache缓存,支持多种缓存方式,如Local的,如Redis,Ehcache等
spring-boot-devtools应用程序快速重启的工具,提升开发体验
spring-boot-starter-data-mongodb集成mongodb,默认访问 mongodb://localhost/test
spring-boot-starter-data-neo4j集成neo4j,默认访问 localhost:7474
spring-boot-starter-data-gemfire集成分布式缓存
spring-boot-starter-data-solr基于apache lucene的搜索平台,默认访问http://localhost:8983/solr
spring-boot-starter-data-cassandra集成cassandra,默认访问 localhost:7474
spring-boot-starter-data-ldap集成ldap
spring-boot-starter-activemq消息集成ActiveMQ 支持
spring-boot-starter-amqp消息集成,AMQP协议支持,如支持RabbitMQ
spring-boot-starter-jta-atomikos分布式事务支持,使用atomikos
spring-boot-starter-jta-bitronix一个开源得分布式事务支持
spring-boot-starter-test包含Junit,Spring Test,Hamcrest,Mockito,JsonPath等测试工具
spring-boot-starter-webserviceswebservice 支持
spring-boot-starter-websocketwebsocket 支持
spring-boot-starter-jerseyRest 应用和 Jersey 支持
spring-boot-starter-freemarkerFremaker支持

Spring Boot 能让开发更简单,而且在维护、监控上也变得简单。我会在本书的后面章节详细说明。

1.3.3 改变了应用系统组织方式

传统的企业应用或者互联网系统,在构建系统的时候,所有功能推挤到一起,体积过于庞大,庞大的单体系统会有如下大家心知肚明的问题。

  • Spring 需要在启动时增强的类太多,导致启动慢。其他技术组件也会在启动的时候做一些处理,比如JPA或者MyBatis。Spring工程里的类越多,启动越慢。

  • 逻辑复杂、模块耦合、
    持日志消息参数化而方技术,如何方便的很好,但他资源的事务协作等代码臃肿,导致维护困难。虽有有各种架构和设计技巧能解耦,但单体应用会习惯性地成为一个大杂烩系统。

  • 任何一个错误都会导致整个系统不可用,隔离性不足。比如一个计算上传附件中word文档页数的程序会占用CPU较多,那么系统会因为用户上传一个较大文档导致整个系统不可用。

  • 可伸缩性差,如上的页数计算是必须完成的功能,那么你不得不部署多个这样庞大的单体系统保证可用性。最好的解决方法更应该是将这种统计功能作为一个子系统单独划分出来并部署多个以提高此功能伸缩性。

  • 部署和运维这样的庞大系统也是个麻烦事情,比如,我以前的一个系统,配置了最大8 GB的内存,内存溢出的时候,你不得不分析超大的Heap文件,效率很低。

Spring Boot 适合创建小微系统,也适合创建微服务系统,例如Spring Boot加上Spring Cloud 技术构建微服务系统,Spring Boot 负责构建微服务和小微系统,Spring Cloud负责管理微服务和小微系统。

1.3.4 Spring Boot 的不足

现在谈Spring Boot 不足还为时过早,我尝试总结一下我认为的Spring Boot 不足之处。

  • Spring Boot 目前仍然高速发展,版本迭代过程中经常出现不兼容低版本情况,甚至有些模块变化很多,从2.0版本到2.2版,也有很多不兼容。比如,2.0的Jetty默认配置允许Post任意大小的HTTP消息,而2.2版的默认配置则改成200000B ,再比如Redis访问默认实现从Jedis改成Lettuce。

  • Spring Boot 打包文件比较庞大。即使一个简单的Web应用,也有17MB。这个包包含了内置的Tomcat,还有MVC用到的Spring Boot、SpringFramework、Spring MVC库以及所有第三方库,如Log、Jackson、hibernate-validator等。

  • Spring Boot 集成了大量第三方技术,有时候第三方技术发展过快,Spring Boot 集成的版本较低,比如Elastic Search 发展很快,版本迭代到6.7,Spring Boot 2.2 目前只支持到6.5版。

  • Spring Boot 自动装配使得配置简单,但自动装配技术却是一个较为难掌握的技术。

  • Spring Boot 提供了很多技术,但对于企业应用或者互联网来说,有些功能还要进一步增强,比如Spring Boot既提供了一级缓存实现,也提供了二级缓存实现,但并没有提供一个同时支持一、二级缓存的技术实现。

  • Spring Boot 的一些默认启用技术组件并非最优。比如,以日志来说,使用Commons Logging ,但我认为SLF4J更好。再比如REST服务,Spring Boot默认使用JDK自带的HttpURLConnection,也不是最优选择。Spring Boot 使用了Tomcat 作为内置的Web服务器,我认为更好的是Undertow。

我们知道Java有很多日志框架,比如Log4J、Logback、java.util.logging ,同时也有很多日志调用抽象层工具,其中最常用的抽象层工具是Apache的Commons Logging 和 SLF4J。SLF4J支持日志消息参数化被各个公司视为最优的开发实践而推荐使用。

Spring Boot 使用JDK自带的HttpURLConnection实现Rest调用,而高效和功能齐全的OKHttp 并没有被默认使用。

1.3.5 热部署

Spring Boot 应用开发过程可以有多种方式实现热部署,最好通过 spring-boot-devtools工具,在pom.xml 中配置如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

devtools工具会监控classpath上文件变化,包括class、配置文件、模板文件、静态资源,如HTML、devtools默认不会监控静态资源的变化,如果需要设定,可以配置,已经默认配置好的,代码如下:

spring.devtools.restart.exclude=static/**,public/**

在我的项目里,热部署还是非常快的,不到2秒。如果你对热部署时间耗时太长感到不满意,可以考虑尝试使用JRebel ,不过这已经超出了本文的范围。

由于devtools只监控classpath上的变化,因此在Ecipse如果保存Java文件,则会立即触发Eclipse编译,并把编译后的文件同步到classpath里。如果你使用Idea,则需要build整个工程才能生效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值