再見! JSP !

2021-03-02 Java基基

「前段時間,我和一位群友因為要不要學習 JSP 在群裡爭論了一番。他的想法是一定要學,並且還羅列了一個讓我哭笑不得的理由,那就是「學習 JSP 可以加深對Servlet原理的理解!」。當時,我整個人都蒙了,就很氣憤啊!這位群友也是工作一年多的人了,不知道為啥會說出這樣的話。本來準備自己寫一篇文章來回懟,後面看了陳龍大佬也寫了一篇類似的文章,看完之後感覺非常不錯。於是,轉載過來,希望對大家有幫助。

自從在知乎回答問題以來,以及根據最近幾年給企業做技術諮詢的情況,發現 JSP 還是一個經常被提到的問題。希望能在這篇文章裡把關於 JSP 的問題集中說明一下。我的觀點很明確,已經寫在文章標題裡了。

確實,很多初學者,甚至是學了一兩年的 Java 程式設計師還在糾結是否要學 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 了。我現在集中把這些技術因素歸納一下。

一個現代主流 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 是有限制的,看官方文檔怎麼說的:

連結在這裡: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 。

還是看這張圖吧:

右側綠色的部分都是 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 放在哪裡?有兩種方案。

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....把整個微服務應用下的所有@Controller和 JSP 都放在 API Gateway 裡面,其他 Microservice 中只有提供 REST API 的@Controller和@Service。這種方案並不算理想的微服務架構,因為 Gateway 沒有解耦,裡面的所有@Controller不能拆分部署。這樣就相當於在 MicroService 架構下有了一個局部的 Monolithic(單體應用)。

那怎麼才算是使用 Spring Cloud 的正確姿勢?還是看上面那幅圖,這次關注左側三個灰色的部分。IoT(物聯網 Internet of Things)、Mobile(移動應用)、Browser(瀏覽器端),這三個也是應用啊。

我們再看一幅圖:

整個 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 兩種實現,都沒有用伺服器端模板。

同樣的問題。為什麼演示 Spring Cloud 的開發,要引入額外的前端技術?

答案都是同樣的,Spring Cloud 就必須前後端分離開發!用 JSP 就無法完美拆分微服務,無法利用微服務本應帶來的各種優勢。

總結:

我曾經在知乎某一個問題下總結過:現在 JSP 處於被前後端夾擊 的狀態,生存空間越來越小了。就算你不打算管前端,只想在伺服器端有所建樹。微服務的前提也必須前後端分離。

放棄 JSP 吧,讓自己的路走的寬一些。如果死守 JSP 不放,伺服器端只能停留在 SSH/SSM 階段,用 Spring Boot+Spring MVC 已經是你的天花板了。

相關焦點

  • 再見,JSP!!!
    一會是ip0:8081/xxx/xxx.jsp,一會是ip1:8082/xxx/xxx.jsp,點個連接又跳轉到ip2:8080/xxx/xxx.jsp.把整個微服務應用下的所有@Controller和JSP都放在API Gateway裡面,其他Microservice中只有提供REST API的@Controller和@Service。
  • 再見 JSP !
    一會是ip0:8081/xxx/xxx.jsp,一會是ip1:8082/xxx/xxx.jsp,點個連接又跳轉到ip2:8080/xxx/xxx.jsp.把整個微服務應用下的所有@Controller和JSP都放在API Gateway裡面,其他Microservice中只有提供REST API的@Controller和@Service。
  • 使用JSP include機制改進外觀
    JSP 頁以擴展名 .jsp 結尾,這表示要使 SSI 偽指令起作用,必須更改 SSI 配置以解析 JSP 文件(給每個 JSP 頁解析增加開銷),或者更改 JSP 配置以將 .shtml 擴展名作為 JSP 頁處理(這是一個壞主意)。對於 Java 開發人員來說,JSP 技術是***的內容管理解決方案,幸運的是,其 include 機制很容易掌握。
  • JSP標籤含義和用法列表
    < jsp:include>標籤表示包含一個靜態的或者動態的文件。 < jsp:forward>標籤表示重定向一個靜態html/jsp的文件,或者是一個程序段。語法: < jsp:forward page="path"} /> 或< jsp:forward page="path"} > < jsp:param name="paramName" value="paramValue" />…… < /jsp:forward>
  • jsp中使用cookie時報錯……
    今天在看jsp中的cookie時,遇到一個比較麻煩的問題。 關鍵代碼如下: 登錄頁面:login.jsp 處理登錄業務的doLogin.jsp 登錄成功跳轉到的頁面:index.jsp 代碼都寫的沒問題,就是報錯: ava.lang.IllegalArgumentException
  • jsp技術被淘汰了?那還要不要學它?
    一、jsp概述1jsp出現的原因jsp這個技術的出現是為了解決一個什麼問題?先看如下情況:在Java代碼中,伺服器要響應一個HTML頁面給瀏覽器,需要將標籤拼接在代碼中。jsp技術就應運而生了,在jsp文件中,既能寫Java代碼,又能寫HTML代碼,特別地厲害。2jsp定義JSP全名為Java Server Pages,翻譯為java伺服器頁面,其本質是一個簡化的Servlet。
  • JSP/Servlet:Servlet/JSP會話跟蹤機制 (1)
    < %@ page session="false" %> 然後,我們用JSP的標記告訴JSP容器程序要使用PseudoSessionBean: < jsp:useBean id="PseudoSessionId" scope="application" class="pseudosession.PseudoSessionBean"
  • jsp項目運行亂碼?那是編碼沒有改,將Eclipse中jsp文件改為UTF-8
    在執行Eclipse中Jsp項目的時候,總會出現運行亂碼的問題,首先你一定要對中文編碼有所敏感,下面攸攸簡單寫一點,怎樣去修改jsp的默認編碼。在你的Eclipse中新建一個jsp文件的時候,是不是下面這個樣子的,三個編碼都是「ISO-8859-1」。如果你的是這個樣子,那麼請接著向下看。
  • 真的嗎,Java 的 JSP 已經被淘汰了?
    控制層負責接收參數,調用相關業務層,封裝數據,以及路由到jsp頁面。然後jsp頁面上使用各種標籤(jstl/el)或者手寫java(<%=%>)將後臺的數據展現出來。對吧?我們先看這種情況,需求定完了,代碼寫完了,測試測完了,然後呢?要發布了吧?
  • springboot如何做到接口返回JSP頁面
    在application.properties中配置支持jsp8.main文件夾下創建對應jsp文件創建webapp/WEB-INF/jsp/xxx.jsp9.創建繼承SpringBootServletInitializer的子類
  • 曾經風光無限的jsp技術,為什麼現在很少有人用了呢?
    二、jsp的發展既然jsp技術能夠解決剛剛servlet代碼裡面所出現的技術,我們來看一下是如何解決的:在這裡我們舉一個小例子,就是前端jsp向伺服器servlet發送請求圖書頁面的功能。我們只需要把數據交給jsp。此時我們的頁面展示就交給jsp來做了。現在我們來看一下jsp長什麼樣子:這就是jsp,我們可以在html頁面中寫一些java代碼。對於我們程式設計師來說,在開發當中靜態的頁面我們只需要用html和css寫一些標籤來展示即可,對於那些動態的部分我們就可以使用java代碼。
  • 同時,支持JSP技術...
    ,就會在MyEclipse Web Browser中顯示index.jsp的頁面新建JSP文件:點擊WebRoot,右鍵,可以新建jsp頁面。具體步驟:右鍵WebRoot>new>other,選擇MyEclipse>Web>JSP(Basic templates),點擊next,輸入文件名稱,點擊finish;Helloword.jsp文件自動打開,MyEclipse為Helloword.jsp創建了一些標籤,我們可以刪除這些內容,自己重新編寫。
  • jWebBox v2.1 發布,JSP/FreeMaker 服務端布局工具
    -- 或其它版本 -->    <scope>provided</scope>  </dependency>     <dependency>    <groupId>javax.servlet.jsp</groupId>    <artifactId>javax.servlet.jsp-api</artifactId
  • JSP頁面的9個隱含對象實例詳解
    JSP頁面的9個隱含對象實例詳解:pageContext,request,session,applicationout,response,page,configexception 1.在helloworld.jsp頁面中輸入如下代碼:2.在瀏覽器中輸入如下代碼,後邊跟隨的
  • 【免費畢設】jsp+sql作業系統教學網站設計(論文+程序)
    並且在整個網站的過程裡都引入了config.jsp,使得用戶只能通過登陸界面進行登陸,無法直接瀏覽網站。2教學資源版塊的實現通過學院介紹版塊中的<a href="teachersouse.jsp">教學資源teachersouse.jsp也可以通過超連結查看教師簡介,教學設備簡介,
  • JSP Web 開發課程教與學(教學大綱,考核大綱和試卷)
    (C) pageContext request sessionapplication  (D) pageScope requestsessionScope applicationScope 7.在 J2EE 中,在 aa.jsp中有行代碼:<% request.setAttribute(「Co.」,」jb-aptech」); %>
  • 乾貨 | 一文搞懂JSP技術
    (5) 執行jspService()方法處理客戶端的請求。對於每一個請求,JSP容器都會創建個新的線程處理它。如果多個客戶端同時請求該JSP文件,則JSP容器會創建多個線程,使每個客戶請求都對應一個線程。
  • 老成FMS 5.0 發布:多處更新,通用的模板告別拷貝 jsp
    老成 FMS 5.0 版本除了修改以前版本的各種 bug 外,功能增強是最大特色增強 mybatis 的通用 service 功能,增刪改查,事務都支持對象一次性搞定前端 ui 代碼在線生成通用的列表與表單模板,後臺設置參數,告別拷貝 jsp
  • 基於jsp+mysql+Spring+mybatis的SSM在線個人PC電腦商城平臺網站系統
    用了技術框架: HTML+CSS+JavaScript+jsp+mysql+Spring+mybatis+SpringMVCtips: 需要連結資料庫的jsp程序,用到的資料庫保存在源碼碼頭的資料庫平臺上,為了防止童鞋們不注意刪除數據,會每2小時還原一次,有較低的概率在你們演示的時候,剛插入或者剛更新,資料庫就被還原了
  • www.stegd.edu.cn/selfec/login/login.jsp廣東自考報名系統入口
    關注學生自考報名,關注廣東自考相關內容請登小編整理帶來的廣東自考報名入口:www.stegd.edu.cn/selfec/login/login.jsp廣東自考報名系統入口 一、報名條件 http://www.stegd.edu.cn/selfec/login/login.jsp 廣東省自考報名系統http://www.xuecan.net