再见! JSP !

2020-08-17 14:43:24 浏览数 (1)

陈龙|https://zhuanlan.zhihu.com/p/71937497

“前段时间,我和一位群友因为要不要学习 JSP 在群里争论了一番。他的想法是一定要学,并且还罗列了一个让我哭笑不得的理由,那就是“学习 JSP 可以加深对Servlet原理的理解!”。当时,我整个人都蒙了,就很气愤啊!这位群友也是工作一年多的人了,不知道为啥会说出这样的话。 本来准备自己写一篇文章来回怼,后面看了陈龙大佬也写了一篇类似的文章,看完之后感觉非常不错。于是,转载过来,希望对大家有帮助。

自从在知乎回答问题以来,以及根据最近几年给企业做技术咨询的情况,发现 JSP 还是一个经常被提到的问题。希望能在这篇文章里把关于 JSP 的问题集中说明一下。我的观点很明确,已经写在文章标题里了。

确实,很多初学者,甚至是学了一两年的 Java 程序员还在纠结是否要学 JSP。我认为如非工作需要,别学!

还是老规矩,有任何疑问都可以在评论区提出来,有时间我一定会解答。我会把典型问题提取到文章正文里,让更多人看到。有任何错误,包括错字、语句不通顺等问题,敬请指正。

先说一下我自己学习和使用 JSP 的经历吧

我 1998 年开始学习 Java,那时候学校里老师可能听说过 Java,但是同学基本上都不知道 Java。校图书馆进第一批 Java 的书,后面的借阅记录上都是我的名字。当时几乎所有男同学都在学 C 、PB、VB、Delphi,女生很多在学 ASP。所以很多同学问我学的是什么,Java 是干什么的。

大学毕业以后,开始用 Java 做的第一个实际项目是对日外包,是 2001 年。日方有一套很老的系统,想用 Java 重构一下,要求用 JSP。我下班就跑去西单图书大厦,发现那里的书都还是 Servlet 的, 没有 JSP 的!

还好,当时的公司同时进行的一项业务就是代理 BEA 的 Weblogic(BEA 是三个从 SUN 出来的人创建的,后来被 Oracle 收购)。Weblogic 的产品文档里包含非常全面的 JSP 介绍,所以起初对 JSP 的学习都是从 Weblogic 开始的。

那时候还没听说过什么 Struts。自己在 SUN 的官网发现了 WAF 的文档,全称是 Web Application Framework,算是最早 MVC 模式的介绍。这个 WAF 不算是框架,只是介绍了 MVC 模式应该是个什么样子,如何用 Servlet JSP 实现 MVC 模式。SUN 的官网提供了少量的样例代码,剩下的都是我们根据文档自己搭建和实践。

在项目的中后期(02 年下半年吧),有一次坐班车,听到后面座位上两个人在说话。一个人问:你知道 Struts 吗?另外一个人说:不知道。问的那个人说:就是 S T R U T S 这几个字母,开发 Java 的。我偷偷记在心里,然后第二天上网查了一下(当时没有智能机,家里也没有 WIFI),才算开启了 Apache 这扇大门。后来在 ASF 上又学习了 Cocoon、pluto、turbine 等等很多框架。

大概 02 年底,对日外包项目顺利完成了,我公司开始接国内的项目。第一个国内项目是东北一所大学的科研经费审批项目。记得去给人家部署和演示的时候特别有意思。我们用了半天时间在服务器上部署好,然后去给客户演示。打开浏览器,输入 ip 端口,开始操作。操作了十几分钟,所有的客户没有说一个字。越演示心里越没底,不知道客户啥反应。大概又过了几分钟,客户的主任发话了:你们的软件呢?

我们的软件呢?我给你演示了半天,这不就是我们的软件吗?最后才明白,用户认为只有下载一个类似叫 setup.exe 或 install.exe 的程序,双击,然后下一步下一步,最后桌面上出现一个快捷方式,那才算是软件!在经过片刻的不可思议之后,我认为实际用户的理念总是落后于研发人员的理念,这个我很容易想明白。但后来发现,我那些学 PB、Delphi 的师兄弟也不是一时半会能接受 B/S 结构的应用算是软件的...他们认为:你不就是写个网页吗???

再后来,从 03-08 年,长期从事企业应用开发,主要是基于 Weblogic Platform,包括 Server、Integration、Portal,其中在 Portal 上工作的时间最多。

其中 04-05 年用 Weblogic Portal 做深圳市最大的电子政务项目,06-07 年用 Weblogic 平台做广东省电信的 3G 业务平台,08-09 年用 Aqualogic 做南方电网的 SOA。

Weblogic Server 中集成了 Struts,没记错的话当时是 1.1 版本。BEA 把 Struts 做了升级和改造,可以在 Weblogic Workshop 中可视化开发,就是下面这样:

img

其中圆形代表 Action,有 Begin Action,End Action,还有普通的中间节点 Action。BEA 把 Struts 的这个升级称作 Java Page Flow(Java 页面流)。一组这样的图形当中包含的 Action 和 JSP,会定义在一个扩展名是.jpf 的文件中。

后来,BEA 把 JPF 捐献给了 Apache,成为 ASF 下的一个开源项目Apache Beehive。

这个项目现在已经停止更新了。

大概从 06 年开始,接触到了 YUI,也就是 Yahoo User Interface,Yahoo 开源的一套前端 JS 组件库。从此算是开启了我的前端之路。

07-08 年开始用 Extjs,作者说 Ext 就是 Extension(扩展)的意思,扩展了 YUI,提供了更丰富的适合企业开发的前端组件。但这时候,Extjs 还仅仅是丰富的 UI 组件库,算不上框架。就是在 JSP 生成的 HTML 里面嵌入 Extjs 的组件。

09-11 年用 GWT,就是 Google Web Toolkits。Google 当时的想法很先进,用 Java 开发前端 UI,最终编译成 JS。有点类似于现在 TS 编译成 JS 的过程,就是打算利用上 Java 的强类型、面向对象等特点。这时候就已经完全前后端分离了。可以说从 08 年之后我就再也没写过 JSP,一个页面也没写过。

10 年开始用 Bootstrap。这时候 GWT 的缺点就暴露出来了,CSS 非常难改。直到 13 年初,开始用上了 Angularjs。记得当时在智联招聘上发布职位的时候搜了一下,北京市只有用友和我们公司招聘 Angularjs 开发。后来就从 Angularjs 用到 React,又用回 Angular4,一直到现在都以最新版本的 Angular 为主,企业应用和互联网应用都有开发。移动开发主要用 Ionic,React Native 也用过。

为什么要详细介绍我过去和 JSP 以及前端框架相关的开发经历呢?是因为我想表达一个观点:如果要客观公正评价 JSP 是否还有必要用,特别是还有必要学,需要一个真正长期用过 JSP(前后端不分离)开发,也真正长期用前端框架(前后端分离)开发的人才可以。

就像我在有些知乎答案下评论的那样:

遇到这种情况,我总想起福特的名言:“如果我当年去问顾客他们想要什么,他们肯定会告诉我:‘一匹更快的马。’”

满大街跑马车的时代,福特问顾客需要什么,顾客就说需要一匹更快的马。他们不知道汽车时代会给生活带来怎样革命性的变化。

在 BP 机时代,大家认为有人戴 BP 机已经很牛了。满大街诺基亚摩托罗拉功能机的时代,大家也都觉得够用了。问他们需要什么,他们估计会回答:充一次电能不能待机一个月?能不能把自己喜欢的 MP3 当彩铃?

我觉得要对比评价两代产品,应该给两代产品都熟练体验过的人去判断。从功能机时代过来的人,现在 iphone 都已经用到第三部了,你再问他功能机够不够用。就拿一个两代产品都具有的功能(比如都可以 QQ 聊天)对比,你愿意回到功能机时代还是继续用智能机。

一直抱定 JSP 不撒手,没动力、没能力学习前端技术,没有真正理解前后端分离开发模式的人,不可能得出公正全面的评价。

在校期间或参加培训班就学习了前端框架,参加工作后就开始前后端分离的人,也无法理解老人只用 JSP 或用 JSP JS 前端 UI 组件的开发模式是个怎么回事。

上面两种人,据我实际接触中了解,大部分都认为自己的开发模式是理所当然的。就像我之前描述自己刚毕业时候的经历一样。大部分客户和我的一些同学,理所当然认为双击 setup.exe,然后下一步下一步才是软件。而我理所当然认为 B/S 架构的也是软件,只是更便于开发和操作。

JSP 为什么不适合现在的主流开发,为什么正在被抛弃

过去一年多,陆陆续续在知乎上回答了一些关于 JSP 的问题。当然,我的回答都是建议淘汰 JSP,新人小白一定不要再学 JSP 了。我现在集中把这些技术因素归纳一下。

一个现代主流 Java Web 应用,不管前端、后端、还是微服务架构,都在淘汰 JSP。

其中,我认为 Java 服务器端主流技术还是 Spring(Spring Boot Spring MVC Spring Cloud)。

下面三点,第一点几乎尽人皆知,第二点有一部分人清楚,第三点却很少有人意识到。

1.前端框架已经非常成熟和稳定,不需要 JSP

前后端分离已经不是什么趋势了,而是当前 B/S 架构开发的主流模式。前后端分离之后,前端只负责展现和交互,后端负责核心业务逻辑。前后端通过 API 进行交互,并且最好符合 RESTful 风格。服务器端把数据返回给前端就不再关心这些数据用在哪里、如何布局、什么样式。

这个层面的原因非常容易理解,也是绝大多数讨论 JSP 是否还有必要学的时候里都会提到的。

2.服务器端的 Spring MVC/WebFlux 和 Spring Boot 已经开始抛弃 JSP

从 Spring 5 开始,在原有的基于 Servlet 技术的 Spring MVC 之外增加了一个新的编程模型,就是 Spring WebFlux。

Spring WebFlux 是响应式非阻塞的,而且不支持 Servlet API,所以也就不支持 JSP!

img

上图左侧是 Spring 5 新引入的 Spring WebFlux,右侧是大家熟悉的 Spring MVC,两者并列,Spring 同时支持。

关于这一点,可以看 Stack Overflow 上面来自 Spring Framework 和 Spring Boot 团队成员 Brian Clozel 的回答:https://stackoverflow.com/questions/46970379/spring-webflux-no-jsp-support?rq=1

很多人可能又会说了:新的 Spring WebFlux 不支持 JSP,那咱们不用就好了,至少 Spring MVC 还是支持 JSP 的啊。那我们继续看。

如果我们继续使用 Spring Boot Spring MVC 开发,那么 Spring Boot 对 JSP 是有限制的,看官方文档怎么说的:

img

链接在这里:https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-template-engines

其中那行备注:

“If possible, JSPs should be avoided. There are several known limitations when using them with embedded servlet containers. 尽可能避免用 JSP。当使用嵌入式 Servlet 容器时,有一些已知的限制。

关于这些限制和如何继续在 Spring Boot 中使用 JSP,可以自己查一下,知乎里就有好多文章

Spring Boot 对 JSP 有限制,那咱们就凑合用呗,反正我是写 Java 的,我的发展方向是架构师,我正打算学习微服务,正在看 Spring Cloud。那咱们就继续看看 Spring Cloud 吧。

3.微服务架构下更没有 JSP 的用武之地

首先要明白 Spring Boot 和 Spring Cloud 的关系。可以先看我的这个回答:https://www.zhihu.com/question/47304987/answer/627831450 。

还是看这张图吧:

img

右侧绿色的部分都是 Spring Cloud 的组成部分,不管是 API Gateway、Config Dashboard,Service Registry,还是多个 MicroServices,他们都是 Spring Boot 应用!或者说 Spring Boot 是整个 Spring Cloud 的基石(其实也是 Spring Cloud Data Flow 的基石)。

哦,你明白了,因为有 Spring Boot 对 JSP 的限制,而 Spring Cloud 的组成部分都是 Spring Boot 应用,所以 Spring Cloud 也对 JSP 有限制。其实不仅仅是表面上这个原因,咱们继续分析。

如果强行继续在 Spring Cloud 环境中继续使用 JSP,那么 JSP 放在哪里?有两种方案。

  1. API Gateway 和每个 MicroService 里面都有@Controller以及对应的 JSP。那么这种方案下,不同微服务中的 JSP 如何通信?用户访问的时候,同一个应用下的所有 JSP 页面会在不同 IP 和端口下来回变换。一会是http://ip0:8081/xxx/xxx.jsp,一会是http://ip1:8082/xxx/xxx.jsp,点个连接又跳转到http://ip2:8080/xxx/xxx.jsp....
  2. 把整个微服务应用下的所有@Controller和 JSP 都放在 API Gateway 里面,其他 Microservice 中只有提供 REST API 的@Controller@Service。这种方案并不算理想的微服务架构,因为 Gateway 没有解耦,里面的所有@Controller不能拆分部署。这样就相当于在 MicroService 架构下有了一个局部的 Monolithic(单体应用)。

那怎么才算是使用 Spring Cloud 的正确姿势?还是看上面那幅图,这次关注左侧三个灰色的部分。IoT(物联网 Internet of Things)、Mobile(移动应用)、Browser(浏览器端),这三个也是应用啊。

我们再看一幅图:

img

整个 Spring 体系的图出来了。还是看左侧,Your App,也就是 IoT(物联网 Internet of Things)、Mobile(移动应用)、Browser(浏览器端)这三类!

Browser 就是前后端分离之后的前端应用,独立开发、独立部署、只和服务器端有 HTTP RESTful 通信。

我们看看 Spring 官方给出的 Spring Cloud 例子,链接在这里:https://spring.io/projects/spring-cloud#samples 。

customers-stores-ui 是前端应用,用 Angularjs 实现的。例子是便于学习的,不应该引入额外的太多其他技术!为什么 Spring 官方的例子非要用上前端技术?不能只用服务器端开发人员熟悉的模板引擎(包括 JSP)来演示 Spring Cloud 吗?

我们再看另外一个例子,Spring 的 Petclinic 大家都熟悉吧?Spring 官方例子:https://github.com/spring-projects/spring-petclinic 。

官方的是 Monolithic(单体)应用,模板用的是 Thymeleaf,自己去看代码。

用 Spring Cloud 实现的版本:https://github.com/spring-petclinic 。

前端有 Angular 和 React 两种实现,服务器端有 Java 和 Kotlin 两种实现,都没有用服务器端模板。

img

同样的问题。为什么演示 Spring Cloud 的开发,要引入额外的前端技术?

答案都是同样的,Spring Cloud 就必须前后端分离开发!用 JSP 就无法完美拆分微服务,无法利用微服务本应带来的各种优势。

总结:

我曾经在知乎某一个问题下总结过:现在 JSP 处于被前后端夹击的状态,生存空间越来越小了。就算你不打算管前端,只想在服务器端有所建树。微服务的前提也必须前后端分离。

放弃 JSP 吧,让自己的路走的宽一些。如果死守 JSP 不放,服务器端只能停留在 SSH/SSM 阶段,用 Spring Boot Spring MVC 已经是你的天花板了。

0 人点赞